@@ -17,9 +17,9 @@ module Streamly.Internal.Data.Unbox
17 MutableByteArray(..)
17 MutableByteArray(..)
18 , getMutableByteArray#
18 , getMutableByteArray#
19 , sizeOfMutableByteArray
19 , sizeOfMutableByteArray
22 , putSliceUnsafe
21 , putSliceUnsafe
24 -- ** Allocation
24 -- ** Allocation
25 , PinnedState(..)
25 , PinnedState(..)
@@ -106,11 +106,6 @@ data MutableByteArray = MutableByteArray (MutableByteArray# RealWorld)
106getMutableByteArray# :: MutableByteArray -> MutableByteArray# RealWorld
106getMutableByteArray# :: MutableByteArray -> MutableByteArray# RealWorld
107getMutableByteArray# (MutableByteArray mbarr) = mbarr
107getMutableByteArray# (MutableByteArray mbarr) = mbarr
110−touch :: MutableByteArray -> IO ()
111−touch (MutableByteArray contents) =
112− IO $ \s -> case touch# contents s of s' -> (# s', () #)
114-- | Return the size of the array in bytes.
109-- | Return the size of the array in bytes.
115{-# INLINE sizeOfMutableByteArray #-}
110{-# INLINE sizeOfMutableByteArray #-}
116sizeOfMutableByteArray :: MutableByteArray -> IO Int
111sizeOfMutableByteArray :: MutableByteArray -> IO Int
@@ -119,6 +114,49 @@ sizeOfMutableByteArray (MutableByteArray arr) =
119 case getSizeofMutableByteArray# arr s of
114 case getSizeofMutableByteArray# arr s of
120 (# s1, i #) -> (# s1, I# i #)
115 (# s1, i #) -> (# s1, I# i #)
118+touch :: MutableByteArray -> IO ()
119+touch (MutableByteArray contents) =
120+ IO $ \s -> case touch# contents s of s' -> (# s', () #)
122+-- XXX We can provide another API for "unsafe" FFI calls passing an unlifted
123+-- pointer to the FFI call. For unsafe calls we do not need to pin the array.
124+-- We can pass an unlifted pointer to the FFI routine to avoid GC kicking in
125+-- before the pointer is wrapped.
127+-- From the GHC manual:
129+-- GHC, since version 8.4, guarantees that garbage collection will never occur
130+-- during an unsafe call, even in the bytecode interpreter, and further
131+-- guarantees that unsafe calls will be performed in the calling thread. Making
132+-- it safe to pass heap-allocated objects to unsafe functions.
134+-- | Use a @MutableByteArray@ as @Ptr a@. This is useful when we want to pass
135+-- an array as a pointer to some operating system call or to a "safe" FFI call.
137+-- If the array is not pinned it is copied to pinned memory before passing it
138+-- to the monadic action.
140+-- /Performance Notes:/ Forces a copy if the array is not pinned. It is advised
141+-- that the programmer keeps this in mind and creates a pinned array
142+-- opportunistically before this operation occurs, to avoid the cost of a copy
145+-- /Unsafe/ because of direct pointer operations. The user must ensure that
146+-- they are writing within the legal bounds of the array.
150+{-# INLINE asPtrUnsafe #-}
151+asPtrUnsafe :: MonadIO m => MutableByteArray -> (Ptr a -> m b) -> m b
152+asPtrUnsafe arr f = do
153+ contents <- liftIO $ pin arr
154+ let !ptr = Ptr (byteArrayContents#
155+ (unsafeCoerce# (getMutableByteArray# contents)))
157+ liftIO $ touch contents
122--------------------------------------------------------------------------------
160--------------------------------------------------------------------------------
123-- Creation
161-- Creation
124--------------------------------------------------------------------------------
162--------------------------------------------------------------------------------