Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add withPrimArrayContents and withMutablePrimArrayContents #400

Merged
merged 3 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions Data/Primitive/ByteArray.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ import System.IO.Unsafe (unsafeDupablePerformIO)

import Data.Array.Byte (ByteArray(..), MutableByteArray(..))

import Data.Primitive.Internal.Operations (mutableByteArrayContentsShim)

-- | Create a new mutable byte array of the specified size in bytes.
-- The underlying memory is left uninitialized.
--
Expand Down Expand Up @@ -161,15 +163,6 @@ mutableByteArrayContents :: MutableByteArray s -> Ptr Word8
{-# INLINE mutableByteArrayContents #-}
mutableByteArrayContents (MutableByteArray arr#) = Ptr (mutableByteArrayContentsShim arr#)

mutableByteArrayContentsShim :: MutableByteArray# s -> Addr#
{-# INLINE mutableByteArrayContentsShim #-}
mutableByteArrayContentsShim x =
#if __GLASGOW_HASKELL__ >= 902
mutableByteArrayContents# x
#else
byteArrayContents# (unsafeCoerce# x)
#endif

-- | A composition of 'mutableByteArrayContents' and 'keepAliveUnlifted'.
-- The callback function must not return the pointer. The argument byte
-- array must be /pinned/. See 'byteArrayContents' for an explanation
Expand Down
11 changes: 11 additions & 0 deletions Data/Primitive/Internal/Operations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module Data.Primitive.Internal.Operations (
, keepAliveLiftedLifted#
, keepAliveUnliftedLifted#
#endif
, mutableByteArrayContentsShim
, UnliftedType
) where

Expand Down Expand Up @@ -192,3 +193,13 @@ type UnliftedType = TYPE 'PtrRepUnlifted
#elif __GLASGOW_HASKELL__ < 902
type UnliftedType = TYPE 'UnliftedRep
#endif

mutableByteArrayContentsShim :: MutableByteArray# s -> Addr#
{-# INLINE mutableByteArrayContentsShim #-}
mutableByteArrayContentsShim x =
#if __GLASGOW_HASKELL__ >= 902
mutableByteArrayContents# x
#else
byteArrayContents# (unsafeCoerce# x)
#endif

34 changes: 28 additions & 6 deletions Data/Primitive/PrimArray.hs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ module Data.Primitive.PrimArray
, sizeofMutablePrimArray
, sizeofPrimArray
, primArrayContents
, withPrimArrayContents
, mutablePrimArrayContents
, withMutablePrimArrayContents
#if __GLASGOW_HASKELL__ >= 802
, isPrimArrayPinned
, isMutablePrimArrayPinned
Expand Down Expand Up @@ -133,6 +135,8 @@ import Data.Semigroup
import qualified GHC.Exts as Exts
#endif

import Data.Primitive.Internal.Operations (mutableByteArrayContentsShim)

-- | Arrays of unboxed elements. This accepts types like 'Double', 'Char',
-- 'Int' and 'Word', as well as their fixed-length variants ('Word8',
-- 'Word16', etc.). Since the elements are unboxed, a 'PrimArray' is strict
Expand Down Expand Up @@ -1106,12 +1110,8 @@ primArrayContents (PrimArray arr#) = Ptr (byteArrayContents# arr#)
-- @since 0.7.1.0
mutablePrimArrayContents :: MutablePrimArray s a -> Ptr a
{-# INLINE mutablePrimArrayContents #-}
mutablePrimArrayContents (MutablePrimArray arr#) = Ptr
#if __GLASGOW_HASKELL__ >= 902
(mutableByteArrayContents# arr#)
#else
(byteArrayContents# (unsafeCoerce# arr#))
#endif
mutablePrimArrayContents (MutablePrimArray arr#) =
Ptr (mutableByteArrayContentsShim arr#)

-- | Return a newly allocated array with the specified subrange of the
-- provided array. The provided array should contain the full subrange
Expand Down Expand Up @@ -1162,3 +1162,25 @@ unST (GHCST.ST f) = f
#else /* In older GHCs, runRW# is not available. */
runPrimArray m = runST $ m >>= unsafeFreezePrimArray
#endif

-- | A composition of 'primArrayContents' and 'keepAliveUnlifted'.
-- The callback function must not return the pointer. The argument
-- array must be /pinned/. See 'primArrayContents' for an explanation
-- of which primitive arrays are pinned.
--
-- Note: This could be implemented with 'keepAlive' instead of
-- 'keepAliveUnlifted', but 'keepAlive' here would cause GHC to materialize
-- the wrapper data constructor on the heap.
withPrimArrayContents :: PrimBase m => PrimArray a -> (Ptr a -> m a) -> m a
{-# INLINE withPrimArrayContents #-}
withPrimArrayContents (PrimArray arr#) f =
keepAliveUnlifted arr# (f (Ptr (byteArrayContents# arr#)))

-- | A composition of 'mutablePrimArrayContents' and 'keepAliveUnlifted'.
-- The callback function must not return the pointer. The argument
-- array must be /pinned/. See 'primArrayContents' for an explanation
-- of which primitive arrays are pinned.
withMutablePrimArrayContents :: PrimBase m => MutablePrimArray (PrimState m) a -> (Ptr a -> m a) -> m a
{-# INLINE withMutablePrimArrayContents #-}
withMutablePrimArrayContents (MutablePrimArray arr#) f =
keepAliveUnlifted arr# (f (Ptr (mutableByteArrayContentsShim arr#)))
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Changes in version 0.9.0.0

* Add `withByteArrayContents`, `withMutableByteArrayContents`,
`withPrimArrayContents`, `withMutablePrimArrayContents`.

* Fix signature of `keepAlive`.

* Remove re-export of `fromList` and `fromListN` from `Data.Primitive.Array`.
Expand Down
Loading