@@ -17,9 +17,9 @@ module Streamly.Internal.Data.Unbox
1717 MutableByteArray(..)
1818 , getMutableByteArray#
1919 , sizeOfMutableByteArray
20− , touch
2120 , nil
2221 , putSliceUnsafe
22+ , asPtrUnsafe
2323
2424 -- ** Allocation
2525 , PinnedState(..)
@@ -106,11 +106,6 @@ data MutableByteArray = MutableByteArray (MutableByteArray# RealWorld)
106106getMutableByteArray# :: MutableByteArray -> MutableByteArray# RealWorld
107107getMutableByteArray# (MutableByteArray mbarr) = mbarr
108108
109−{-# INLINE touch #-}
110−touch :: MutableByteArray -> IO ()
111−touch (MutableByteArray contents) =
112− IO $ \s -> case touch# contents s of s' -> (# s', () #)
113−
114109-- | Return the size of the array in bytes.
115110{-# INLINE sizeOfMutableByteArray #-}
116111sizeOfMutableByteArray :: MutableByteArray -> IO Int
@@ -119,6 +114,49 @@ sizeOfMutableByteArray (MutableByteArray arr) =
119114 case getSizeofMutableByteArray# arr s of
120115 (# s1, i #) -> (# s1, I# i #)
121116
117+{-# INLINE touch #-}
118+touch :: MutableByteArray -> IO ()
119+touch (MutableByteArray contents) =
120+ IO $ \s -> case touch# contents s of s' -> (# s', () #)
121+
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.
126+--
127+-- From the GHC manual:
128+--
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.
133+
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.
136+--
137+-- If the array is not pinned it is copied to pinned memory before passing it
138+-- to the monadic action.
139+--
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
143+-- if possible.
144+--
145+-- /Unsafe/ because of direct pointer operations. The user must ensure that
146+-- they are writing within the legal bounds of the array.
147+--
148+-- /Pre-release/
149+--
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)))
156+ r <- f ptr
157+ liftIO $ touch contents
158+ return r
159+
122160--------------------------------------------------------------------------------
123161-- Creation
124162--------------------------------------------------------------------------------