on master help sign in
Create a separate MutByteArray module
commitdc58c595415412edbf00601bae16a28d35269e60 authorHarendra Kumar <harendra@composewell.com> dateSat 25 Nov 2023, 08:10 (3 years ago) parent18f8156
9 files changed+269−246
core/src/Streamly/Internal/Data/Array/Type.hs+1−1 core/src/Streamly/Internal/Data/IORef/Unboxed.hs+3−7 core/src/Streamly/Internal/Data/MutArray/Type.hs+3−3 core/src/Streamly/Internal/Data/MutByteArray.hs+249 core/src/Streamly/Internal/Data/Serialize.hs+4−1 core/src/Streamly/Internal/Data/Serialize/TH/RecHeader.hs+1−1 core/src/Streamly/Internal/Data/Serialize/Type.hs+5−7 core/src/Streamly/Internal/Data/Unbox.hs+2−226 core/streamly-core.cabal+1
core/src/Streamly/Internal/Data/Array/Type.hs+1−1
@@ -121,7 +121,7 @@ import qualified Streamly.Internal.Data.MutArray.Type as MA
121121import qualified Streamly.Internal.Data.Stream.Type as D
122122import qualified Streamly.Internal.Data.Stream.Generate as D
123123import qualified Streamly.Internal.Data.StreamK.Type as K
124−import qualified Streamly.Internal.Data.Unbox as Unboxed
124+import qualified Streamly.Internal.Data.MutByteArray as Unboxed
125125import qualified Streamly.Internal.Data.Unfold.Type as Unfold
126126import qualified Text.ParserCombinators.ReadPrec as ReadPrec
127127
core/src/Streamly/Internal/Data/IORef/Unboxed.hs+3−7
@@ -38,14 +38,10 @@ where
3838
3939#include "inline.hs"
4040
41−import Data.Proxy (Proxy(..))
4241import Control.Monad.IO.Class (MonadIO(..))
43−import Streamly.Internal.Data.Unbox
44− ( MutByteArray(..)
45− , Unbox(..)
46− , newByteArray
47− , sizeOf
48− )
42+import Data.Proxy (Proxy(..))
43+import Streamly.Internal.Data.MutByteArray (MutByteArray(..), newByteArray)
44+import Streamly.Internal.Data.Unbox (Unbox(..), sizeOf)
4945
5046import qualified Streamly.Internal.Data.Stream.Type as D
5147
core/src/Streamly/Internal/Data/MutArray/Type.hs+3−3
@@ -239,14 +239,14 @@ import Data.Proxy (Proxy(..))
239239import Data.Word (Word8)
240240import Foreign.C.Types (CSize(..), CInt(..))
241241import Foreign.Ptr (plusPtr, minusPtr, nullPtr)
242−import Streamly.Internal.Data.Unbox
242+import Streamly.Internal.Data.MutByteArray
243243 ( MutByteArray(..)
244244 , MutableByteArray
245− , Unbox(..)
246245 , PinnedState(..)
247246 , getMutableByteArray#
248247 , putSliceUnsafe
249248 )
249+import Streamly.Internal.Data.Unbox (Unbox(..))
250250import GHC.Base
251251 ( IO(..)
252252 , Int(..)
@@ -266,11 +266,11 @@ import Streamly.Internal.Data.Unfold.Type (Unfold(..))
266266import Streamly.Internal.System.IO (arrayPayloadSize, defaultChunkSize)
267267
268268import qualified Streamly.Internal.Data.Fold.Type as FL
269+import qualified Streamly.Internal.Data.MutByteArray as Unboxed
269270import qualified Streamly.Internal.Data.Producer as Producer
270271import qualified Streamly.Internal.Data.Stream.Type as D
271272import qualified Streamly.Internal.Data.Stream.Lift as D
272273import qualified Streamly.Internal.Data.StreamK.Type as K
273−import qualified Streamly.Internal.Data.Unbox as Unboxed
274274import qualified Prelude
275275
276276import Prelude hiding
core/src/Streamly/Internal/Data/MutByteArray.hsnew file+249
@@ -0,0 +1,249 @@
1+{-# LANGUAGE UnboxedTuples #-}
2+
3+-- |
4+-- Module : Streamly.Internal.Data.MutByteArray
5+-- Copyright : (c) 2023 Composewell Technologies
6+-- License : BSD3-3-Clause
7+-- Maintainer : streamly@composewell.com
8+-- Stability : experimental
9+-- Portability : GHC
10+--
11+module Streamly.Internal.Data.MutByteArray
12+ (
13+ -- ** MutByteArray
14+ MutByteArray(..)
15+ , MutableByteArray
16+ , getMutableByteArray#
17+
18+ -- ** Pinning
19+ , PinnedState(..)
20+ , isPinned
21+ , pin
22+ , unpin
23+
24+ -- ** Allocation
25+ , nil
26+ , newBytesAs
27+ , newByteArray
28+ , pinnedNewByteArray
29+ , pinnedNewAlignedBytes
30+
31+ -- ** Access
32+ , sizeOfMutableByteArray
33+ , putSliceUnsafe
34+ , asPtrUnsafe
35+ ) where
36+
37+import Control.Monad.IO.Class (MonadIO(..))
38+#ifdef DEBUG
39+import Debug.Trace (trace)
40+#endif
41+import GHC.Base (IO(..))
42+import System.IO.Unsafe (unsafePerformIO)
43+
44+import GHC.Exts
45+
46+--------------------------------------------------------------------------------
47+-- The ArrayContents type
48+--------------------------------------------------------------------------------
49+
50+data PinnedState
51+ = Pinned
52+ | Unpinned
53+
54+-- XXX can use UnliftedNewtypes
55+
56+-- | A lifted mutable byte array type wrapping @MutableByteArray# RealWorld@.
57+-- This is a low level array used to back high level unboxed arrays and
58+-- serialized data.
59+data MutByteArray = MutByteArray (MutableByteArray# RealWorld)
60+
61+{-# DEPRECATED MutableByteArray "Please use MutByteArray instead" #-}
62+type MutableByteArray = MutByteArray
63+
64+{-# INLINE getMutableByteArray# #-}
65+getMutableByteArray# :: MutByteArray -> MutableByteArray# RealWorld
66+getMutableByteArray# (MutByteArray mbarr) = mbarr
67+
68+-- | Return the size of the array in bytes.
69+{-# INLINE sizeOfMutableByteArray #-}
70+sizeOfMutableByteArray :: MutByteArray -> IO Int
71+sizeOfMutableByteArray (MutByteArray arr) =
72+ IO $ \s ->
73+ case getSizeofMutableByteArray# arr s of
74+ (# s1, i #) -> (# s1, I# i #)
75+
76+{-# INLINE touch #-}
77+touch :: MutByteArray -> IO ()
78+touch (MutByteArray contents) =
79+ IO $ \s -> case touch# contents s of s' -> (# s', () #)
80+
81+-- XXX We can provide another API for "unsafe" FFI calls passing an unlifted
82+-- pointer to the FFI call. For unsafe calls we do not need to pin the array.
83+-- We can pass an unlifted pointer to the FFI routine to avoid GC kicking in
84+-- before the pointer is wrapped.
85+--
86+-- From the GHC manual:
87+--
88+-- GHC, since version 8.4, guarantees that garbage collection will never occur
89+-- during an unsafe call, even in the bytecode interpreter, and further
90+-- guarantees that unsafe calls will be performed in the calling thread. Making
91+-- it safe to pass heap-allocated objects to unsafe functions.
92+
93+-- | Use a @MutByteArray@ as @Ptr a@. This is useful when we want to pass
94+-- an array as a pointer to some operating system call or to a "safe" FFI call.
95+--
96+-- If the array is not pinned it is copied to pinned memory before passing it
97+-- to the monadic action.
98+--
99+-- /Performance Notes:/ Forces a copy if the array is not pinned. It is advised
100+-- that the programmer keeps this in mind and creates a pinned array
101+-- opportunistically before this operation occurs, to avoid the cost of a copy
102+-- if possible.
103+--
104+-- /Unsafe/ because of direct pointer operations. The user must ensure that
105+-- they are writing within the legal bounds of the array.
106+--
107+-- /Pre-release/
108+--
109+{-# INLINE asPtrUnsafe #-}
110+asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
111+asPtrUnsafe arr f = do
112+ contents <- liftIO $ pin arr
113+ let !ptr = Ptr (byteArrayContents#
114+ (unsafeCoerce# (getMutableByteArray# contents)))
115+ r <- f ptr
116+ liftIO $ touch contents
117+ return r
118+
119+--------------------------------------------------------------------------------
120+-- Creation
121+--------------------------------------------------------------------------------
122+
123+{-# NOINLINE nil #-}
124+nil :: MutByteArray
125+nil = unsafePerformIO $ newByteArray 0
126+
127+{-# INLINE newByteArray #-}
128+newByteArray :: Int -> IO MutByteArray
129+newByteArray nbytes | nbytes < 0 =
130+ errorWithoutStackTrace "newByteArray: size must be >= 0"
131+newByteArray (I# nbytes) = IO $ \s ->
132+ case newByteArray# nbytes s of
133+ (# s', mbarr# #) ->
134+ let c = MutByteArray mbarr#
135+ in (# s', c #)
136+
137+{-# INLINE pinnedNewByteArray #-}
138+pinnedNewByteArray :: Int -> IO MutByteArray
139+pinnedNewByteArray nbytes | nbytes < 0 =
140+ errorWithoutStackTrace "pinnedNewByteArray: size must be >= 0"
141+pinnedNewByteArray (I# nbytes) = IO $ \s ->
142+ case newPinnedByteArray# nbytes s of
143+ (# s', mbarr# #) ->
144+ let c = MutByteArray mbarr#
145+ in (# s', c #)
146+
147+{-# INLINE pinnedNewAlignedBytes #-}
148+pinnedNewAlignedBytes :: Int -> Int -> IO MutByteArray
149+pinnedNewAlignedBytes nbytes _align | nbytes < 0 =
150+ errorWithoutStackTrace "pinnedNewAlignedBytes: size must be >= 0"
151+pinnedNewAlignedBytes (I# nbytes) (I# align) = IO $ \s ->
152+ case newAlignedPinnedByteArray# nbytes align s of
153+ (# s', mbarr# #) ->
154+ let c = MutByteArray mbarr#
155+ in (# s', c #)
156+
157+{-# INLINE newBytesAs #-}
158+newBytesAs :: PinnedState -> Int -> IO MutByteArray
159+newBytesAs Unpinned = newByteArray
160+newBytesAs Pinned = pinnedNewByteArray
161+
162+-------------------------------------------------------------------------------
163+-- Copying
164+-------------------------------------------------------------------------------
165+
166+-- | Put a sub range of a source array into a subrange of a destination array.
167+-- This is not safe as it does not check the bounds.
168+{-# INLINE putSliceUnsafe #-}
169+putSliceUnsafe ::
170+ MonadIO m
171+ => MutByteArray
172+ -> Int
173+ -> MutByteArray
174+ -> Int
175+ -> Int
176+ -> m ()
177+putSliceUnsafe src srcStartBytes dst dstStartBytes lenBytes = liftIO $ do
178+#ifdef DEBUG
179+ srcLen <- sizeOfMutableByteArray src
180+ dstLen <- sizeOfMutableByteArray src
181+ when (srcLen - srcStartBytes < lenBytes) $ error "SRC: Insufficient length."
182+ when (dstLen - dstStartBytes < lenBytes) $ error "DST: Insufficient length."
183+#endif
184+ let !(I# srcStartBytes#) = srcStartBytes
185+ !(I# dstStartBytes#) = dstStartBytes
186+ !(I# lenBytes#) = lenBytes
187+ let arrS# = getMutableByteArray# src
188+ arrD# = getMutableByteArray# dst
189+ IO $ \s# -> (# copyMutableByteArray#
190+ arrS# srcStartBytes# arrD# dstStartBytes# lenBytes# s#
191+ , () #)
192+
193+-------------------------------------------------------------------------------
194+-- Pinning & Unpinning
195+-------------------------------------------------------------------------------
196+
197+{-# INLINE isPinned #-}
198+isPinned :: MutByteArray -> Bool
199+isPinned (MutByteArray arr#) =
200+ let pinnedInt = I# (isMutableByteArrayPinned# arr#)
201+ in pinnedInt /= 0
202+
203+
204+{-# INLINE cloneMutableArrayWith# #-}
205+cloneMutableArrayWith#
206+ :: (Int# -> State# RealWorld -> (# State# RealWorld
207+ , MutableByteArray# RealWorld #))
208+ -> MutableByteArray# RealWorld
209+ -> State# RealWorld
210+ -> (# State# RealWorld, MutableByteArray# RealWorld #)
211+cloneMutableArrayWith# alloc# arr# s# =
212+ case getSizeofMutableByteArray# arr# s# of
213+ (# s1#, i# #) ->
214+ case alloc# i# s1# of
215+ (# s2#, arr1# #) ->
216+ case copyMutableByteArray# arr# 0# arr1# 0# i# s2# of
217+ s3# -> (# s3#, arr1# #)
218+
219+{-# INLINE pin #-}
220+pin :: MutByteArray -> IO MutByteArray
221+pin arr@(MutByteArray marr#) =
222+ if isPinned arr
223+ then return arr
224+ else
225+#ifdef DEBUG
226+ do
227+ -- XXX dump stack trace
228+ trace ("pin: Copying array") (return ())
229+#endif
230+ IO
231+ $ \s# ->
232+ case cloneMutableArrayWith# newPinnedByteArray# marr# s# of
233+ (# s1#, marr1# #) -> (# s1#, MutByteArray marr1# #)
234+
235+{-# INLINE unpin #-}
236+unpin :: MutByteArray -> IO MutByteArray
237+unpin arr@(MutByteArray marr#) =
238+ if not (isPinned arr)
239+ then return arr
240+ else
241+#ifdef DEBUG
242+ do
243+ -- XXX dump stack trace
244+ trace ("unpin: Copying array") (return ())
245+#endif
246+ IO
247+ $ \s# ->
248+ case cloneMutableArrayWith# newByteArray# marr# s# of
249+ (# s1#, marr1# #) -> (# s1#, MutByteArray marr1# #)
core/src/Streamly/Internal/Data/Serialize.hs+4−1
@@ -13,8 +13,10 @@
1313
1414module Streamly.Internal.Data.Serialize
1515 (
16+ -- * MutByteArray
17+ module Streamly.Internal.Data.MutByteArray
1618 -- * Unbox
17− module Streamly.Internal.Data.Unbox
19+ , module Streamly.Internal.Data.Unbox
1820 , module Streamly.Internal.Data.Unbox.TH
1921 -- * Serialize
2022 , module Streamly.Internal.Data.Serialize.Type
@@ -37,6 +39,7 @@ import GHC.Num.Integer (Integer(..))
3739import GHC.Integer.GMP.Internals (Integer(..), BigNat(..))
3840#endif
3941
42+import Streamly.Internal.Data.MutByteArray
4043import Streamly.Internal.Data.Serialize.TH
4144import Streamly.Internal.Data.Serialize.Type
4245import Streamly.Internal.Data.Unbox
core/src/Streamly/Internal/Data/Serialize/TH/RecHeader.hs+1−1
@@ -27,7 +27,7 @@ import Data.Maybe (fromJust)
2727import Language.Haskell.TH
2828import Streamly.Internal.Data.Serialize.Type (Serialize(..))
2929import Data.Foldable (foldlM)
30−import Streamly.Internal.Data.Unbox (MutByteArray)
30+import Streamly.Internal.Data.MutByteArray (MutByteArray)
3131import Data.Proxy (Proxy(..))
3232
3333import qualified Streamly.Internal.Data.Unbox as Unbox
core/src/Streamly/Internal/Data/Serialize/Type.hs+5−7
@@ -27,17 +27,15 @@ import Control.Exception (assert)
2727
2828import Data.List (foldl')
2929import Data.Proxy (Proxy (..))
30−import Streamly.Internal.Data.Unbox
31− ( MutByteArray(..)
32− , PinnedState(..)
33− , Unbox
34− )
30+import Streamly.Internal.Data.Unbox (Unbox)
31+import Streamly.Internal.Data.MutByteArray (MutByteArray(..), PinnedState(..))
3532import Streamly.Internal.Data.Array.Type (Array(..))
3633import Streamly.Internal.System.IO (unsafeInlineIO)
3734import GHC.Int (Int16(..), Int32(..), Int64(..), Int8(..))
3835import GHC.Word (Word16(..), Word32(..), Word64(..), Word8(..))
3936import GHC.Stable (StablePtr(..))
4037
38+import qualified Streamly.Internal.Data.MutByteArray as MBA
4139import qualified Streamly.Internal.Data.Unbox as Unbox
4240import qualified Streamly.Internal.Data.Array as Array
4341import qualified Streamly.Internal.Data.MutArray as MutArray
@@ -297,7 +295,7 @@ instance Serialize (Array a) where
297295 serialize off arr (Array {..}) = do
298296 let arrLen = arrEnd - arrStart
299297 off1 <- serialize off arr arrLen
300− Unbox.putSliceUnsafe arrContents arrStart arr off1 arrLen
298+ MBA.putSliceUnsafe arrContents arrStart arr off1 arrLen
301299 pure (off1 + arrLen)
302300
303301instance (Serialize a, Serialize b) => Serialize (a, b) where
@@ -325,7 +323,7 @@ encodeAs :: forall a. Serialize a => PinnedState -> a -> Array Word8
325323encodeAs ps a =
326324 unsafeInlineIO $ do
327325 let len = size 0 a
328− mbarr <- Unbox.newBytesAs ps len
326+ mbarr <- MBA.newBytesAs ps len
329327 off <- serialize 0 mbarr a
330328 assertM(len == off)
331329 pure $ Array mbarr 0 off
core/src/Streamly/Internal/Data/Unbox.hs+2−226
@@ -13,27 +13,8 @@
1313--
1414module Streamly.Internal.Data.Unbox
1515 (
16− -- ** MutByteArray
17− MutByteArray(..)
18− , MutableByteArray
19− , getMutableByteArray#
20− , sizeOfMutableByteArray
21− , nil
22− , putSliceUnsafe
23− , asPtrUnsafe
24−
25− -- ** Allocation
26− , PinnedState(..)
27− , isPinned
28− , pin
29− , unpin
30− , newBytesAs
31− , newByteArray
32− , pinnedNewByteArray
33− , pinnedNewAlignedBytes
34−
3516 -- ** Unbox type class
36− , Unbox(..)
17+ Unbox(..)
3718
3819 -- ** Peek and poke utilities
3920 , BoundedPtr (..)
@@ -59,7 +40,6 @@ module Streamly.Internal.Data.Unbox
5940#include "MachDeps.h"
6041#include "ArrayMacros.h"
6142
62−import Control.Monad.IO.Class (MonadIO(..))
6343import Control.Monad (void, when)
6444import Data.Complex (Complex((:+)))
6545import Data.Functor ((<&>))
@@ -81,217 +61,13 @@ import GHC.Word (Word16(..), Word32(..), Word64(..), Word8(..))
8161import GHC.RTS.Flags (IoSubSystem(..))
8262#endif
8363import Streamly.Internal.Data.Builder (Builder (..))
84−import System.IO.Unsafe (unsafePerformIO)
8564
8665import GHC.Generics
8766import GHC.Exts
8867import GHC.TypeLits
8968import Prelude hiding (read)
9069
91−--------------------------------------------------------------------------------
92−-- The ArrayContents type
93−--------------------------------------------------------------------------------
94−
95−data PinnedState
96− = Pinned
97− | Unpinned
98−
99−-- XXX can use UnliftedNewtypes
100−
101−-- | A lifted mutable byte array type wrapping @MutableByteArray# RealWorld@.
102−-- This is a low level array used to back high level unboxed arrays and
103−-- serialized data.
104−data MutByteArray = MutByteArray (MutableByteArray# RealWorld)
105−
106−{-# DEPRECATED MutableByteArray "Please use MutByteArray instead" #-}
107−type MutableByteArray = MutByteArray
108−
109−{-# INLINE getMutableByteArray# #-}
110−getMutableByteArray# :: MutByteArray -> MutableByteArray# RealWorld
111−getMutableByteArray# (MutByteArray mbarr) = mbarr
112−
113−-- | Return the size of the array in bytes.
114−{-# INLINE sizeOfMutableByteArray #-}
115−sizeOfMutableByteArray :: MutByteArray -> IO Int
116−sizeOfMutableByteArray (MutByteArray arr) =
117− IO $ \s ->
118− case getSizeofMutableByteArray# arr s of
119− (# s1, i #) -> (# s1, I# i #)
120−
121−{-# INLINE touch #-}
122−touch :: MutByteArray -> IO ()
123−touch (MutByteArray contents) =
124− IO $ \s -> case touch# contents s of s' -> (# s', () #)
125−
126−-- XXX We can provide another API for "unsafe" FFI calls passing an unlifted
127−-- pointer to the FFI call. For unsafe calls we do not need to pin the array.
128−-- We can pass an unlifted pointer to the FFI routine to avoid GC kicking in
129−-- before the pointer is wrapped.
130−--
131−-- From the GHC manual:
132−--
133−-- GHC, since version 8.4, guarantees that garbage collection will never occur
134−-- during an unsafe call, even in the bytecode interpreter, and further
135−-- guarantees that unsafe calls will be performed in the calling thread. Making
136−-- it safe to pass heap-allocated objects to unsafe functions.
137−
138−-- | Use a @MutByteArray@ as @Ptr a@. This is useful when we want to pass
139−-- an array as a pointer to some operating system call or to a "safe" FFI call.
140−--
141−-- If the array is not pinned it is copied to pinned memory before passing it
142−-- to the monadic action.
143−--
144−-- /Performance Notes:/ Forces a copy if the array is not pinned. It is advised
145−-- that the programmer keeps this in mind and creates a pinned array
146−-- opportunistically before this operation occurs, to avoid the cost of a copy
147−-- if possible.
148−--
149−-- /Unsafe/ because of direct pointer operations. The user must ensure that
150−-- they are writing within the legal bounds of the array.
151−--
152−-- /Pre-release/
153−--
154−{-# INLINE asPtrUnsafe #-}
155−asPtrUnsafe :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b
156−asPtrUnsafe arr f = do
157− contents <- liftIO $ pin arr
158− let !ptr = Ptr (byteArrayContents#
159− (unsafeCoerce# (getMutableByteArray# contents)))
160− r <- f ptr
161− liftIO $ touch contents
162− return r
163−
164−--------------------------------------------------------------------------------
165−-- Creation
166−--------------------------------------------------------------------------------
167−
168−{-# NOINLINE nil #-}
169−nil :: MutByteArray
170−nil = unsafePerformIO $ newByteArray 0
171−
172−{-# INLINE newByteArray #-}
173−newByteArray :: Int -> IO MutByteArray
174−newByteArray nbytes | nbytes < 0 =
175− errorWithoutStackTrace "newByteArray: size must be >= 0"
176−newByteArray (I# nbytes) = IO $ \s ->
177− case newByteArray# nbytes s of
178− (# s', mbarr# #) ->
179− let c = MutByteArray mbarr#
180− in (# s', c #)
181−
182−{-# INLINE pinnedNewByteArray #-}
183−pinnedNewByteArray :: Int -> IO MutByteArray
184−pinnedNewByteArray nbytes | nbytes < 0 =
185− errorWithoutStackTrace "pinnedNewByteArray: size must be >= 0"
186−pinnedNewByteArray (I# nbytes) = IO $ \s ->
187− case newPinnedByteArray# nbytes s of
188− (# s', mbarr# #) ->
189− let c = MutByteArray mbarr#
190− in (# s', c #)
191−
192−{-# INLINE pinnedNewAlignedBytes #-}
193−pinnedNewAlignedBytes :: Int -> Int -> IO MutByteArray
194−pinnedNewAlignedBytes nbytes _align | nbytes < 0 =
195− errorWithoutStackTrace "pinnedNewAlignedBytes: size must be >= 0"
196−pinnedNewAlignedBytes (I# nbytes) (I# align) = IO $ \s ->
197− case newAlignedPinnedByteArray# nbytes align s of
198− (# s', mbarr# #) ->
199− let c = MutByteArray mbarr#
200− in (# s', c #)
201−
202−{-# INLINE newBytesAs #-}
203−newBytesAs :: PinnedState -> Int -> IO MutByteArray
204−newBytesAs Unpinned = newByteArray
205−newBytesAs Pinned = pinnedNewByteArray
206−
207−-------------------------------------------------------------------------------
208−-- Copying
209−-------------------------------------------------------------------------------
210−
211−-- | Put a sub range of a source array into a subrange of a destination array.
212−-- This is not safe as it does not check the bounds.
213−{-# INLINE putSliceUnsafe #-}
214−putSliceUnsafe ::
215− MonadIO m
216− => MutByteArray
217− -> Int
218− -> MutByteArray
219− -> Int
220− -> Int
221− -> m ()
222−putSliceUnsafe src srcStartBytes dst dstStartBytes lenBytes = liftIO $ do
223−#ifdef DEBUG
224− srcLen <- sizeOfMutableByteArray src
225− dstLen <- sizeOfMutableByteArray src
226− when (srcLen - srcStartBytes < lenBytes) $ error "SRC: Insufficient length."
227− when (dstLen - dstStartBytes < lenBytes) $ error "DST: Insufficient length."
228−#endif
229− let !(I# srcStartBytes#) = srcStartBytes
230− !(I# dstStartBytes#) = dstStartBytes
231− !(I# lenBytes#) = lenBytes
232− let arrS# = getMutableByteArray# src
233− arrD# = getMutableByteArray# dst
234− IO $ \s# -> (# copyMutableByteArray#
235− arrS# srcStartBytes# arrD# dstStartBytes# lenBytes# s#
236− , () #)
237−
238−-------------------------------------------------------------------------------
239−-- Pinning & Unpinning
240−-------------------------------------------------------------------------------
241−
242−{-# INLINE isPinned #-}
243−isPinned :: MutByteArray -> Bool
244−isPinned (MutByteArray arr#) =
245− let pinnedInt = I# (isMutableByteArrayPinned# arr#)
246− in pinnedInt /= 0
247−
248−
249−{-# INLINE cloneMutableArrayWith# #-}
250−cloneMutableArrayWith#
251− :: (Int# -> State# RealWorld -> (# State# RealWorld
252− , MutableByteArray# RealWorld #))
253− -> MutableByteArray# RealWorld
254− -> State# RealWorld
255− -> (# State# RealWorld, MutableByteArray# RealWorld #)
256−cloneMutableArrayWith# alloc# arr# s# =
257− case getSizeofMutableByteArray# arr# s# of
258− (# s1#, i# #) ->
259− case alloc# i# s1# of
260− (# s2#, arr1# #) ->
261− case copyMutableByteArray# arr# 0# arr1# 0# i# s2# of
262− s3# -> (# s3#, arr1# #)
263−
264−{-# INLINE pin #-}
265−pin :: MutByteArray -> IO MutByteArray
266−pin arr@(MutByteArray marr#) =
267− if isPinned arr
268− then return arr
269− else
270−#ifdef DEBUG
271− do
272− -- XXX dump stack trace
273− trace ("pin: Copying array") (return ())
274−#endif
275− IO
276− $ \s# ->
277− case cloneMutableArrayWith# newPinnedByteArray# marr# s# of
278− (# s1#, marr1# #) -> (# s1#, MutByteArray marr1# #)
279−
280−{-# INLINE unpin #-}
281−unpin :: MutByteArray -> IO MutByteArray
282−unpin arr@(MutByteArray marr#) =
283− if not (isPinned arr)
284− then return arr
285− else
286−#ifdef DEBUG
287− do
288− -- XXX dump stack trace
289− trace ("unpin: Copying array") (return ())
290−#endif
291− IO
292− $ \s# ->
293− case cloneMutableArrayWith# newByteArray# marr# s# of
294− (# s1#, marr1# #) -> (# s1#, MutByteArray marr1# #)
70+import Streamly.Internal.Data.MutByteArray (MutByteArray(..))
29571
29672--------------------------------------------------------------------------------
29773-- The Unbox type class
core/streamly-core.cabal+1
@@ -421,6 +421,7 @@ library
421421 , Streamly.Internal.Data.Array.Type
422422
423423 -- Unboxed IORef
424+ , Streamly.Internal.Data.MutByteArray
424425 , Streamly.Internal.Data.Unbox
425426 , Streamly.Internal.Data.IORef.Unboxed
426427 , Streamly.Internal.Data.Unbox.TH