on master help sign in
Rename, update docs of array creation from ptr
cc072beHarendra Kumar
src/Streamly/Internal/Memory/Array.hs+5−2
@@ -40,9 +40,12 @@ module Streamly.Internal.Memory.Array
40
40
41 -- * Construction
41 -- * Construction
42
42
43− -- Foreign (Unsafe)
43+ -- Pure, From Static Memory (Unsafe)
44+ -- We can use fromPtrM#, fromCStringM# and fromAddrM# to create arrays from
45+ -- a dynamic memory address which requires a finalizer.
46+ , A.fromPtr
44 , A.fromAddr#
47 , A.fromAddr#
45− , A.fromString#
48+ , A.fromCString#
46
49
47 -- Pure List APIs
50 -- Pure List APIs
48 , A.fromListN
51 , A.fromListN
src/Streamly/Internal/Memory/Array/Types.hs+51−42
@@ -21,8 +21,9 @@ module Streamly.Internal.Memory.Array.Types
21 -- * Construction
21 -- * Construction
22 , spliceTwo
22 , spliceTwo
23
23
24+ , fromPtr
24 , fromAddr#
25 , fromAddr#
25− , fromString#
26+ , fromCString#
26 , fromList
27 , fromList
27 , fromListN
28 , fromListN
28 , fromStreamDN
29 , fromStreamDN
@@ -86,7 +87,6 @@ import Control.Monad.IO.Class (MonadIO(..))
86import Data.Word (Word8)
87import Data.Word (Word8)
87import Foreign.C.String (CString)
88import Foreign.C.String (CString)
88import Foreign.C.Types (CSize(..))
89import Foreign.C.Types (CSize(..))
89−import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
90import Foreign.Ptr (plusPtr, castPtr)
90import Foreign.Ptr (plusPtr, castPtr)
91import Foreign.Storable (Storable(..))
91import Foreign.Storable (Storable(..))
92import GHC.Base (Addr#, nullAddr#)
92import GHC.Base (Addr#, nullAddr#)
@@ -217,6 +217,30 @@ spliceTwo :: (MonadIO m, Storable a) => Array a -> Array a -> m (Array a)
217spliceTwo arr1 arr2 =
217spliceTwo arr1 arr2 =
218 unsafeFreeze <$> MA.spliceTwo (unsafeThaw arr1) (unsafeThaw arr2)
218 unsafeFreeze <$> MA.spliceTwo (unsafeThaw arr1) (unsafeThaw arr2)
219
219
220+-- | Create an 'Array' of the given number of elements of type @a@ from a read
221+-- only pointer @Ptr a@. The pointer is not freed when the array is garbage
222+-- collected. This API is unsafe for the following reasons:
223+--
224+-- 1. The pointer must point to static pinned memory or foreign memory that
225+-- does not require freeing..
226+-- 2. The pointer must be legally accessible upto the given length.
227+-- 3. To guarantee that the array is immutable, the contents of the address
228+-- must be guaranteed to not change.
229+--
230+-- /Unsafe/
231+--
232+-- /Internal/
233+--
234+{-# INLINE fromPtr #-}
235+fromPtr :: Int -> Ptr a -> Array a
236+fromPtr n ptr = MA.unsafeInlineIO $ do
237+ fptr <- newForeignPtr_ ptr
238+ let end = ptr `plusPtr` n
239+ return $ Array
240+ { aStart = fptr
241+ , aEnd = end
242+ }
243+
220-- XXX when converting an array of Word8 from a literal string we can simply
244-- XXX when converting an array of Word8 from a literal string we can simply
221-- refer to the literal string. Is it possible to write rules such that
245-- refer to the literal string. Is it possible to write rules such that
222-- fromList Word8 can be rewritten so that GHC does not first convert the
246-- fromList Word8 can be rewritten so that GHC does not first convert the
@@ -227,13 +251,8 @@ spliceTwo arr1 arr2 =
227-- an array of the required type. With template Haskell we can provide a safe
251-- an array of the required type. With template Haskell we can provide a safe
228-- version of fromString#.
252-- version of fromString#.
229--
253--
230−-- | Create an @Array Word8@ of the given length from a machine address
254+-- | Create an @Array Word8@ of the given length from a static, read only
231−-- 'Addr#'. This API is unsafe for the following reasons:
255+-- machine address 'Addr#'. See 'fromPtr' for safety caveats.
232−--
233−-- 1. The address must point to pinned memory or foreign memory.
234−-- 2. The address must be legally accessible upto the given length.
235−-- 3. To guarantee that the array is immutable, the contents of the address
236−-- must be guaranteed to not change.
237--
256--
238-- A common use case for this API is to create an array from a static unboxed
257-- A common use case for this API is to create an array from a static unboxed
239-- string literal. GHC string literals are of type 'Addr#', and must contain
258-- string literal. GHC string literals are of type 'Addr#', and must contain
@@ -252,52 +271,42 @@ spliceTwo arr1 arr2 =
252--
271--
253-- /Time complexity: O(1)/
272-- /Time complexity: O(1)/
254--
273--
274+-- /Internal/
275+--
255{-# INLINE fromAddr# #-}
276{-# INLINE fromAddr# #-}
256−fromAddr# :: Int -> Addr# -> IO (Array Word8)
277+fromAddr# :: Int -> Addr# -> Array a
257−fromAddr# n addr# = do
278+fromAddr# n addr# = fromPtr n (castPtr $ Ptr addr#)
258− ptr <- newForeignPtr_ (castPtr $ Ptr addr#)
259− let p = unsafeForeignPtrToPtr ptr
260− let end = p `plusPtr` n
261− return $ Array
262− { aStart = ptr
263− , aEnd = end
264− }
265
279
266−-- | Like 'fromAddr#' but determines the length of the array upto and excluding
280+-- | Generate a byte array from an 'Addr#' that contains a sequence of NUL
281+-- (@0@) terminated bytes. The array would not include the NUL byte. The
267−-- the first @0@ byte. The address must be legally accessible up to the first
282+-- address must be in static read-only memory and must be legally accessible up
268−-- NUL byte.
283+-- to and including the first NUL byte.
269--
284--
270−-- A common use case for this API is to create an array from an unboxed string
285+-- An unboxed string literal (e.g. @"hello"#@) is a common example of an
271−-- literal. Unboxed string literals are guaranteed to be terminated by a NUL
286+-- 'Addr#' in static read only memory. It represents the UTF8 encoded sequence
272−-- byte.
287+-- of bytes terminated by a NUL byte (a 'CString') corresponding to the
288+-- given unicode string.
273--
289--
274−-- >>> fromString# "hello world!"#
290+-- >>> fromCString# "hello world!"#
275-- > [104,101,108,108,111,32,119,111,114,108,100,33]
291-- > [104,101,108,108,111,32,119,111,114,108,100,33]
276--
292--
277−-- >>> fromString# "\255\NUL\255"#
293+-- >>> fromCString# "\255\NUL\255"#
278-- > [255]
294-- > [255]
279--
295--
280−-- /See also: 'fromAddr#', 'fromString'/
296+-- /See also: 'fromAddr#'/
281--
297--
282-- /Unsafe/
298-- /Unsafe/
283--
299--
284-- /Time complexity: O(n) (computes the length of the string)/
300-- /Time complexity: O(n) (computes the length of the string)/
285--
301--
286−{-# INLINE fromString# #-}
302+-- /Internal/
303+--
304+{-# INLINE fromCString# #-}
287−fromString# :: Addr# -> IO (Array Word8)
305+fromCString# :: Addr# -> Array Word8
288−fromString# addr# = do
306+fromCString# addr# = do
289− ptr <- newForeignPtr_ (castPtr cstr)
307+ let cstr = Ptr addr#
290− len <- c_strlen cstr
308+ len = MA.unsafeInlineIO $ c_strlen cstr
291− let n = fromIntegral len
309+ fromPtr (fromIntegral len) (castPtr cstr)
292− let p = unsafeForeignPtrToPtr ptr
293− let end = p `plusPtr` n
294− return $ Array
295− { aStart = ptr
296− , aEnd = end
297− }
298− where
299− cstr :: CString
300− cstr = Ptr addr#
301
310
302-- | Create an 'Array' from the first N elements of a list. The array is
311-- | Create an 'Array' from the first N elements of a list. The array is
303-- allocated to size N, if the list terminates before N elements then the
312-- allocated to size N, if the list terminates before N elements then the