@@ -6,10 +6,8 @@
7module Streamly.Internal.Data.Unboxed
7module Streamly.Internal.Data.Unboxed
8 ( Unbox(..)
8 ( Unbox(..)
10 , peekWith
9 , peekWith
11 , pokeWith
10 , pokeWith
13 , MutableByteArray(..)
11 , MutableByteArray(..)
14 , castContents
12 , castContents
@@ -17,6 +15,7 @@ module Streamly.Internal.Data.Unboxed
19 , newUnpinnedBytes
17 , newUnpinnedBytes
20 , newAlignedPinnedBytes
19 , newAlignedPinnedBytes
@@ -40,7 +39,6 @@ module Streamly.Internal.Data.Unboxed
42#include "MachDeps.h"
41#include "MachDeps.h"
44#include "ArrayMacros.h"
42#include "ArrayMacros.h"
46import Control.Monad (void, when)
44import Control.Monad (void, when)
@@ -51,7 +49,6 @@ import Data.Functor.Identity (Identity(..))
51import Data.Kind (Type)
49import Data.Kind (Type)
52import Data.Proxy (Proxy (..))
50import Data.Proxy (Proxy (..))
53import Foreign.Ptr (IntPtr(..), WordPtr(..))
51import Foreign.Ptr (IntPtr(..), WordPtr(..))
54−import Foreign.Storable (Storable(..))
55import GHC.Base (IO(..))
52import GHC.Base (IO(..))
56import GHC.Fingerprint.Type (Fingerprint(..))
53import GHC.Fingerprint.Type (Fingerprint(..))
57import GHC.Int (Int16(..), Int32(..), Int64(..), Int8(..))
54import GHC.Int (Int16(..), Int32(..), Int64(..), Int8(..))
@@ -115,6 +112,16 @@ newUnpinnedBytes (I# nbytes) = IO $ \s ->
115 let c = MutableByteArray mbarr#
112 let c = MutableByteArray mbarr#
116 in (# s', c #)
113 in (# s', c #)
115+{-# INLINE newPinnedBytes #-}
116+newPinnedBytes :: Int -> IO (MutableByteArray a)
117+newPinnedBytes nbytes | nbytes < 0 =
118+ errorWithoutStackTrace "newPinnedBytes: size must be >= 0"
119+newPinnedBytes (I# nbytes) = IO $ \s ->
120+ case newPinnedByteArray# nbytes s of
122+ let c = MutableByteArray mbarr#
118{-# INLINE newAlignedPinnedBytes #-}
125{-# INLINE newAlignedPinnedBytes #-}
119newAlignedPinnedBytes :: Int -> Int -> IO (MutableByteArray a)
126newAlignedPinnedBytes :: Int -> Int -> IO (MutableByteArray a)
120newAlignedPinnedBytes nbytes _align | nbytes < 0 =
127newAlignedPinnedBytes nbytes _align | nbytes < 0 =
@@ -175,7 +182,6 @@ unpin arr@(MutableByteArray marr#) =
175-- The Unbox type class
182-- The Unbox type class
176--------------------------------------------------------------------------------
183--------------------------------------------------------------------------------
178−-- XXX Remove dependency on Storable
179-- XXX Use Proxy type in sizeOf method.
185-- XXX Use Proxy type in sizeOf method.
180-- XXX generate error if the size is < 1
186-- XXX generate error if the size is < 1
181-- XXX Remove the phantom parameter from MutableByteArray?
187-- XXX Remove the phantom parameter from MutableByteArray?
@@ -208,9 +214,6 @@ unpin arr@(MutableByteArray marr#) =
208-- anymore, see
214-- anymore, see
209-- https://lemire.me/blog/2012/05/31/data-alignment-for-speed-myth-or-reality/
215-- https://lemire.me/blog/2012/05/31/data-alignment-for-speed-myth-or-reality/
211−-- We have to keep the instances compatible with Storable as we depend on it for
212−-- size and alignment. We can possibly write tests for checking compatibility
215-- The main goal of the Unbox type class is to be used in arrays. Invariants
218-- The main goal of the Unbox type class is to be used in arrays. Invariants
216-- for the sizeOf value required for use in arrays:
219-- for the sizeOf value required for use in arrays:
@@ -230,16 +233,6 @@ unpin arr@(MutableByteArray marr#) =
230-- boxed type from the mutable byte array. The write operation 'pokeByteIndex'
233-- boxed type from the mutable byte array. The write operation 'pokeByteIndex'
231-- writes the boxed type to the mutable byte array.
234-- writes the boxed type to the mutable byte array.
233−-- This type class depends on the 'Storable' for 'sizeOf' and 'alignment'
234−-- operations. While 'Storable' supplies the ability to serialize a type to a
235−-- 'Ptr' type, 'Unbox' augments it by supplying the ability to serialize to a
236−-- mutable byte array. The advantage of 'Unbox' over 'Storable' is that we can
237−-- use unpinned memory with 'Unbox'.
239−-- Note: Use the @QuantifiedConstraints@ language extension so that you can
240−-- just use a single 'Unbox' constraint in your code rather than using both
241−-- 'Storable' and 'Unbox'.
243-- Here is an example, to write an instance for this type class.
236-- Here is an example, to write an instance for this type class.
@@ -249,30 +242,11 @@ unpin arr@(MutableByteArray marr#) =
252−-- Note you can leave peek and poke undefined in 'Storable' if you are not
253−-- using the Storable instance, Unbox does not need these operations.
255−-- >>> import Foreign.Ptr (plusPtr, castPtr)
256−-- >>> import Foreign.Storable (Storable(..))
258−-- instance Storable Object where
262−-- let p = castPtr ptr
264−-- x1 <- peek (p `plusPtr` 8)
265−-- return $ Object x0 x1
266−-- poke ptr (Object x0 x1) = do
267−-- let p = castPtr ptr
269−-- poke (p `plusPtr` 8) x1
272-- >>> import Streamly.Data.Array (Unbox(..))
245-- >>> import Streamly.Data.Array (Unbox(..))
273-- >>> import Streamly.Internal.Data.Unboxed (castContents)
246-- >>> import Streamly.Internal.Data.Unboxed (castContents)
275-- instance Unbox Object where
248-- instance Unbox Object where
276-- peekByteIndex arr i = do
250-- peekByteIndex arr i = do
277-- let p = castContents arr
251-- let p = castContents arr
278-- x0 <- peekByteIndex p i
252-- x0 <- peekByteIndex p i
@@ -284,7 +258,9 @@ unpin arr@(MutableByteArray marr#) =
284-- pokeByteIndex p (i + 8) x1
258-- pokeByteIndex p (i + 8) x1
287−class Storable a => Unbox a where
261+class Unbox a where
288 -- | Read an element of type "a" from a MutableByteArray given the byte
264 -- | Read an element of type "a" from a MutableByteArray given the byte
289 -- index.
265 -- index.
@@ -298,7 +274,7 @@ class Storable a => Unbox a where
298 -- of the array, the caller must not assume that.
274 -- of the array, the caller must not assume that.
299 pokeByteIndex :: MutableByteArray a -> Int -> a -> IO ()
275 pokeByteIndex :: MutableByteArray a -> Int -> a -> IO ()
301−#define DERIVE_UNBOXED(_type, _constructor, _readArray, _writeArray) \
277+#define DERIVE_UNBOXED(_type, _constructor, _readArray, _writeArray, _sizeOf) \
302instance Unbox _type where { \
278instance Unbox _type where { \
303; {-# INLINE peekByteIndex #-} \
279; {-# INLINE peekByteIndex #-} \
304; peekByteIndex (MutableByteArray mbarr) (I# n) = IO $ \s -> \
280; peekByteIndex (MutableByteArray mbarr) (I# n) = IO $ \s -> \
@@ -307,14 +283,18 @@ instance Unbox _type where { \
307; {-# INLINE pokeByteIndex #-} \
283; {-# INLINE pokeByteIndex #-} \
308; pokeByteIndex (MutableByteArray mbarr) (I# n) (_constructor val) = \
284; pokeByteIndex (MutableByteArray mbarr) (I# n) (_constructor val) = \
309 IO $ \s -> (# _writeArray mbarr n val s, () #) \
285 IO $ \s -> (# _writeArray mbarr n val s, () #) \
286+; {-# INLINE sizeOf #-} \
287+; sizeOf _ = _sizeOf \
312−#define DERIVE_WRAPPED_UNBOX(_constraint, _type, _constructor) \
290+#define DERIVE_WRAPPED_UNBOX(_constraint, _type, _constructor, _innerType) \
313−instance _constraint Unbox _type where \
291+instance _constraint Unbox _type where \
314−; {-# INLINE peekByteIndex #-} \
292+; {-# INLINE peekByteIndex #-} \
315−; peekByteIndex arr i = _constructor <$> peekByteIndex (castContents arr) i \
293+; peekByteIndex arr i = _constructor <$> peekByteIndex (castContents arr) i \
316−; {-# INLINE pokeByteIndex #-} \
294+; {-# INLINE pokeByteIndex #-} \
317−; pokeByteIndex arr i (_constructor a) = pokeByteIndex (castContents arr) i a
295+; pokeByteIndex arr i (_constructor a) = pokeByteIndex (castContents arr) i a \
296+; {-# INLINE sizeOf #-} \
297+; sizeOf _ = SIZE_OF(_innerType)
319#define DERIVE_BINARY_UNBOX(_constraint, _type, _constructor, _innerType) \
299#define DERIVE_BINARY_UNBOX(_constraint, _type, _constructor, _innerType) \
320instance _constraint Unbox _type where { \
300instance _constraint Unbox _type where { \
@@ -329,100 +309,117 @@ instance _constraint Unbox _type where { \
329 let contents = castContents arr :: MutableByteArray _innerType \
309 let contents = castContents arr :: MutableByteArray _innerType \
330 in pokeByteIndex contents i p1 >> \
310 in pokeByteIndex contents i p1 >> \
331 pokeByteIndex contents (i + SIZE_OF(_innerType)) p2 \
311 pokeByteIndex contents (i + SIZE_OF(_innerType)) p2 \
312+; {-# INLINE sizeOf #-} \
313+; sizeOf _ = 2 * SIZE_OF(_innerType) \
334DERIVE_UNBOXED( Char
316DERIVE_UNBOXED( Char
336 , readWord8ArrayAsWideChar#
318 , readWord8ArrayAsWideChar#
337− , writeWord8ArrayAsWideChar#)
319+ , writeWord8ArrayAsWideChar#
339DERIVE_UNBOXED( Int8
322DERIVE_UNBOXED( Int8
341 , readInt8Array#
324 , readInt8Array#
342− , writeInt8Array#)
325+ , writeInt8Array#
344DERIVE_UNBOXED( Int16
328DERIVE_UNBOXED( Int16
346 , readWord8ArrayAsInt16#
330 , readWord8ArrayAsInt16#
347− , writeWord8ArrayAsInt16#)
331+ , writeWord8ArrayAsInt16#
349DERIVE_UNBOXED( Int32
334DERIVE_UNBOXED( Int32
351 , readWord8ArrayAsInt32#
336 , readWord8ArrayAsInt32#
352− , writeWord8ArrayAsInt32#)
337+ , writeWord8ArrayAsInt32#
354DERIVE_UNBOXED( Int
340DERIVE_UNBOXED( Int
356 , readWord8ArrayAsInt#
342 , readWord8ArrayAsInt#
357− , writeWord8ArrayAsInt#)
343+ , writeWord8ArrayAsInt#
359DERIVE_UNBOXED( Int64
346DERIVE_UNBOXED( Int64
361 , readWord8ArrayAsInt64#
348 , readWord8ArrayAsInt64#
362− , writeWord8ArrayAsInt64#)
349+ , writeWord8ArrayAsInt64#
364DERIVE_UNBOXED( Word
352DERIVE_UNBOXED( Word
366 , readWord8ArrayAsWord#
354 , readWord8ArrayAsWord#
367− , writeWord8ArrayAsWord#)
355+ , writeWord8ArrayAsWord#
369DERIVE_UNBOXED( Word8
358DERIVE_UNBOXED( Word8
371 , readWord8Array#
360 , readWord8Array#
372− , writeWord8Array#)
361+ , writeWord8Array#
374DERIVE_UNBOXED( Word16
364DERIVE_UNBOXED( Word16
376 , readWord8ArrayAsWord16#
366 , readWord8ArrayAsWord16#
377− , writeWord8ArrayAsWord16#)
367+ , writeWord8ArrayAsWord16#
379DERIVE_UNBOXED( Word32
370DERIVE_UNBOXED( Word32
381 , readWord8ArrayAsWord32#
372 , readWord8ArrayAsWord32#
382− , writeWord8ArrayAsWord32#)
373+ , writeWord8ArrayAsWord32#
384DERIVE_UNBOXED( Word64
376DERIVE_UNBOXED( Word64
386 , readWord8ArrayAsWord64#
378 , readWord8ArrayAsWord64#
387− , writeWord8ArrayAsWord64#)
379+ , writeWord8ArrayAsWord64#
389DERIVE_UNBOXED( Double
382DERIVE_UNBOXED( Double
391 , readWord8ArrayAsDouble#
384 , readWord8ArrayAsDouble#
392− , writeWord8ArrayAsDouble#)
385+ , writeWord8ArrayAsDouble#
394DERIVE_UNBOXED( Float
388DERIVE_UNBOXED( Float
396 , readWord8ArrayAsFloat#
390 , readWord8ArrayAsFloat#
397− , writeWord8ArrayAsFloat#)
391+ , writeWord8ArrayAsFloat#
399DERIVE_UNBOXED( (StablePtr a)
394DERIVE_UNBOXED( (StablePtr a)
400 , StablePtr
395 , StablePtr
401 , readWord8ArrayAsStablePtr#
396 , readWord8ArrayAsStablePtr#
402− , writeWord8ArrayAsStablePtr#)
397+ , writeWord8ArrayAsStablePtr#
398+ , SIZEOF_HSSTABLEPTR)
404DERIVE_UNBOXED( (Ptr a)
400DERIVE_UNBOXED( (Ptr a)
406 , readWord8ArrayAsAddr#
402 , readWord8ArrayAsAddr#
407− , writeWord8ArrayAsAddr#)
403+ , writeWord8ArrayAsAddr#
409DERIVE_UNBOXED( (FunPtr a)
406DERIVE_UNBOXED( (FunPtr a)
411 , readWord8ArrayAsAddr#
408 , readWord8ArrayAsAddr#
412− , writeWord8ArrayAsAddr#)
409+ , writeWord8ArrayAsAddr#
414−DERIVE_WRAPPED_UNBOX(,IntPtr,IntPtr)
412+DERIVE_WRAPPED_UNBOX(,IntPtr,IntPtr,Int)
415−DERIVE_WRAPPED_UNBOX(,WordPtr,WordPtr)
413+DERIVE_WRAPPED_UNBOX(,WordPtr,WordPtr,Word)
416−DERIVE_WRAPPED_UNBOX(Unbox a =>,(Identity a),Identity)
414+DERIVE_WRAPPED_UNBOX(Unbox a =>,(Identity a),Identity,a)
417#if MIN_VERSION_base(4,14,0)
415#if MIN_VERSION_base(4,14,0)
418−DERIVE_WRAPPED_UNBOX(Unbox a =>,(Down a),Down)
416+DERIVE_WRAPPED_UNBOX(Unbox a =>,(Down a),Down,a)
420−DERIVE_WRAPPED_UNBOX(Unbox a =>,(Const a b),Const)
418+DERIVE_WRAPPED_UNBOX(Unbox a =>,(Const a b),Const,a)
421DERIVE_BINARY_UNBOX(forall a. Unbox a =>,(Complex a),(:+),a)
419DERIVE_BINARY_UNBOX(forall a. Unbox a =>,(Complex a),(:+),a)
422−DERIVE_BINARY_UNBOX(forall a. (Integral a, Unbox a) =>,(Ratio a),(:%),a)
420+DERIVE_BINARY_UNBOX(forall a. Unbox a =>,(Ratio a),(:%),a)
423DERIVE_BINARY_UNBOX(,Fingerprint,Fingerprint,Word64)
421DERIVE_BINARY_UNBOX(,Fingerprint,Fingerprint,Word64)
425−-- XXX This should have a size 1.
426instance Unbox () where
423instance Unbox () where
428 {-# INLINE peekByteIndex #-}
425 {-# INLINE peekByteIndex #-}
@@ -431,6 +428,9 @@ instance Unbox () where
431 {-# INLINE pokeByteIndex #-}
428 {-# INLINE pokeByteIndex #-}
432 pokeByteIndex _ _ _ = return ()
429 pokeByteIndex _ _ _ = return ()
431+ {-# INLINE sizeOf #-}
434#if MIN_VERSION_base(4,15,0)
434#if MIN_VERSION_base(4,15,0)
435instance Unbox IoSubSystem where
435instance Unbox IoSubSystem where
@@ -439,6 +439,9 @@ instance Unbox IoSubSystem where
440 {-# INLINE pokeByteIndex #-}
440 {-# INLINE pokeByteIndex #-}
441 pokeByteIndex arr i a = pokeByteIndex (castContents arr) i (fromEnum a)
441 pokeByteIndex arr i a = pokeByteIndex (castContents arr) i (fromEnum a)
443+ {-# INLINE sizeOf #-}
444+ sizeOf = sizeOf . fromEnum
444instance Unbox Bool where
447instance Unbox Bool where
@@ -446,13 +449,16 @@ instance Unbox Bool where
446 {-# INLINE peekByteIndex #-}
449 {-# INLINE peekByteIndex #-}
447 peekByteIndex arr i = do
450 peekByteIndex arr i = do
448 res <- peekByteIndex (castContents arr) i
451 res <- peekByteIndex (castContents arr) i
449− return $ res /= (0 :: Int32)
452+ return $ res /= (0 :: Int8)
451 {-# INLINE pokeByteIndex #-}
454 {-# INLINE pokeByteIndex #-}
452 pokeByteIndex arr i a =
455 pokeByteIndex arr i a =
454− then pokeByteIndex (castContents arr) i (1 :: Int32)
457+ then pokeByteIndex (castContents arr) i (1 :: Int8)
455− else pokeByteIndex (castContents arr) i (0 :: Int32)
458+ else pokeByteIndex (castContents arr) i (0 :: Int8)
460+ {-# INLINE sizeOf #-}
457--------------------------------------------------------------------------------
463--------------------------------------------------------------------------------
458-- Functions
464-- Functions