on master help sign in
Update the Unboxed representation

1. Use sizeOf and alignment from Storable 2. Rename readByteArray -> box and writeByteArray -> unbox 3. Rename ArrayContents to MutableByteArray 4. Change the meaning of the typeclass and update the docs accordingly

commite3e60caeaa2984b08ba68a359b436f66dee38bc9 authorAdithya Kumar <adithya@composewell.com> dateThu 11 Aug 2022, 11:45 (4 years ago) parent257a8a2
16 files changed+127−152
core/src/Streamly/Internal/Data/Array/Unboxed.hs+1−2 core/src/Streamly/Internal/Data/Array/Unboxed/Mut/Type.hs+11−11 core/src/Streamly/Internal/Data/Array/Unboxed/Type.hs+2−2 core/src/Streamly/Internal/Data/Fold.hs+3−3 core/src/Streamly/Internal/Data/IORef/Unboxed.hs+4−3 core/src/Streamly/Internal/Data/Ring/Foreign.hs+5−5 core/src/Streamly/Internal/Data/Stream/Eliminate.hs+1−2 core/src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs+3−3 core/src/Streamly/Internal/Data/Time/Units.hs+8−4 core/src/Streamly/Internal/Data/Unboxed.hs+78−102 src/Streamly/Internal/Data/Array/Stream/Foreign.hs+1−1 src/Streamly/Internal/Data/Stream/IsStream/Common.hs+1−2 src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+1−2 src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+3−4 src/Streamly/Internal/Unicode/Stream.hs+4−4 test/Streamly/Test/Prelude/Serial.hs+1−2
core/src/Streamly/Internal/Data/Array/Unboxed.hs+1−2
@@ -134,7 +134,6 @@ import Streamly.Internal.Data.Tuple.Strict (Tuple3Fused'(..))
134134import Streamly.Internal.Data.Unfold.Type (Unfold(..))
135135import Streamly.Internal.System.IO (unsafeInlineIO)
136136
137−import qualified Foreign.Storable as Storable
138137import qualified Streamly.Internal.Data.Array.Unboxed.Mut.Type as MA
139138import qualified Streamly.Internal.Data.Array.Unboxed.Mut as MA
140139import qualified Streamly.Internal.Data.Array.Unboxed.Type as A
@@ -269,7 +268,7 @@ last = getIndexRev 0
269268-- @since 0.8.0
270269{-# INLINE writeLastN #-}
271270writeLastN ::
272− (Unboxed a, Storable.Storable a, MonadIO m) => Int -> Fold m a (Array a)
271+ (Unboxed a, MonadIO m) => Int -> Fold m a (Array a)
273272writeLastN n
274273 | n <= 0 = fmap (const mempty) FL.drain
275274 | otherwise = A.unsafeFreeze <$> Fold step initial done
core/src/Streamly/Internal/Data/Array/Unboxed/Mut/Type.hs+11−11
@@ -17,7 +17,7 @@ module Streamly.Internal.Data.Array.Unboxed.Mut.Type
1717 -- * Type
1818 -- $arrayNotes
1919 Array (..)
20− , ArrayContents
20+ , MutableByteArray
2121 , nilArrayContents
2222 , touch
2323 , pin
@@ -226,7 +226,7 @@ import Data.Word (Word8)
226226import Foreign.C.Types (CSize(..), CInt(..))
227227import Foreign.Ptr (plusPtr, minusPtr, nullPtr)
228228import Streamly.Internal.Data.Unboxed
229− ( ArrayContents(..)
229+ ( MutableByteArray(..)
230230 , Unboxed
231231 , alignment
232232 , castContents
@@ -341,7 +341,7 @@ data Array a =
341341 -- The array is a range into arrContents. arrContents may be a superset of
342342 -- the slice represented by the array. All offsets are in bytes.
343343 Array
344− { arrContents :: {-# UNPACK #-} !(ArrayContents a)
344+ { arrContents :: {-# UNPACK #-} !(MutableByteArray a)
345345 , arrStart :: {-# UNPACK #-} !Int -- ^ index into arrContents
346346 , arrEnd :: {-# UNPACK #-} !Int -- ^ index into arrContents
347347 -- Represents the first invalid index of
@@ -391,7 +391,7 @@ unpin arr@Array{..} = do
391391-- /Pre-release/
392392{-# INLINE newArrayWith #-}
393393newArrayWith :: forall m a. (MonadIO m, Unboxed a)
394− => (Int -> Int -> m (ArrayContents a)) -> Int -> Int -> m (Array a)
394+ => (Int -> Int -> m (MutableByteArray a)) -> Int -> Int -> m (Array a)
395395newArrayWith alloc alignSize count = do
396396 let size = max (count * SIZE_OF(a)) 0
397397 contents <- alloc size alignSize
@@ -405,17 +405,17 @@ newArrayWith alloc alignSize count = do
405405-- XXX Move this to Unboxed and rename this to newPinnedAlignedBytes?
406406-- XXX Similarly have newUnpinnedBytes
407407{-# INLINE newAlignedArrayContents #-}
408−newAlignedArrayContents :: Int -> Int -> IO (ArrayContents a)
408+newAlignedArrayContents :: Int -> Int -> IO (MutableByteArray a)
409409newAlignedArrayContents nbytes _align | nbytes < 0 =
410410 errorWithoutStackTrace "newAlignedArrayContents: size must be >= 0"
411411newAlignedArrayContents (I# nbytes) (I# align) = IO $ \s ->
412412 case newAlignedPinnedByteArray# nbytes align s of
413413 (# s', mbarr# #) ->
414− let c = ArrayContents mbarr#
414+ let c = MutableByteArray mbarr#
415415 in (# s', c #)
416416
417417{-# NOINLINE nilArrayContents #-}
418−nilArrayContents :: ArrayContents a
418+nilArrayContents :: MutableByteArray a
419419nilArrayContents =
420420 unsafePerformIO $ newAlignedArrayContents 0 0
421421
@@ -587,7 +587,7 @@ modify f Array{..} = liftIO $
587587 go (INDEX_NEXT(i,a))
588588
589589{-# INLINE swapArrayByteIndices #-}
590−swapArrayByteIndices :: Unboxed a => ArrayContents a -> Int -> Int -> IO ()
590+swapArrayByteIndices :: Unboxed a => MutableByteArray a -> Int -> Int -> IO ()
591591swapArrayByteIndices arrContents i1 i2 = do
592592 r1 <- peekWith arrContents i1
593593 r2 <- peekWith arrContents i2
@@ -723,8 +723,8 @@ reallocAligned elemSize alignSize newCapacityInBytes Array{..} = do
723723 -- Allocate new array
724724 let newCapMaxInBytes = roundUpLargeArray newCapacityInBytes
725725 contents <- newAlignedArrayContents newCapMaxInBytes alignSize
726− let !(ArrayContents mbarrFrom#) = arrContents
727− !(ArrayContents mbarrTo#) = contents
726+ let !(MutableByteArray mbarrFrom#) = arrContents
727+ !(MutableByteArray mbarrTo#) = contents
728728
729729 -- Copy old data
730730 let oldStart = arrStart
@@ -1421,7 +1421,7 @@ flattenArraysRev (D.Stream step state) = D.Stream step' (OuterLoop state)
14211421-------------------------------------------------------------------------------
14221422
14231423data ArrayUnsafe a = ArrayUnsafe
1424− {-# UNPACK #-} !(ArrayContents a) -- contents
1424+ {-# UNPACK #-} !(MutableByteArray a) -- contents
14251425 {-# UNPACK #-} !Int -- index 1
14261426 {-# UNPACK #-} !Int -- index 2
14271427
core/src/Streamly/Internal/Data/Array/Unboxed/Type.hs+2−2
@@ -85,7 +85,7 @@ import GHC.Exts (IsList, IsString(..))
8585
8686import GHC.IO (unsafePerformIO)
8787import GHC.Ptr (Ptr(..))
88−import Streamly.Internal.Data.Array.Unboxed.Mut.Type (ArrayContents)
88+import Streamly.Internal.Data.Array.Unboxed.Mut.Type (MutableByteArray)
8989import Streamly.Internal.Data.Fold.Type (Fold(..))
9090import Streamly.Internal.Data.Stream.Type (Stream)
9191import Streamly.Internal.Data.Unboxed (Unboxed, peekWith, sizeOf)
@@ -133,7 +133,7 @@ data Array a =
133133#endif
134134 -- All offsets are in terms of bytes from the start of arraycontents
135135 Array
136− { arrContents :: {-# UNPACK #-} !(ArrayContents a)
136+ { arrContents :: {-# UNPACK #-} !(MutableByteArray a)
137137 , arrStart :: {-# UNPACK #-} !Int -- offset
138138 , arrEnd :: {-# UNPACK #-} !Int -- offset + len
139139 }
core/src/Streamly/Internal/Data/Fold.hs+3−3
@@ -306,7 +306,7 @@ import Data.IORef (newIORef, readIORef, writeIORef)
306306import Data.Map.Strict (Map)
307307import Data.Maybe (isJust, fromJust)
308308import Data.Word (Word32)
309−import Foreign.Storable (Storable, peek, sizeOf)
309+import Foreign.Storable (peek, sizeOf)
310310import Streamly.Internal.Data.IsMap (IsMap(..))
311311import Streamly.Internal.Data.Pipe.Type (Pipe (..), PipeState(..))
312312import Streamly.Internal.Data.Unboxed (Unboxed)
@@ -1483,7 +1483,7 @@ data SplitOnSeqState acc a rb rh w ck =
14831483--
14841484-- /Pre-release/
14851485{-# INLINE takeEndBySeq #-}
1486−takeEndBySeq :: forall m a b. (MonadIO m, Storable a, Unboxed a, Enum a, Eq a) =>
1486+takeEndBySeq :: forall m a b. (MonadIO m, Unboxed a, Enum a, Eq a) =>
14871487 Array.Array a
14881488 -> Fold m a b
14891489 -> Fold m a b
@@ -1619,7 +1619,7 @@ takeEndBySeq patArr (Fold fstep finitial fextract) =
16191619-- /Pre-release/
16201620--
16211621{-# INLINE takeEndBySeq_ #-}
1622−takeEndBySeq_ :: forall m a b. (MonadIO m, Storable a, Unboxed a, Enum a, Eq a) =>
1622+takeEndBySeq_ :: forall m a b. (MonadIO m, Unboxed a, Enum a, Eq a) =>
16231623 Array.Array a
16241624 -> Fold m a b
16251625 -> Fold m a b
core/src/Streamly/Internal/Data/IORef/Unboxed.hs+4−3
@@ -40,8 +40,9 @@ where
4040
4141import Control.Monad.IO.Class (MonadIO(..))
4242import Streamly.Internal.Data.Unboxed
43− ( ArrayContents(..)
44− , Unboxed(..)
43+ ( MutableByteArray(..)
44+ , Unboxed
45+ , sizeOf
4546 , peekWith
4647 , pokeWith
4748 , newUnpinnedArrayContents
@@ -50,7 +51,7 @@ import Streamly.Internal.Data.Unboxed
5051import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
5152
5253-- | An 'IORef' holds a single 'Unboxed' value.
53−newtype IORef a = IORef (ArrayContents a)
54+newtype IORef a = IORef (MutableByteArray a)
5455
5556-- | Create a new 'IORef'.
5657--
core/src/Streamly/Internal/Data/Ring/Foreign.hs+5−5
@@ -80,7 +80,7 @@ import Foreign.ForeignPtr (ForeignPtr, withForeignPtr, touchForeignPtr)
8080import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
8181import Foreign.Ptr (plusPtr, minusPtr, castPtr)
8282import Streamly.Internal.Data.Unboxed as Unboxed
83− ( ArrayContents
83+ ( MutableByteArray
8484 , Unboxed
8585 , castContents
8686 , peekWith
@@ -412,7 +412,7 @@ unsafeEqArrayN Ring{..} rh A.Array{..} nBytes
412412
413413 where
414414
415− w8Contents = castContents arrContents :: ArrayContents Word8
415+ w8Contents = castContents arrContents :: MutableByteArray Word8
416416
417417 check p i = do
418418 relem <- peek p
@@ -446,7 +446,7 @@ unsafeEqArray Ring{..} rh A.Array{..} =
446446
447447 where
448448
449− w8Contents = castContents arrContents :: ArrayContents Word8
449+ w8Contents = castContents arrContents :: MutableByteArray Word8
450450
451451 check p i = do
452452 relem <- peek p
@@ -561,7 +561,7 @@ data Tuple4' a b c d = Tuple4' !a !b !c !d deriving Show
561561-- a))@ action depends on when it is executed. It does not capture the sanpshot
562562-- of the ring at a particular time.
563563{-# INLINE slidingWindowWith #-}
564−slidingWindowWith :: forall m a b. (MonadIO m, Storable a, Unboxed a)
564+slidingWindowWith :: forall m a b. (MonadIO m, Unboxed a)
565565 => Int -> Fold m ((a, Maybe a), m (Array a)) b -> Fold m a b
566566slidingWindowWith n (Fold step1 initial1 extract1) = Fold step initial extract
567567
@@ -615,6 +615,6 @@ slidingWindowWith n (Fold step1 initial1 extract1) = Fold step initial extract
615615-- there is no old element.
616616--
617617{-# INLINE slidingWindow #-}
618−slidingWindow :: forall m a b. (MonadIO m, Storable a, Unboxed a)
618+slidingWindow :: forall m a b. (MonadIO m, Unboxed a)
619619 => Int -> Fold m (a, Maybe a) b -> Fold m a b
620620slidingWindow n f = slidingWindowWith n (lmap fst f)
core/src/Streamly/Internal/Data/Stream/Eliminate.hs+1−2
@@ -73,7 +73,6 @@ where
7373import Control.Monad.Catch (MonadThrow)
7474import Control.Monad.IO.Class (MonadIO(..))
7575import Control.Monad.Trans.Class (MonadTrans(..))
76−import Foreign.Storable (Storable)
7776import Streamly.Internal.Data.Parser (Parser (..))
7877import Streamly.Internal.Data.Unboxed (Unboxed)
7978
@@ -284,7 +283,7 @@ isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
284283-- /Requires 'Storable' constraint/
285284--
286285{-# INLINE isInfixOf #-}
287−isInfixOf :: (MonadIO m, Eq a, Enum a, Unboxed a, Storable a)
286+isInfixOf :: (MonadIO m, Eq a, Enum a, Unboxed a)
288287 => Stream m a -> Stream m a -> m Bool
289288isInfixOf infx stream = do
290289 arr <- fold Array.write infx
core/src/Streamly/Internal/Data/Stream/StreamD/Nesting.hs+3−3
@@ -155,7 +155,7 @@ import Control.Monad.IO.Class (MonadIO(..))
155155import Data.Bits (shiftR, shiftL, (.|.), (.&.))
156156import Data.Functor.Identity ( Identity )
157157import Data.Word (Word32)
158−import Foreign.Storable (Storable, peek, sizeOf)
158+import Foreign.Storable (peek, sizeOf)
159159import Fusion.Plugin.Types (Fuse(..))
160160import GHC.Types (SPEC(..))
161161
@@ -1823,7 +1823,7 @@ data SplitOnSeqState rb rh ck w fs s b x =
18231823
18241824{-# INLINE_NORMAL splitOnSeq #-}
18251825splitOnSeq
1826− :: forall m a b. (MonadIO m, Storable a, Unboxed a, Enum a, Eq a)
1826+ :: forall m a b. (MonadIO m, Unboxed a, Enum a, Eq a)
18271827 => Array a
18281828 -> Fold m a b
18291829 -> Stream m a
@@ -2136,7 +2136,7 @@ data SplitOnSuffixSeqState rb rh ck w fs s b x =
21362136
21372137{-# INLINE_NORMAL splitOnSuffixSeq #-}
21382138splitOnSuffixSeq
2139− :: forall m a b. (MonadIO m, Storable a, Unboxed a, Enum a, Eq a)
2139+ :: forall m a b. (MonadIO m, Unboxed a, Enum a, Eq a)
21402140 => Bool
21412141 -> Array a
21422142 -> Fold m a b
core/src/Streamly/Internal/Data/Time/Units.hs+8−4
@@ -51,7 +51,8 @@ where
5151import Text.Printf (printf)
5252
5353import Data.Int
54−import Streamly.Internal.Data.Unboxed (Unboxed)
54+import Foreign.Storable (Storable)
55+import Streamly.Internal.Data.Unboxed (Unbox)
5556import Streamly.Internal.Data.Time.TimeSpec
5657
5758-------------------------------------------------------------------------------
@@ -106,7 +107,8 @@ newtype NanoSecond64 = NanoSecond64 Int64
106107 , Real
107108 , Integral
108109 , Ord
109− , Unboxed
110+ , Storable
111+ , Unbox
110112 )
111113
112114-- | An 'Int64' time representation with a microsecond resolution.
@@ -121,7 +123,8 @@ newtype MicroSecond64 = MicroSecond64 Int64
121123 , Real
122124 , Integral
123125 , Ord
124− , Unboxed
126+ , Storable
127+ , Unbox
125128 )
126129
127130-- | An 'Int64' time representation with a millisecond resolution.
@@ -136,7 +139,8 @@ newtype MilliSecond64 = MilliSecond64 Int64
136139 , Real
137140 , Integral
138141 , Ord
139− , Unboxed
142+ , Storable
143+ , Unbox
140144 )
141145
142146-------------------------------------------------------------------------------
core/src/Streamly/Internal/Data/Unboxed.hs+78−102
@@ -3,11 +3,12 @@
33
44module Streamly.Internal.Data.Unboxed
55 ( Unboxed
6+ , Unbox(..)
67 , alignment
78 , peekWith
89 , pokeWith
910 , sizeOf
10− , ArrayContents(..)
11+ , MutableByteArray(..)
1112 , castContents
1213 , touch
1314 , getMutableByteArray#
@@ -20,10 +21,11 @@ module Streamly.Internal.Data.Unboxed
2021
2122#include "ArrayMacros.h"
2223
23−import Data.Complex (Complex((:+)), realPart)
24+import Data.Complex (Complex((:+)))
2425import GHC.Base (IO(..))
2526import GHC.Int (Int32(..), Int64(..))
2627import GHC.Word (Word8(..), Word64(..))
28+import Foreign.Storable (Storable(..))
2729
2830import GHC.Exts
2931
@@ -32,19 +34,19 @@ import GHC.Exts
3234--------------------------------------------------------------------------------
3335
3436-- XXX can use UnliftedNewtypes
35−data ArrayContents a = ArrayContents !(MutableByteArray# RealWorld)
37+data MutableByteArray a = MutableByteArray !(MutableByteArray# RealWorld)
3638
3739{-# INLINE getMutableByteArray# #-}
38−getMutableByteArray# :: ArrayContents a -> MutableByteArray# RealWorld
39−getMutableByteArray# (ArrayContents mbarr) = mbarr
40+getMutableByteArray# :: MutableByteArray a -> MutableByteArray# RealWorld
41+getMutableByteArray# (MutableByteArray mbarr) = mbarr
4042
4143{-# INLINE castContents #-}
42−castContents :: ArrayContents a -> ArrayContents b
43−castContents (ArrayContents mbarr) = ArrayContents mbarr
44+castContents :: MutableByteArray a -> MutableByteArray b
45+castContents (MutableByteArray mbarr) = MutableByteArray mbarr
4446
4547{-# INLINE touch #-}
46−touch :: ArrayContents a -> IO ()
47−touch (ArrayContents contents) =
48+touch :: MutableByteArray a -> IO ()
49+touch (MutableByteArray contents) =
4850 IO $ \s -> case touch# contents s of s' -> (# s', () #)
4951
5052--------------------------------------------------------------------------------
@@ -52,13 +54,13 @@ touch (ArrayContents contents) =
5254--------------------------------------------------------------------------------
5355
5456{-# INLINE newUnpinnedArrayContents #-}
55−newUnpinnedArrayContents :: Int -> IO (ArrayContents a)
57+newUnpinnedArrayContents :: Int -> IO (MutableByteArray a)
5658newUnpinnedArrayContents nbytes | nbytes < 0 =
5759 errorWithoutStackTrace "newUnpinnedArrayContents: size must be >= 0"
5860newUnpinnedArrayContents (I# nbytes) = IO $ \s ->
5961 case newByteArray# nbytes s of
6062 (# s', mbarr# #) ->
61− let c = ArrayContents mbarr#
63+ let c = MutableByteArray mbarr#
6264 in (# s', c #)
6365
6466-------------------------------------------------------------------------------
@@ -66,8 +68,8 @@ newUnpinnedArrayContents (I# nbytes) = IO $ \s ->
6668-------------------------------------------------------------------------------
6769
6870{-# INLINE isPinned #-}
69−isPinned :: ArrayContents a -> Bool
70−isPinned (ArrayContents arr#) =
71+isPinned :: MutableByteArray a -> Bool
72+isPinned (MutableByteArray arr#) =
7173 let pinnedInt = I# (isMutableByteArrayPinned# arr#)
7274 in pinnedInt == 1
7375
@@ -88,24 +90,24 @@ cloneMutableArrayWith# alloc# arr# s# =
8890 s3# -> (# s3#, arr1# #)
8991
9092{-# INLINE pin #-}
91−pin :: ArrayContents a -> IO (ArrayContents a)
92−pin arr@(ArrayContents marr#) =
93+pin :: MutableByteArray a -> IO (MutableByteArray a)
94+pin arr@(MutableByteArray marr#) =
9395 if isPinned arr
9496 then return arr
9597 else IO
9698 $ \s# ->
9799 case cloneMutableArrayWith# newPinnedByteArray# marr# s# of
98− (# s1#, marr1# #) -> (# s1#, ArrayContents marr1# #)
100+ (# s1#, marr1# #) -> (# s1#, MutableByteArray marr1# #)
99101
100102{-# INLINE unpin #-}
101−unpin :: ArrayContents a -> IO (ArrayContents a)
102−unpin arr@(ArrayContents marr#) =
103+unpin :: MutableByteArray a -> IO (MutableByteArray a)
104+unpin arr@(MutableByteArray marr#) =
103105 if not (isPinned arr)
104106 then return arr
105107 else IO
106108 $ \s# ->
107109 case cloneMutableArrayWith# newByteArray# marr# s# of
108− (# s1#, marr1# #) -> (# s1#, ArrayContents marr1# #)
110+ (# s1#, marr1# #) -> (# s1#, MutableByteArray marr1# #)
109111
110112--------------------------------------------------------------------------------
111113-- The Unboxed type class
@@ -225,14 +227,16 @@ writeWord8ArrayAsDouble# arr# i# =
225227-- class allows each primitive type to have its own specific efficient
226228-- implementation to read and write the type to memory.
227229--
228−-- The ArrayContents type currently uses a MutableByteArray#. However, we could
229−-- also use a foreign ptr instead. That would just make the implementation a
230−-- bit more complicated. In that case the type class would have to support
231−-- reading and writing to a Ptr as well, basically what Storable does. We will
232−-- also need to touch the anchoring ptr at the right points which is prone to
233−-- errors. However, it should be simple to implement unmanaged/read-only memory
234−-- arrays by allowing a Ptr type in ArrayContents, though it would require all
235−-- instances to support reading from a Ptr.
230+-- This is a typeclass that uses MutableByteArray but could use ForeignPtr or
231+-- any other representation of memory. We could make this a multiparameter type
232+-- class if necessary.
233+--
234+-- If the type class would have to support reading and writing to a Ptr as well,
235+-- basically what Storable does. We will also need to touch the anchoring ptr at
236+-- the right points which is prone to errors. However, it should be simple to
237+-- implement unmanaged/read-only memory arrays by allowing a Ptr type in
238+-- ArrayContents, though it would require all instances to support reading from
239+-- a Ptr.
236240--
237241-- There is a reason for using byte offset instead of element index in read and
238242-- write operations in the type class. If we use element index slicing of the
@@ -245,144 +249,116 @@ writeWord8ArrayAsDouble# arr# i# =
245249-- anymore, see
246250-- https://lemire.me/blog/2012/05/31/data-alignment-for-speed-myth-or-reality/
247251--
248−-- We try to keep the instances compatible with Storable. But we may have to
249−-- differ, for example a Bool instance can be implemented more efficiently
250−-- using a bit vector. Need to check the performance. We can possibly write
251−-- tests for checking compatibility with Storable.
252+-- We have to keep the instances compatible with Storable as we depend on it for
253+-- size and alignment. We can possibly write tests for checking compatibility
254+-- with Storable.
252255
253−-- | An 'Unboxed' type supplies operations for reading and writing the type
256+-- | An 'Unbox' type supplies operations for reading and writing the type
254257-- from and to a byte array in memory. The read operation constructs the boxed
255258-- type from an unboxed byte representation in memory. The write operation
256259-- writes the boxed type to an unboxed byte representation in memory.
257260--
258−-- This type class is similar to Storable. While Storable allows writing to a
259−-- Ptr, this type class allows writing to a MutableByteArray#.
260−class Unboxed a where
261− sizeOf :: a -> Int
262− alignment :: a -> Int
263−
264− -- Read an element of type "a" from a MutableByteArray given the byte
261+-- This type class dependes on Storable for size and alignment of the type. It
262+-- is similar to Storable in the sense that it has corresponding operations for
263+-- peekByteOff and pokeByteOff. While Storable allows writing to a Ptr, this
264+-- type class allows writing to a MutableByteArray#.
265+class Storable a => Unbox a where
266+ -- | Read an element of type "a" from a MutableByteArray given the byte
265267 -- index.
266− readByteArray :: ArrayContents a -> Int -> IO a
267− writeByteArray :: ArrayContents a -> Int -> a -> IO ()
268−
269−#define DERIVE_UNBOXED(_type, _constructor, _sizeOf, _alignment, _readArray, _writeArray) \
270−instance Unboxed _type where { \
271−; {-# INLINE sizeOf #-} \
272−; sizeOf _ = _sizeOf \
273−; {-# INLINE alignment #-} \
274−; alignment _ = _alignment \
275−; {-# INLINE readByteArray #-} \
276−; readByteArray (ArrayContents mbarr) (I# n) = IO $ \s -> \
268+ box :: MutableByteArray a -> Int -> IO a
269+ -- | Write an element of type "a" to a MutableByteArray given the byte
270+ -- index.
271+ unbox :: MutableByteArray a -> Int -> a -> IO ()
272+
273+type Unboxed a = (Unbox a, Storable a)
274+
275+#define DERIVE_UNBOXED(_type, _constructor, _readArray, _writeArray) \
276+instance Unbox _type where { \
277+; {-# INLINE box #-} \
278+; box (MutableByteArray mbarr) (I# n) = IO $ \s -> \
277279 case _readArray mbarr n s of \
278280 { (# s1, i #) -> (# s1, _constructor i #) } \
279−; {-# INLINE writeByteArray #-} \
280−; writeByteArray (ArrayContents mbarr) (I# n) (_constructor val) = \
281+; {-# INLINE unbox #-} \
282+; unbox (MutableByteArray mbarr) (I# n) (_constructor val) = \
281283 IO $ \s -> (# _writeArray mbarr n val s, () #) \
282284}
283285
284286DERIVE_UNBOXED( Char
285287 , C#
286− , SIZEOF_HSCHAR
287− , ALIGNMENT_HSCHAR
288288 , readWord8ArrayAsWideChar#
289289 , writeWord8ArrayAsWideChar#)
290290
291291DERIVE_UNBOXED( Int32
292292 , I32#
293− , SIZEOF_INT32
294− , ALIGNMENT_INT32
295293 , readWord8ArrayAsInt32#
296294 , writeWord8ArrayAsInt32#)
297295
298296DERIVE_UNBOXED( Int
299297 , I#
300− , SIZEOF_HSINT
301− , ALIGNMENT_HSINT
302298 , readWord8ArrayAsInt#
303299 , writeWord8ArrayAsInt#)
304300
305301DERIVE_UNBOXED( Int64
306302 , I64#
307− , SIZEOF_INT64
308− , ALIGNMENT_INT64
309303 , readWord8ArrayAsInt64#
310304 , writeWord8ArrayAsInt64#)
311305
312306DERIVE_UNBOXED( Word
313307 , W#
314− , SIZEOF_HSWORD
315− , ALIGNMENT_HSWORD
316308 , readWord8ArrayAsWord#
317309 , writeWord8ArrayAsWord#)
318310
319311DERIVE_UNBOXED( Word8
320312 , W8#
321− , SIZEOF_WORD8
322− , ALIGNMENT_WORD8
323313 , readWord8Array#
324314 , writeWord8Array#)
325315
326316DERIVE_UNBOXED( Word64
327317 , W64#
328− , SIZEOF_WORD64
329− , ALIGNMENT_WORD64
330318 , readWord8ArrayAsWord64#
331319 , writeWord8ArrayAsWord64#)
332320
333321DERIVE_UNBOXED( Double
334322 , D#
335− , SIZEOF_DOUBLE
336− , ALIGNMENT_DOUBLE
337323 , readWord8ArrayAsDouble#
338324 , writeWord8ArrayAsDouble#)
339325
340−instance Unboxed Bool where
341− {-# INLINE sizeOf #-}
342− sizeOf _ = sizeOf (undefined :: Word8)
343−
344− {-# INLINE alignment #-}
345− alignment _ = alignment (undefined :: Word8)
326+instance Unbox Bool where
346327
347− {-# INLINE readByteArray #-}
348− readByteArray arr i = do
349− res <- readByteArray (castContents arr) i
350− return $ res /= (0 :: Word8)
328+ {-# INLINE box #-}
329+ box arr i = do
330+ res <- box (castContents arr) i
331+ return $ res /= (0 :: Int32)
351332
352− {-# INLINE writeByteArray #-}
353− writeByteArray arr i a =
333+ {-# INLINE unbox #-}
334+ unbox arr i a =
354335 if a
355− then writeByteArray (castContents arr) i (1 :: Word8)
356− else writeByteArray (castContents arr) i (0 :: Word8)
357−
358−instance forall a. Unboxed a => Unboxed (Complex a) where
359− {-# INLINE sizeOf #-}
360− sizeOf a = 2 * sizeOf (realPart a)
336+ then unbox (castContents arr) i (1 :: Int32)
337+ else unbox (castContents arr) i (0 :: Int32)
361338
362− {-# INLINE alignment #-}
363− alignment a = alignment (realPart a)
339+instance forall a. Unboxed a => Unbox (Complex a) where
364340
365− {-# INLINE readByteArray #-}
366− readByteArray arr i = do
367− let contents = castContents arr :: ArrayContents a
368− real <- readByteArray contents i
369− img <- readByteArray contents (i + SIZE_OF(a))
341+ {-# INLINE box #-}
342+ box arr i = do
343+ let contents = castContents arr :: MutableByteArray a
344+ real <- box contents i
345+ img <- box contents (i + SIZE_OF(a))
370346 return $ real :+ img
371347
372− {-# INLINE writeByteArray #-}
373− writeByteArray arr i (real :+ img) = do
374− let contents = castContents arr :: ArrayContents a
375− writeByteArray contents i real
376− writeByteArray contents (i + SIZE_OF(a)) img
348+ {-# INLINE unbox #-}
349+ unbox arr i (real :+ img) = do
350+ let contents = castContents arr :: MutableByteArray a
351+ unbox contents i real
352+ unbox contents (i + SIZE_OF(a)) img
377353
378354--------------------------------------------------------------------------------
379355-- Functions
380356--------------------------------------------------------------------------------
381357
382358{-# INLINE peekWith #-}
383−peekWith :: Unboxed a => ArrayContents a -> Int -> IO a
384−peekWith = readByteArray
359+peekWith :: Unboxed a => MutableByteArray a -> Int -> IO a
360+peekWith = box
385361
386362{-# INLINE pokeWith #-}
387−pokeWith :: Unboxed a => ArrayContents a -> Int -> a -> IO ()
388−pokeWith = writeByteArray
363+pokeWith :: Unboxed a => MutableByteArray a -> Int -> a -> IO ()
364+pokeWith = unbox
src/Streamly/Internal/Data/Array/Stream/Foreign.hs+1−1
@@ -170,7 +170,7 @@ interposeSuffix x = S.interposeSuffix x A.read
170170
171171data FlattenState s a =
172172 OuterLoop s
173− | InnerLoop s !(MA.ArrayContents a) !Int !Int
173+ | InnerLoop s !(MA.MutableByteArray a) !Int !Int
174174
175175-- XXX Remove monadIO constraint
176176{-# INLINE_NORMAL unlines #-}
src/Streamly/Internal/Data/Stream/IsStream/Common.hs+1−2
@@ -69,7 +69,6 @@ where
6969
7070import Control.Concurrent (threadDelay)
7171import Control.Monad.IO.Class (MonadIO(..))
72−import qualified Foreign.Storable as Storable (Storable)
7372import Streamly.Internal.Control.Concurrent (MonadAsync)
7473import Streamly.Internal.Data.Array.Unboxed.Type (Array)
7574import Streamly.Internal.Data.Fold.Type (Fold (..))
@@ -673,7 +672,7 @@ foldManyPost f m = fromStreamD $ D.foldManyPost f (toStreamD m)
673672-- that we can search files in files for example.
674673{-# INLINE splitOnSeq #-}
675674splitOnSeq
676− :: (IsStream t, MonadIO m, Storable.Storable a, Unboxed a, Enum a, Eq a)
675+ :: (IsStream t, MonadIO m, Unboxed a, Enum a, Eq a)
677676 => Array a -> Fold m a b -> t m a -> t m b
678677splitOnSeq patt f m =
679678 IsStream.fromStreamD $ D.splitOnSeq patt f (IsStream.toStreamD m)
src/Streamly/Internal/Data/Stream/IsStream/Eliminate.hs+1−2
@@ -156,7 +156,6 @@ where
156156
157157import Control.Monad.IO.Class (MonadIO(..))
158158import Control.Monad.Trans.Class (MonadTrans(..))
159−import qualified Foreign.Storable as Storable (Storable)
160159import Streamly.Internal.Control.Concurrent (MonadAsync)
161160import Streamly.Internal.Data.SVar (defState)
162161import Streamly.Internal.Data.Stream.IsStream.Common
@@ -841,7 +840,7 @@ isPrefixOf m1 m2 = D.isPrefixOf (toStreamD m1) (toStreamD m2)
841840-- /Requires 'Storable' constraint/
842841--
843842{-# INLINE isInfixOf #-}
844−isInfixOf :: (MonadIO m, Eq a, Enum a, Storable.Storable a, Unboxed a)
843+isInfixOf :: (MonadIO m, Eq a, Enum a, Unboxed a)
845844 => SerialT m a -> SerialT m a -> m Bool
846845isInfixOf infx stream = do
847846 arr <- fold A.write infx
src/Streamly/Internal/Data/Stream/IsStream/Reduce.hs+3−4
@@ -157,7 +157,6 @@ import Data.Kind (Type)
157157import Data.Map (Map)
158158import Data.Maybe (isNothing)
159159import Data.Proxy (Proxy(..))
160−import qualified Foreign.Storable as Storable (Storable)
161160import Streamly.Internal.Control.Concurrent (MonadAsync)
162161import Streamly.Internal.Data.Fold.Type (Fold (..))
163162import Streamly.Internal.Data.IsMap (IsMap(..))
@@ -824,7 +823,7 @@ splitOnAny _subseq _f _m =
824823-- /Pre-release/
825824{-# INLINE splitBySeq #-}
826825splitBySeq
827− :: (IsStream t, MonadAsync m, Storable.Storable a, Unboxed a, Enum a, Eq a)
826+ :: (IsStream t, MonadAsync m, Unboxed a, Enum a, Eq a)
828827 => Array a -> Fold m a b -> t m a -> t m b
829828splitBySeq patt f m =
830829 intersperseM (fold f (A.toStream patt)) $ splitOnSeq patt f m
@@ -875,7 +874,7 @@ splitBySeq patt f m =
875874-- /Pre-release/
876875{-# INLINE splitOnSuffixSeq #-}
877876splitOnSuffixSeq
878− :: (IsStream t, MonadIO m, Storable.Storable a, Unboxed a, Enum a, Eq a)
877+ :: (IsStream t, MonadIO m, Unboxed a, Enum a, Eq a)
879878 => Array a -> Fold m a b -> t m a -> t m b
880879splitOnSuffixSeq patt f m =
881880 fromStreamD $ D.splitOnSuffixSeq False patt f (toStreamD m)
@@ -927,7 +926,7 @@ wordsOn _subseq _f _m =
927926-- /Pre-release/
928927{-# INLINE splitWithSuffixSeq #-}
929928splitWithSuffixSeq
930− :: (IsStream t, MonadIO m, Storable.Storable a, Unboxed a, Enum a, Eq a)
929+ :: (IsStream t, MonadIO m, Unboxed a, Enum a, Eq a)
931930 => Array a -> Fold m a b -> t m a -> t m b
932931splitWithSuffixSeq patt f m =
933932 fromStreamD $ D.splitOnSuffixSeq True patt f (toStreamD m)
src/Streamly/Internal/Unicode/Stream.hs+4−4
@@ -102,7 +102,7 @@ import GHC.IO.Encoding.Failure (isSurrogate)
102102import GHC.Ptr (Ptr (..), plusPtr)
103103import System.IO.Unsafe (unsafePerformIO)
104104import Streamly.Internal.Data.Array.Unboxed (Array)
105−import Streamly.Internal.Data.Array.Unboxed.Mut.Type (ArrayContents)
105+import Streamly.Internal.Data.Array.Unboxed.Mut.Type (MutableByteArray)
106106import Streamly.Internal.Data.Fold (Fold)
107107import Streamly.Internal.Data.Stream.IsStream.Type
108108 (IsStream, fromStreamD, toStreamD, adapt)
@@ -703,9 +703,9 @@ decodeUtf8Lax = decodeUtf8
703703#endif
704704data FlattenState s a
705705 = OuterLoop s !(Maybe (DecodeState, CodePoint))
706− | InnerLoopDecodeInit s (ArrayContents a) !Int !Int
707− | InnerLoopDecodeFirst s (ArrayContents a) !Int !Int Word8
708− | InnerLoopDecoding s (ArrayContents a) !Int !Int
706+ | InnerLoopDecodeInit s (MutableByteArray a) !Int !Int
707+ | InnerLoopDecodeFirst s (MutableByteArray a) !Int !Int Word8
708+ | InnerLoopDecoding s (MutableByteArray a) !Int !Int
709709 !DecodeState !CodePoint
710710 | YAndC !Char (FlattenState s a) -- These constructors can be
711711 -- encoded in the UTF8DecodeState
test/Streamly/Test/Prelude/Serial.hs+1−2
@@ -21,7 +21,6 @@ import Data.Word (Word8)
2121import Data.Semigroup ((<>))
2222#endif
2323import Data.Semigroup (Sum(..), getSum)
24−import Foreign.Storable (Storable)
2524import Streamly.Internal.Data.Unboxed (Unboxed)
2625import Test.Hspec.QuickCheck
2726import Test.QuickCheck
@@ -113,7 +112,7 @@ splitOnSuffixSeq = do
113112 $ IS.splitOnSuffixSeq (A.fromList pat) FL.toList (S.fromList xs)
114113
115114splitterProperties ::
116− forall a. (Arbitrary a, Eq a, Show a, Storable a, Unboxed a, Enum a)
115+ forall a. (Arbitrary a, Eq a, Show a, Unboxed a, Enum a)
117116 => a
118117 -> String
119118 -> Spec