-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Unified interface for memory managemenet. -- -- Please see the README on GitHub at -- https://github.com/lehins/primal#readme @package primal-memory @version 0.2.0.0 module Data.Prim.Memory.Ptr copyPtrToMBytes :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> MBytes p s -> Off e -> Count e -> m () movePtrToMBytes :: (MonadPrim s m, Prim e) => Ptr e -> Off e -> MBytes p s -> Off e -> Count e -> m () copyBytesToPtr :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> Ptr e -> Off e -> Count e -> m () copyMBytesToPtr :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> Ptr e -> Off e -> Count e -> m () moveMBytesToPtr :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> Ptr e -> Off e -> Count e -> m () copyByteOffPtrToMBytes :: (MonadPrim s m, Prim e) => Ptr e -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () moveByteOffPtrToMBytes :: (MonadPrim s m, Prim e) => Ptr e -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () copyByteOffBytesToPtr :: (MonadPrim s m, Prim e) => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () copyByteOffMBytesToPtr :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () moveByteOffMBytesToPtr :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () compareByteOffBytesToPtr :: Prim e => Bytes p -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> Ordering compareByteOffPtrToBytes :: Prim e => Ptr e -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering module Data.Prim.Memory.ByteString -- | Mutable version of a ByteString newtype MByteString s MByteString :: ByteString -> MByteString s -- | Builders denote sequences of bytes. They are Monoids -- where mempty is the zero-length sequence and mappend is -- concatenation, which runs in O(1). data Builder -- | Convert Bytes into a bytestring Builder toBuilderBytes :: Bytes p -> Builder -- | O(n) - Allocate Bytes and fill them using the supplied -- Builder fromBuilderBytes :: Builder -> Bytes 'Pin -- | A space-efficient representation of a Word8 vector, supporting -- many efficient operations. -- -- A ByteString contains 8-bit bytes, or by using the operations -- from Data.ByteString.Char8 it can be interpreted as containing -- 8-bit characters. data ByteString PS :: {-# UNPACK #-} !ForeignPtr Word8 -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> ByteString -- | O(1) - Cast immutable Bytes to an immutable -- ByteString toByteStringBytes :: Bytes 'Pin -> ByteString -- | O(n) - Convert a strict ByteString to Bytes. fromByteStringBytes :: Typeable p => ByteString -> Bytes p -- | O(n) - Allocate Bytes and fill them with the contents of -- a lazy ByteString fromLazyByteStringBytes :: ByteString -> Bytes 'Pin withPtrByteString :: MonadPrim s m => ByteString -> (Ptr a -> m b) -> m b withNoHaltPtrByteString :: MonadUnliftPrim s m => ByteString -> (Ptr a -> m b) -> m b -- | A compact representation of a Word8 vector. -- -- It has a lower memory overhead than a ByteString and and does -- not contribute to heap fragmentation. It can be converted to or from a -- ByteString (at the cost of copying the string data). It -- supports very few other operations. -- -- It is suitable for use as an internal representation for code that -- needs to keep many short strings in memory, but it should not -- be used as an interchange type. That is, it should not generally be -- used in public APIs. The ByteString type is usually more -- suitable for use in interfaces; it is more flexible and it supports a -- wide range of operations. data ShortByteString SBS :: ByteArray# -> ShortByteString -- | O(1) - Cast an immutable Bytes to an immutable -- ShortByteString toShortByteStringBytes :: Bytes p -> ShortByteString -- | O(1) - Cast an immutable ShortByteString to an immutable -- Bytes fromShortByteStringBytes :: ShortByteString -> Bytes 'Inc byteStringConvertError :: String -> a module Data.Prim.Memory.ForeignPtr -- | For memory allocated as pinned it is possible to operate on it with a -- Ptr. Any data type that is backed by such memory can have a -- PtrAccess instance. The simplest way is to convert it to a -- ForeignPtr and other functions will come for free. class PtrAccess s p -- | Convert to ForeignPtr. toForeignPtr :: (PtrAccess s p, MonadPrim s m) => p -> m (ForeignPtr a) -- | Apply an action to the raw memory Ptr to which the data type -- point to. Type of data stored in memory is left ambiguous -- intentionaly, so that the user can choose how to treat the memory -- content. withPtrAccess :: (PtrAccess s p, MonadPrim s m) => p -> (Ptr a -> m b) -> m b -- | See this GHC issue #17746 and related to it in order to get -- more insight why this is needed. withNoHaltPtrAccess :: (PtrAccess s p, MonadUnliftPrim s m) => p -> (Ptr a -> m b) -> m b -- | The type ForeignPtr represents references to objects that are -- maintained in a foreign language, i.e., that are not part of the data -- structures usually managed by the Haskell storage manager. The -- essential difference between ForeignPtrs and vanilla memory -- references of type Ptr a is that the former may be associated -- with finalizers. A finalizer is a routine that is invoked when -- the Haskell storage manager detects that - within the Haskell heap and -- stack - there are no more references left that are pointing to the -- ForeignPtr. Typically, the finalizer will, then, invoke -- routines in the foreign language that free the resources bound by the -- foreign object. -- -- The ForeignPtr is parameterised in the same way as Ptr. -- The type argument of ForeignPtr should normally be an instance -- of class Storable. data ForeignPtr a ForeignPtr :: Addr# -> ForeignPtrContents -> ForeignPtr a -- | This function casts a ForeignPtr parameterised by one type into -- another type. castForeignPtr :: () => ForeignPtr a -> ForeignPtr b -- | This function extracts the pointer component of a foreign pointer. -- This is a potentially dangerous operations, as if the argument to -- unsafeForeignPtrToPtr is the last usage occurrence of the given -- foreign pointer, then its finalizer(s) will be run, which potentially -- invalidates the plain pointer just obtained. Hence, -- touchForeignPtr must be used wherever it has to be guaranteed -- that the pointer lives on - i.e., has another usage occurrence. -- -- To avoid subtle coding errors, hand written marshalling code should -- preferably use withForeignPtr rather than combinations of -- unsafeForeignPtrToPtr and touchForeignPtr. However, the -- latter routines are occasionally preferred in tool generated -- marshalling code. unsafeForeignPtrToPtr :: () => ForeignPtr a -> Ptr a data ForeignPtrContents PlainForeignPtr :: !IORef Finalizers -> ForeignPtrContents MallocPtr :: MutableByteArray# RealWorld -> !IORef Finalizers -> ForeignPtrContents PlainPtr :: MutableByteArray# RealWorld -> ForeignPtrContents -- | Advances the given address by the given offset in number of elemeents. -- This operation does not affect associated finalizers in any way. plusOffForeignPtr :: Prim e => ForeignPtr e -> Off e -> ForeignPtr e -- | Advances the given address by the given offset in bytes. This -- operation does not affect associated finalizers in any way. plusByteOffForeignPtr :: ForeignPtr e -> Off Word8 -> ForeignPtr e -- | Find the offset in number of elements that is between the two pointers -- by subtracting one address from another and dividing the result by the -- size of an element. minusOffForeignPtr :: Prim e => ForeignPtr e -> ForeignPtr e -> Off e -- | Same as minusOffForeignPtr, but will also return the remainder -- in bytes that is left over. minusOffRemForeignPtr :: Prim e => ForeignPtr e -> ForeignPtr e -> (Off e, Off Word8) -- | Find the offset in bytes that is between the two pointers by -- subtracting one address from another. minusByteOffForeignPtr :: ForeignPtr e -> ForeignPtr e -> Off Word8 -- | Apply an action to the raw pointer. It is unsafe to return the actual -- pointer back from the action because memory itself might get garbage -- collected or cleaned up by finalizers. -- -- It is also important not to run non-terminating actions, because GHC -- can optimize away the logic that runs after the action and GC will -- happen before the action get's a chance to finish resulting in corrupt -- memory. Whenever you have an action that runs an infinite loop or ends -- in an exception throwing, make sure to use withNoHaltForeignPtr -- instead. withForeignPtr :: MonadPrim s m => ForeignPtr e -> (Ptr e -> m b) -> m b -- | Same thing as withForeignPtr except it should be used for never -- ending actions. See withNoHaltPtrAccess for more information on -- how this differes from withForeignPtr. withNoHaltForeignPtr :: MonadUnliftPrim s m => ForeignPtr e -> (Ptr e -> m b) -> m b -- | Similar to mallocPlainForeignPtr, except instead of -- Storable we use Prim and we are not restricted to -- IO, since finalizers are not possible with PlaintPtr mallocPlainForeignPtr :: forall e m s. (MonadPrim s m, Prim e) => m (ForeignPtr e) -- | Similar to mallocPlainForeignPtrArray, except instead of -- Storable we use Prim. mallocCountPlainForeignPtr :: (MonadPrim s m, Prim e) => Count e -> m (ForeignPtr e) -- | Just like mallocCountForeignPtr, but memory is also aligned -- according to Prim instance mallocCountPlainForeignPtrAligned :: forall e m s. (MonadPrim s m, Prim e) => Count e -> m (ForeignPtr e) -- | Lifted version of mallocForeignPtrBytes. mallocByteCountPlainForeignPtr :: MonadPrim s m => Count Word8 -> m (ForeignPtr e) -- | Lifted version of mallocForeignPtrAlignedBytes. mallocByteCountPlainForeignPtrAligned :: MonadPrim s m => Count Word8 -> Int -> m (ForeignPtr e) -- | Lifted version of finalizeForeignPtr. finalizeForeignPtr :: MonadPrim RW m => ForeignPtr e -> m () -- | A finalizer is represented as a pointer to a foreign function that, at -- finalisation time, gets as an argument a plain pointer variant of the -- foreign pointer that the finalizer is associated with. -- -- Note that the foreign function must use the ccall -- calling convention. type FinalizerPtr a = FunPtr Ptr a -> IO () -- | Lifted version of newForeignPtr. newForeignPtr :: MonadPrim RW m => FinalizerPtr e -> Ptr e -> m (ForeignPtr e) -- | Lifted version of newForeignPtr_. newForeignPtr_ :: MonadPrim RW m => Ptr e -> m (ForeignPtr e) -- | Lifted version of touchForeignPtr. touchForeignPtr :: MonadPrim s m => ForeignPtr e -> m () -- | Simila to mallocForeignPtr, except it operates on Prim, -- instead of Storable. mallocForeignPtr :: forall e m. (MonadPrim RW m, Prim e) => m (ForeignPtr e) -- | Similar to mallocForeignPtrArray, except instead of -- Storable we use Prim. mallocCountForeignPtr :: (MonadPrim RW m, Prim e) => Count e -> m (ForeignPtr e) -- | Just like mallocCountForeignPtr, but memory is also aligned -- according to Prim instance mallocCountForeignPtrAligned :: (MonadPrim RW m, Prim e) => Count e -> m (ForeignPtr e) -- | Lifted version of mallocForeignPtrBytes. mallocByteCountForeignPtr :: MonadPrim RW m => Count Word8 -> m (ForeignPtr e) -- | Lifted version of mallocForeignPtrAlignedBytes. mallocByteCountForeignPtrAligned :: MonadPrim RW m => Count Word8 -> Int -> m (ForeignPtr e) -- | Lifted version of addForeignPtrFinalizer addForeignPtrFinalizer :: MonadPrim RW m => FinalizerPtr e -> ForeignPtr e -> m () type FinalizerEnvPtr env a = FunPtr Ptr env -> Ptr a -> IO () -- | Lifted version of newForeignPtrEnv. newForeignPtrEnv :: MonadPrim RW m => FinalizerEnvPtr env e -> Ptr env -> Ptr e -> m (ForeignPtr e) -- | Lifted version of addForeignPtrFinalizerEnv addForeignPtrFinalizerEnv :: MonadPrim RW m => FinalizerEnvPtr env e -> Ptr env -> ForeignPtr e -> m () -- | Unlifted version of newConcForeignPtr newConcForeignPtr :: MonadUnliftPrim RW m => Ptr e -> m () -> m (ForeignPtr e) -- | Unlifted version of addForeignPtrConcFinalizer addForeignPtrConcFinalizer :: MonadUnliftPrim RW m => ForeignPtr a -> m () -> m () toForeignPtrBytes :: Bytes 'Pin -> ForeignPtr e toForeignPtrMBytes :: MBytes 'Pin s -> ForeignPtr e instance Data.Prim.Memory.ForeignPtr.PtrAccess s (GHC.ForeignPtr.ForeignPtr a) instance Data.Prim.Memory.ForeignPtr.PtrAccess s Data.ByteString.Internal.ByteString instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.ByteString.MByteString s) instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.Bytes.Internal.Bytes 'Data.Prim.Memory.Bytes.Internal.Pin) instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.Bytes.Internal.MBytes 'Data.Prim.Memory.Bytes.Internal.Pin s) module Data.Prim.Memory.Text -- | A space efficient, packed, unboxed Unicode text type. data Text Text :: {-# UNPACK #-} !Array -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> Text -- | Mutable version of a Text data MText s MText :: {-# UNPACK #-} !MArray s -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> MText s -- | Immutable array type. -- -- The Array constructor is exposed since text-1.1.1.3 data Array Array :: ByteArray# -> Array [aBA] :: Array -> ByteArray# -- | Mutable array type, for use in the ST monad. -- -- The MArray constructor is exposed since text-1.1.1.3 data MArray s MArray :: MutableByteArray# s -> MArray s [maBA] :: MArray s -> MutableByteArray# s toBytesArray :: Array -> Bytes 'Inc fromBytesArray :: Bytes p -> Array toMBytesMArray :: MArray s -> MBytes 'Inc s fromMBytesMArray :: MBytes p s -> MArray s module Data.Prim.Memory.Bytes -- | An immutable region of memory which was allocated either as pinned or -- unpinned. -- -- Constructor is not exported for safety. Violating type level -- Pinned kind is very dangerous. Type safe constructor -- fromByteArray# and unwrapper toByteArray# should be used -- instead. As a backdoor, of course, the actual constructor is available -- from Data.Prim.Memory.Internal data Bytes (p :: Pinned) -- | Wrap ByteArray# into Bytes toByteArray# :: Bytes p -> ByteArray# -- | Unwrap Bytes to get the underlying ByteArray#. fromByteArray# :: ByteArray# -> Bytes 'Inc cloneBytes :: Typeable p => Bytes p -> Bytes p emptyBytes :: Bytes p eqBytes :: Bytes p1 -> Bytes p2 -> Bool singletonBytes :: forall e p. (Prim e, Typeable p) => e -> Bytes p isEmptyBytes :: Bytes p -> Bool -- | Allocated memory is not cleared, so make sure to fill it in properly, -- otherwise you might find some garbage there. createBytes :: forall p e b s m. (Prim e, Typeable p, MonadPrim s m) => Count e -> (MBytes p s -> m b) -> m (b, Bytes p) createBytes_ :: forall p e b s m. (Prim e, Typeable p, MonadPrim s m) => Count e -> (MBytes p s -> m b) -> m (Bytes p) createBytesST :: forall p e b. (Prim e, Typeable p) => Count e -> (forall s. MBytes p s -> ST s b) -> (b, Bytes p) createBytesST_ :: forall p e b. (Prim e, Typeable p) => Count e -> (forall s. MBytes p s -> ST s b) -> Bytes p -- | In GHC there is a distinction between pinned and unpinned memory. -- -- Pinned memory is such that when allocated, it is guaranteed not to -- move throughout the lifetime of a program. In other words the address -- pointer that refers to allocated bytes will not change until the -- associated ByteArray# or MutableByteArray# is no longer -- referenced anywhere in the program at which point it gets garbage -- collected. On the other hand unpinned memory can be moved around -- during GC, which helps to reduce memory fragmentation. -- -- Pinned/unpinnned choice during allocation is a bit of a lie, because -- when attempt is made to allocate memory as unpinned, but requested -- size is a bit more than a certain threshold (somewhere around 3KiB) it -- might still be allocated as pinned. Because of that fact through out -- the "primal" universe there is a distinction between memory that is -- either Pinned or Inconclusive. -- -- It is possible to use one of toPinnedBytes or -- toPinnedMBytes to get a conclusive type. data Pinned -- | Pinned, which indicates that allocated memory will not move Pin :: Pinned -- | Inconclusive, thus memory could be pinned or unpinned Inc :: Pinned isPinnedBytes :: Bytes p -> Bool isPinnedMBytes :: MBytes p d -> Bool toPinnedBytes :: Bytes p -> Maybe (Bytes 'Pin) toPinnedMBytes :: MBytes p s -> Maybe (MBytes 'Pin s) toInconclusiveBytes :: Bytes p -> Bytes 'Inc toInconclusiveMBytes :: MBytes p e -> MBytes 'Inc e relaxPinnedBytes :: Bytes 'Pin -> Bytes p relaxPinnedMBytes :: MBytes 'Pin e -> MBytes p e ensurePinnedBytes :: Bytes p -> Bytes 'Pin ensurePinnedMBytes :: MonadPrim s m => MBytes p s -> m (MBytes 'Pin s) -- | Mutable region of memory which was allocated either as pinned or -- unpinned. -- -- Constructor is not exported for safety. Violating type level -- Pinned kind is very dangerous. Type safe constructor -- fromMutableByteArray# and unwrapper toMutableByteArray# -- should be used instead. As a backdoor, of course, the actual -- constructor is available in Data.Prim.Memory.Internal module -- and specially unsafe function castPinnedMBytes was crafted. data MBytes (p :: Pinned) s -- | Wrap MutableByteArray# into MBytes toMutableByteArray# :: MBytes p s -> MutableByteArray# s -- | Unwrap MBytes to get the underlying MutableByteArray#. fromMutableByteArray# :: MutableByteArray# s -> MBytes 'Inc s -- | Check if two byte arrays refer to pinned memory and compare their -- pointers. isSameBytes :: Bytes p1 -> Bytes p2 -> Bool -- | Perform pointer equality on pinned Bytes. isSamePinnedBytes :: Bytes 'Pin -> Bytes 'Pin -> Bool -- | Check if two mutable bytes pointers refer to the same memory isSameMBytes :: MBytes p1 s -> MBytes p2 s -> Bool indexOffBytes :: Prim e => Bytes p -> Off e -> e indexByteOffBytes :: Prim e => Bytes p -> Off Word8 -> e byteCountBytes :: Bytes p -> Count Word8 -- | How many elements of type a fits into bytes completely. In -- order to get a possible count of leftover bytes use -- countRemBytes countBytes :: Prim e => Bytes p -> Count e -- | Get the count of elements of type a that can fit into bytes -- as well as the slack number of bytes that would be leftover in case -- when total number of bytes available is not exactly divisable by the -- size of the element that will be stored in the memory chunk. countRemBytes :: forall e p. Prim e => Bytes p -> (Count e, Count Word8) compareBytes :: Prim e => Bytes p1 -> Off e -> Bytes p2 -> Off e -> Count e -> Ordering compareByteOffBytes :: Prim e => Bytes p1 -> Off Word8 -> Bytes p2 -> Off Word8 -> Count e -> Ordering thawBytes :: MonadPrim s m => Bytes p -> m (MBytes p s) freezeMBytes :: MonadPrim s m => MBytes p s -> m (Bytes p) allocMBytes :: forall p e s m. (Typeable p, Prim e, MonadPrim s m) => Count e -> m (MBytes p s) singletonMBytes :: forall e p m s. (Prim e, Typeable p, MonadPrim s m) => e -> m (MBytes p s) allocPinnedMBytes :: (MonadPrim s m, Prim e) => Count e -> m (MBytes 'Pin s) allocAlignedMBytes :: forall e m s. (MonadPrim s m, Prim e) => Count e -> m (MBytes 'Pin s) allocUnpinnedMBytes :: (MonadPrim s m, Prim e) => Count e -> m (MBytes 'Inc s) callocMBytes :: (MonadPrim s m, Prim e, Typeable p) => Count e -> m (MBytes p s) callocAlignedMBytes :: (MonadPrim s m, Prim e) => Count e -> m (MBytes 'Pin s) -- | Shrink mutable bytes to new specified count of elements. The new count -- must be less than or equal to the current count as reported by -- getCountMBytes. shrinkMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Count e -> m () -- | Attempt to resize mutable bytes in place. -- -- resizeMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Count e -> m (MBytes 'Inc s) reallocMBytes :: forall e p m s. (MonadPrim s m, Typeable p, Prim e) => MBytes p s -> Count e -> m (MBytes p s) -- | This function allows the change of state token. Use with care, because -- it can allow mutation to escape the ST monad. coerceStateMBytes :: MBytes p s' -> MBytes p s cloneMBytes :: (MonadPrim s m, Typeable p) => MBytes p s -> m (MBytes p s) withCloneMBytes :: (MonadPrim s m, Typeable p) => Bytes p -> (MBytes p s -> m a) -> m (a, Bytes p) withCloneMBytes_ :: (MonadPrim s m, Typeable p) => Bytes p -> (MBytes p s -> m a) -> m (Bytes p) withCloneMBytesST :: Typeable p => Bytes p -> (forall s. MBytes p s -> ST s a) -> (a, Bytes p) withCloneMBytesST_ :: Typeable p => Bytes p -> (forall s. MBytes p s -> ST s a) -> Bytes p -- | Same as loadListMem loadListMBytes :: (Prim e, Typeable p, MonadPrim s m) => [e] -> MBytes p s -> m ([e], Count e) -- | Same as loadListMem_ loadListMBytes_ :: (Prim e, Typeable p, MonadPrim s m) => [e] -> MBytes p s -> m () copyBytesToMBytes :: (MonadPrim s m, Prim e) => Bytes ps -> Off e -> MBytes pd s -> Off e -> Count e -> m () moveMBytesToMBytes :: (MonadPrim s m, Prim e) => MBytes ps s -> Off e -> MBytes pd s -> Off e -> Count e -> m () getByteCountMBytes :: MonadPrim s m => MBytes p s -> m (Count Word8) -- | How many elements of type a fits into bytes completely. In -- order to get any number of leftover bytes use countRemBytes getCountMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> m (Count e) -- | Get the number of elements of type a that can fit into bytes -- as well as the slack number of bytes that would be leftover in case -- when total number of bytes available is not exactly divisable by the -- size of the element that will be stored in the memory chunk. getCountRemOfMBytes :: forall e p s m. (MonadPrim s m, Prim e) => MBytes p s -> m (Count e, Count Word8) readOffMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m e readByteOffMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> m e writeOffMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> e -> m () writeByteOffMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Off Word8 -> e -> m () setMBytes :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> Count e -> e -> m () -- | Fill the mutable array with zeros efficiently. zeroMBytes :: MonadPrim s m => MBytes p s -> m () -- | Pointer access to immutable Bytes should be for read only -- purposes, but it is not enforced. Any mutation will break referential -- transparency withPtrBytes :: MonadPrim s m => Bytes 'Pin -> (Ptr e -> m b) -> m b -- | Same as withPtrBytes, but is suitable for actions that don't -- terminate withNoHaltPtrBytes :: MonadUnliftPrim s m => Bytes 'Pin -> (Ptr e -> m b) -> m b withPtrMBytes :: MonadPrim s m => MBytes 'Pin s -> (Ptr e -> m b) -> m b withNoHaltPtrMBytes :: MonadUnliftPrim s m => MBytes 'Pin s -> (Ptr e -> m b) -> m b toPtrBytes :: Bytes 'Pin -> Ptr e toPtrMBytes :: MBytes 'Pin s -> Ptr e toForeignPtrBytes :: Bytes 'Pin -> ForeignPtr e toForeignPtrMBytes :: MBytes 'Pin s -> ForeignPtr e fromListBytes :: forall e p. (Prim e, Typeable p) => [e] -> Bytes p -- | Exactly like fromListMemN, but restricted to Bytes. fromListBytesN :: (Prim e, Typeable p) => Count e -> [e] -> (Either [e] (Count e), Bytes p) -- | Same as fromListZeroMemN_ fromListBytesN_ :: (Prim e, Typeable p) => Count e -> [e] -> Bytes p -- | Allocate new memory region and append second bytes region after the -- first one appendBytes :: Typeable p => Bytes p1 -> Bytes p2 -> Bytes p concatBytes :: Typeable p => [Bytes p'] -> Bytes p -- | It is only guaranteed to convert the whole memory to a list whenever -- the size of allocated memory is exactly divisible by the size of the -- element, otherwise there will be some slack left unaccounted for. toListBytes :: Prim e => Bytes p -> [e] toListSlackBytes :: Prim e => Bytes p -> ([e], [Word8]) -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Returns the actual value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. casMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> e -> e -> m e -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Returns True if swap was successfull and false -- otherwise. Offset is in number of elements, rather than bytes. Implies -- a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. casBoolMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> e -> e -> m Bool -- | Just like casBoolMBytes, but also returns the actual value, -- which will match the supplied expected value if the returned flag is -- True -- -- Note - Bounds are not checked, therefore this function is -- unsafe. casBoolFetchMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> e -> e -> m (Bool, e) -- | Perform atomic read of MBytes at the supplied index. Offset is -- in number of elements, rather than bytes. Implies a full memory -- barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicReadMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> m e -- | Perform a write into MBytes at the supplied index atomically. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicWriteMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> e -> m () -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Returns the artifact of computation b. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> (e -> (e, b)) -> m b -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyMBytes_ :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> (e -> e) -> m () -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicBoolModifyFetchOldMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> (e -> e) -> m e -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyFetchOldMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> (e -> e) -> m e -- | Perform atomic modification of an element in the MBytes at the -- supplied index. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyFetchNewMBytes :: (MonadPrim s m, Atomic e) => MBytes p s -> Off e -> (e -> e) -> m e -- | Add a numeric value to an element of a MBytes, corresponds to -- (+) done atomically. Returns the previous value. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAddFetchOldMBytes :: (MonadPrim s m, AtomicCount e) => MBytes p s -> Off e -> e -> m e -- | Add a numeric value to an element of a MBytes, corresponds to -- (+) done atomically. Returns the new value. Offset is -- in number of elements, rather than bytes. Implies a full memory -- barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAddFetchNewMBytes :: (MonadPrim s m, AtomicCount e) => MBytes p s -> Off e -> e -> m e -- | Subtract a numeric value from an element of a MBytes, -- corresponds to (-) done atomically. Returns the -- previous value. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicSubFetchOldMBytes :: (MonadPrim s m, AtomicCount e) => MBytes p s -> Off e -> e -> m e -- | Subtract a numeric value from an element of a MBytes, -- corresponds to (-) done atomically. Returns the new -- value. Offset is in number of elements, rather than bytes. Implies a -- full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicSubFetchNewMBytes :: (MonadPrim s m, AtomicCount e) => MBytes p s -> Off e -> e -> m e -- | Binary conjunction (AND) of an element of a MBytes with the -- supplied value, corresponds to (.&.) done -- atomically. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAndFetchOldMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Binary conjunction (AND) of an element of a MBytes with the -- supplied value, corresponds to (.&.) done -- atomically. Returns the new value. Offset is in number of elements, -- rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAndFetchNewMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Negation of binary conjunction (NAND) of an element of a MBytes -- with the supplied value, corresponds to \x y -> -- complement (x .&. y) done atomically. Returns -- the previous value. Offset is in number of elements, rather than -- bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNandFetchOldMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Negation of binary conjunction (NAND) of an element of a MBytes -- with the supplied value, corresponds to \x y -> -- complement (x .&. y) done atomically. Returns -- the new value. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNandFetchNewMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Binary disjunction (OR) of an element of a MBytes with the -- supplied value, corresponds to (.|.) done atomically. -- Returns the previous value. Offset is in number of elements, rather -- than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicOrFetchOldMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Binary disjunction (OR) of an element of a MBytes with the -- supplied value, corresponds to (.|.) done atomically. -- Returns the new value. Offset is in number of elements, rather than -- bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicOrFetchNewMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Binary exclusive disjunction (XOR) of an element of a MBytes -- with the supplied value, corresponds to xor done -- atomically. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicXorFetchOldMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Binary exclusive disjunction (XOR) of an element of a MBytes -- with the supplied value, corresponds to xor done -- atomically. Returns the new value. Offset is in number of elements, -- rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicXorFetchNewMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> e -> m e -- | Binary negation (NOT) of an element of a MBytes, corresponds to -- (complement) done atomically. Returns the previous -- value. Offset is in number of elements, rather than bytes. Implies a -- full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNotFetchOldMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> m e -- | Binary negation (NOT) of an element of a MBytes, corresponds to -- (complement) done atomically. Returns the new value. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNotFetchNewMBytes :: (MonadPrim s m, AtomicBits e) => MBytes p s -> Off e -> m e prefetchBytes0 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m () prefetchMBytes0 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m () prefetchBytes1 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m () prefetchMBytes1 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m () prefetchBytes2 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m () prefetchMBytes2 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m () prefetchBytes3 :: (MonadPrim s m, Prim e) => Bytes p -> Off e -> m () prefetchMBytes3 :: (MonadPrim s m, Prim e) => MBytes p s -> Off e -> m () module Data.Prim.Memory.PrimArray -- | An immutable array of bytes of type e newtype PrimArray (p :: Pinned) e PrimArray :: Bytes p -> PrimArray e -- | A mutable array of bytes of type e newtype MPrimArray (p :: Pinned) e s MPrimArray :: MBytes p s -> MPrimArray e s -- | In GHC there is a distinction between pinned and unpinned memory. -- -- Pinned memory is such that when allocated, it is guaranteed not to -- move throughout the lifetime of a program. In other words the address -- pointer that refers to allocated bytes will not change until the -- associated ByteArray# or MutableByteArray# is no longer -- referenced anywhere in the program at which point it gets garbage -- collected. On the other hand unpinned memory can be moved around -- during GC, which helps to reduce memory fragmentation. -- -- Pinned/unpinnned choice during allocation is a bit of a lie, because -- when attempt is made to allocate memory as unpinned, but requested -- size is a bit more than a certain threshold (somewhere around 3KiB) it -- might still be allocated as pinned. Because of that fact through out -- the "primal" universe there is a distinction between memory that is -- either Pinned or Inconclusive. -- -- It is possible to use one of toPinnedBytes or -- toPinnedMBytes to get a conclusive type. data Pinned -- | Pinned, which indicates that allocated memory will not move Pin :: Pinned -- | Inconclusive, thus memory could be pinned or unpinned Inc :: Pinned fromBytesPrimArray :: Bytes p -> PrimArray p e toBytesPrimArray :: PrimArray p e -> Bytes p castPrimArray :: PrimArray p e' -> PrimArray p e fromMBytesMPrimArray :: MBytes p s -> MPrimArray p e s toMBytesMPrimArray :: MPrimArray p e s -> MBytes p s castMPrimArray :: MPrimArray p e' s -> MPrimArray p e s allocMPrimArray :: forall e p m s. (Typeable p, Prim e, MonadPrim s m) => Size -> m (MPrimArray p e s) allocPinnedMPrimArray :: forall e m s. (MonadPrim s m, Prim e) => Size -> m (MPrimArray 'Pin e s) allocAlignedMPrimArray :: (MonadPrim s m, Prim e) => Count e -> m (MPrimArray 'Pin e s) allocUnpinnedMPrimArray :: forall e m s. (MonadPrim s m, Prim e) => Size -> m (MPrimArray 'Inc e s) -- | Shrink mutable bytes to new specified count of elements. The new count -- must be less than or equal to the current count as reported by -- getCountMPrimArray. shrinkMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Size -> m () -- | Attempt to resize mutable bytes in place. -- -- resizeMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Size -> m (MPrimArray 'Inc e s) reallocMPrimArray :: forall e p m s. (MonadPrim s m, Typeable p, Prim e) => MPrimArray p e s -> Size -> m (MPrimArray p e s) isPinnedPrimArray :: PrimArray p e -> Bool isPinnedMPrimArray :: MPrimArray p e s -> Bool thawPrimArray :: MonadPrim s m => PrimArray p e -> m (MPrimArray p e s) freezeMPrimArray :: MonadPrim s m => MPrimArray p e s -> m (PrimArray p e) sizePrimArray :: forall e p. Prim e => PrimArray p e -> Size getSizeMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> m Size readMPrimArray :: (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> m e writeMPrimArray :: (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> e -> m () setMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> Size -> e -> m () copyPrimArrayToMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => PrimArray p e -> Int -> MPrimArray p e s -> Int -> Size -> m () moveMPrimArrayToMPrimArray :: forall e p m s. (MonadPrim s m, Prim e) => MPrimArray p e s -> Int -> MPrimArray p e s -> Int -> Size -> m () instance Data.Prim.Memory.Internal.MemWrite (Data.Prim.Memory.PrimArray.MPrimArray p e) instance Control.DeepSeq.NFData (Data.Prim.Memory.PrimArray.MPrimArray p e s) instance Data.Prim.Memory.Internal.MemRead (Data.Prim.Memory.PrimArray.PrimArray p e) instance Data.Typeable.Internal.Typeable p => GHC.Base.Monoid (Data.Prim.Memory.PrimArray.PrimArray p e) instance Data.Typeable.Internal.Typeable p => GHC.Base.Semigroup (Data.Prim.Memory.PrimArray.PrimArray p e) instance Control.DeepSeq.NFData (Data.Prim.Memory.PrimArray.PrimArray p e) instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.PrimArray.MPrimArray 'Data.Prim.Memory.Bytes.Internal.Pin e s) instance Data.Typeable.Internal.Typeable p => Data.Prim.Memory.Internal.MemAlloc (Data.Prim.Memory.PrimArray.MPrimArray p e) instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.PrimArray.PrimArray 'Data.Prim.Memory.Bytes.Internal.Pin e) instance (Data.Typeable.Internal.Typeable p, Data.Prim.Class.Prim e) => GHC.Exts.IsList (Data.Prim.Memory.PrimArray.PrimArray p e) instance Data.Typeable.Internal.Typeable p => Data.String.IsString (Data.Prim.Memory.PrimArray.PrimArray p GHC.Types.Char) instance (GHC.Show.Show e, Data.Prim.Class.Prim e) => GHC.Show.Show (Data.Prim.Memory.PrimArray.PrimArray p e) module Data.Prim.Memory.Addr -- | Immutable read-only address data Addr e Addr :: Addr# -> {-# UNPACK #-} !Bytes 'Pin -> Addr e [addrAddr#] :: Addr e -> Addr# [addrBytes] :: Addr e -> {-# UNPACK #-} !Bytes 'Pin castAddr :: Addr e -> Addr b fromBytesAddr :: Bytes 'Pin -> Addr e curOffAddr :: Prim e => Addr e -> Off e byteCountAddr :: Addr e -> Count Word8 countAddr :: forall e. Prim e => Addr e -> Count e plusOffAddr :: Prim e => Addr e -> Off e -> Addr e indexAddr :: Prim e => Addr e -> e indexOffAddr :: Prim e => Addr e -> Off e -> e indexByteOffAddr :: Prim e => Addr e -> Off Word8 -> e readAddr :: (MonadPrim s m, Prim e) => Addr e -> m e readOffAddr :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m e readByteOffAddr :: (MonadPrim s m, Prim e) => Addr e -> Off Word8 -> m e thawAddr :: MonadPrim s m => Addr e -> m (MAddr e s) freezeMAddr :: MonadPrim s m => MAddr e s -> m (Addr e) withPtrAddr :: MonadPrim s m => Addr e -> (Ptr e -> m b) -> m b withAddrAddr# :: MonadPrim s m => Addr e -> (Addr# -> m b) -> m b withNoHaltPtrAddr :: MonadUnliftPrim s m => Addr e -> (Ptr e -> m b) -> m b -- | Mutable address data MAddr e s MAddr :: Addr# -> {-# UNPACK #-} !MBytes 'Pin s -> MAddr e s [mAddrAddr#] :: MAddr e s -> Addr# [mAddrMBytes] :: MAddr e s -> {-# UNPACK #-} !MBytes 'Pin s castMAddr :: MAddr e s -> MAddr b s allocMAddr :: (MonadPrim s m, Prim e) => Count e -> m (MAddr e s) callocMAddr :: (MonadPrim s m, Prim e) => Count e -> m (MAddr e s) reallocMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Count e -> m (MAddr e s) -- | Shrink mutable address to new specified size in number of elements. -- The new count must be less than or equal to the current as reported by -- getCountMAddr. shrinkMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Count e -> m () -- | Shrink mutable address to new specified size in bytes. The new count -- must be less than or equal to the current as reported by -- getByteCountMAddr. shrinkByteCountMAddr :: MonadPrim s m => MAddr e s -> Count Word8 -> m () setMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> Count e -> e -> m () curOffMAddr :: forall e s. Prim e => MAddr e s -> Off e getByteCountMAddr :: MonadPrim s m => MAddr e s -> m (Count Word8) getCountMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> m (Count e) plusOffMAddr :: Prim e => MAddr e s -> Off e -> MAddr e s readMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> m e readOffMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m e readByteOffMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Off Word8 -> m e writeMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> e -> m () writeOffMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> e -> m () writeByteOffMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Off Word8 -> e -> m () copyAddrToMAddr :: (MonadPrim s m, Prim e) => Addr e -> Off e -> MAddr e s -> Off e -> Count e -> m () moveMAddrToMAddr :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> MAddr e s -> Off e -> Count e -> m () withPtrMAddr :: MonadPrim s m => MAddr e s -> (Ptr e -> m b) -> m b withAddrMAddr# :: MonadPrim s m => MAddr e s -> (Addr# -> m b) -> m b withNoHaltPtrMAddr :: MonadUnliftPrim s m => MAddr e s -> (Ptr e -> m b) -> m b toForeignPtrAddr :: Addr e -> ForeignPtr e toForeignPtrMAddr :: MAddr e s -> ForeignPtr e -- | This is a unsafe cast therefore modification of ForeignPtr will -- be reflected in resulting immutable Addr. Pointer created with -- malloc cannot be converted to Addr and will result in -- Nothing fromForeignPtrAddr :: ForeignPtr e -> Maybe (Addr e) -- | Discarding the original ForeignPtr will trigger finalizers that were -- attached to it, because MAddr does not retain any finalizers. -- Pointer created with malloc cannot be converted to -- MAddr and will result in Nothing fromForeignPtrMAddr :: ForeignPtr e -> Maybe (MAddr e s) -- | O(1) - Cast an immutable Addr to an immutable -- ByteString toByteStringAddr :: Addr Word8 -> ByteString -- | O(1) - Cast an immutable Addr to an immutable -- ShortByteString toShortByteStringAddr :: Addr Word8 -> (ShortByteString, Off Word8) -- | O(n) - Convert an immutable ShortByteString to an -- immutable Addr. In a most common case when -- ShortByteString is not backed by pinned memory, this function -- will return Nothing. fromShortByteStringAddr :: ShortByteString -> Addr Word8 -- | O(1) - Cast an immutable ByteString to Addr. Also -- returns the original length of ByteString, which will be less or equal -- to countOfAddr in the produced Addr. fromByteStringAddr :: ByteString -> (Addr Word8, Count Word8) -- | O(1) - Cast an immutable ByteString to a mutable -- MAddr. Also returns the original length of ByteString, which -- will be less or equal to getCountOfMAddr in the produced -- MAddr. -- -- Unsafe - Further modification of MAddr will affect the -- source ByteString fromByteStringMAddr :: ByteString -> (MAddr Word8 s, Count Word8) -- | Perform atomic modification of an element in the MAddr at the -- supplied index. Returns the artifact of computation b. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. casOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> e -> e -> m e -- | Perform atomic modification of an element in the MAddr at the -- supplied index. Returns True if swap was successfull and false -- otherwise. Offset is in number of elements, rather than bytes. Implies -- a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. casBoolOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> e -> e -> m Bool -- | Just like casBoolOffMAddr, but also returns the actual value, -- which will match the supplied expected value if the returned flag is -- True -- -- Note - Bounds are not checked, therefore this function is -- unsafe. casBoolFetchOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> e -> e -> m (Bool, e) -- | Perform atomic read of an element in the MAddr at the supplied -- offset. Offset is in number of elements, rather than bytes. Implies a -- full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicReadOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> m e -- | Perform atomic write of an element in the MAddr at the supplied -- offset. Offset is in number of elements, rather than bytes. Implies a -- full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicWriteOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> e -> m () -- | Perform atomic modification of an element in the MAddr at the -- supplied index. Returns the artifact of computation b. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> (e -> (e, b)) -> m b -- | Perform atomic modification of an element in the MAddr at the -- supplied index. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyOffMAddr_ :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> (e -> e) -> m () -- | Perform atomic modification of an element in the MAddr at the -- supplied index. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyFetchOldOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> (e -> e) -> m e -- | Perform atomic modification of an element in the MAddr at the -- supplied index. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicModifyFetchNewOffMAddr :: (MonadPrim s m, Atomic e) => MAddr e s -> Off e -> (e -> e) -> m e -- | Add a numeric value to an element of a MAddr, corresponds to -- (+) done atomically. Returns the previous value. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAddFetchOldOffMAddr :: (MonadPrim s m, AtomicCount e) => MAddr e s -> Off e -> e -> m e -- | Add a numeric value to an element of a MAddr, corresponds to -- (+) done atomically. Returns the new value. Offset is -- in number of elements, rather than bytes. Implies a full memory -- barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAddFetchNewOffMAddr :: (MonadPrim s m, AtomicCount e) => MAddr e s -> Off e -> e -> m e -- | Subtract a numeric value from an element of a MAddr, -- corresponds to (-) done atomically. Returns the -- previous value. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicSubFetchOldOffMAddr :: (MonadPrim s m, AtomicCount e) => MAddr e s -> Off e -> e -> m e -- | Subtract a numeric value from an element of a MAddr, -- corresponds to (-) done atomically. Returns the new -- value. Offset is in number of elements, rather than bytes. Implies a -- full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicSubFetchNewOffMAddr :: (MonadPrim s m, AtomicCount e) => MAddr e s -> Off e -> e -> m e -- | Binary conjunction (AND) of an element of a MAddr with the -- supplied value, corresponds to (.&.) done -- atomically. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAndFetchOldOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Binary conjunction (AND) of an element of a MAddr with the -- supplied value, corresponds to (.&.) done -- atomically. Returns the new value. Offset is in number of elements, -- rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicAndFetchNewOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Negation of binary conjunction (NAND) of an element of a MAddr -- with the supplied value, corresponds to \x y -> -- complement (x .&. y) done atomically. Returns -- the previous value. Offset is in number of elements, rather than -- bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNandFetchOldOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Negation of binary conjunction (NAND) of an element of a MAddr -- with the supplied value, corresponds to \x y -> -- complement (x .&. y) done atomically. Returns -- the new value. Offset is in number of elements, rather than bytes. -- Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNandFetchNewOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Binary disjunction (OR) of an element of a MAddr with the -- supplied value, corresponds to (.|.) done atomically. -- Returns the previous value. Offset is in number of elements, rather -- than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicOrFetchOldOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Binary disjunction (OR) of an element of a MAddr with the -- supplied value, corresponds to (.|.) done atomically. -- Returns the new value. Offset is in number of elements, rather than -- bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicOrFetchNewOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Binary exclusive disjunction (XOR) of an element of a MAddr -- with the supplied value, corresponds to xor done -- atomically. Returns the previous value. Offset is in number of -- elements, rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicXorFetchOldOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Binary exclusive disjunction (XOR) of an element of a MAddr -- with the supplied value, corresponds to xor done -- atomically. Returns the new value. Offset is in number of elements, -- rather than bytes. Implies a full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicXorFetchNewOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> e -> m e -- | Binary negation (NOT) of an element of a MAddr, corresponds to -- (complement) done atomically. Returns the previous -- value. Offset is in number of elements, rather than bytes. Implies a -- full memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNotFetchOldOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> m e -- | Binary negation (NOT) of an element of a MAddr, corresponds to -- (complement) done atomically. Returns the new value. -- Offset is in number of elements, rather than bytes. Implies a full -- memory barrier. -- -- Note - Bounds are not checked, therefore this function is -- unsafe. atomicNotFetchNewOffMAddr :: (MonadPrim s m, AtomicBits e) => MAddr e s -> Off e -> m e prefetchAddr0 :: MonadPrim s m => Addr e -> m () prefetchMAddr0 :: MonadPrim s m => MAddr e s -> m () prefetchAddr1 :: MonadPrim s m => Addr e -> m () prefetchMAddr1 :: MonadPrim s m => MAddr e s -> m () prefetchAddr2 :: MonadPrim s m => Addr e -> m () prefetchMAddr2 :: MonadPrim s m => MAddr e s -> m () prefetchAddr3 :: MonadPrim s m => Addr e -> m () prefetchMAddr3 :: MonadPrim s m => MAddr e s -> m () prefetchOffAddr0 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m () prefetchOffMAddr0 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m () prefetchOffAddr1 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m () prefetchOffMAddr1 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m () prefetchOffAddr2 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m () prefetchOffMAddr2 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m () prefetchOffAddr3 :: (MonadPrim s m, Prim e) => Addr e -> Off e -> m () prefetchOffMAddr3 :: (MonadPrim s m, Prim e) => MAddr e s -> Off e -> m () instance Control.DeepSeq.NFData (Data.Prim.Memory.Addr.MAddr e s) instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.Addr.MAddr e s) instance Data.Prim.Memory.Internal.MemAlloc (Data.Prim.Memory.Addr.MAddr e) instance Data.Prim.Memory.Internal.MemWrite (Data.Prim.Memory.Addr.MAddr e) instance GHC.Classes.Eq (Data.Prim.Memory.Addr.Addr e) instance (GHC.Show.Show e, Data.Prim.Class.Prim e) => GHC.Show.Show (Data.Prim.Memory.Addr.Addr e) instance Data.String.IsString (Data.Prim.Memory.Addr.Addr GHC.Types.Char) instance Data.Prim.Class.Prim e => GHC.Exts.IsList (Data.Prim.Memory.Addr.Addr e) instance GHC.Base.Semigroup (Data.Prim.Memory.Addr.Addr e) instance GHC.Base.Monoid (Data.Prim.Memory.Addr.Addr e) instance Control.DeepSeq.NFData (Data.Prim.Memory.Addr.Addr e) instance Data.Prim.Memory.ForeignPtr.PtrAccess s (Data.Prim.Memory.Addr.Addr e) instance Data.Prim.Memory.Internal.MemRead (Data.Prim.Memory.Addr.Addr e) module Data.Prim.Memory -- | In GHC there is a distinction between pinned and unpinned memory. -- -- Pinned memory is such that when allocated, it is guaranteed not to -- move throughout the lifetime of a program. In other words the address -- pointer that refers to allocated bytes will not change until the -- associated ByteArray# or MutableByteArray# is no longer -- referenced anywhere in the program at which point it gets garbage -- collected. On the other hand unpinned memory can be moved around -- during GC, which helps to reduce memory fragmentation. -- -- Pinned/unpinnned choice during allocation is a bit of a lie, because -- when attempt is made to allocate memory as unpinned, but requested -- size is a bit more than a certain threshold (somewhere around 3KiB) it -- might still be allocated as pinned. Because of that fact through out -- the "primal" universe there is a distinction between memory that is -- either Pinned or Inconclusive. -- -- It is possible to use one of toPinnedBytes or -- toPinnedMBytes to get a conclusive type. data Pinned -- | Pinned, which indicates that allocated memory will not move Pin :: Pinned -- | Inconclusive, thus memory could be pinned or unpinned Inc :: Pinned -- | An immutable region of memory which was allocated either as pinned or -- unpinned. -- -- Constructor is not exported for safety. Violating type level -- Pinned kind is very dangerous. Type safe constructor -- fromByteArray# and unwrapper toByteArray# should be used -- instead. As a backdoor, of course, the actual constructor is available -- from Data.Prim.Memory.Internal data Bytes (p :: Pinned) -- | Type class that can be implemented for an immutable data type that -- provides read-only direct access to memory class MemRead mr -- | Figure out how many elements fits into the immutable region of memory. -- It is possible that there is a remainder of bytes left, see -- countRemMem for getting that too. -- --

Examples

-- --
--   >>> b = fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin
--   
--   >>> b
--   [0x00,0x01,0x02,0x03,0x04,0x05]
--   
--   >>> countMem b :: Count Word16
--   Count {unCount = 3}
--   
--   >>> countMem b :: Count Word32
--   Count {unCount = 1}
--   
countMem :: forall e mr. (MemRead mr, Prim e) => mr -> Count e -- | Compute how many elements and a byte size remainder that can fit into -- the region of memory. -- --

Examples

-- --
--   >>> b = fromListMem [0 .. 5 :: Word8] :: Bytes 'Pin
--   
--   >>> b
--   [0x00,0x01,0x02,0x03,0x04,0x05]
--   
--   >>> countRemMem @Word16 b
--   (Count {unCount = 3},Count {unCount = 0})
--   
--   >>> countRemMem @Word32 b
--   (Count {unCount = 1},Count {unCount = 2})
--   
countRemMem :: forall e mr. (MemRead mr, Prim e) => mr -> (Count e, Count Word8) -- | Number of bytes allocated by the data type available for reading. -- --

Example

-- --
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> byteCountMem (fromByteListMem [1,2,3] :: Bytes 'Inc)
--   Count {unCount = 3}
--   
byteCountMem :: MemRead mr => mr -> Count Word8 -- | Read an element with an offset in number of elements, rather than -- bytes as is the case with indexByteOffMem. -- -- indexOffMem :: (MemRead mr, Prim e) => mr -> Off e -> e -- | Read an element with an offset in number of bytes. Bounds are not -- checked. -- -- indexByteOffMem :: (MemRead mr, Prim e) => mr -> Off Word8 -> e -- | Construct an immutable memory region that can't hold any data. Same as -- mempty :: FrozenMem ma -- --

Example

-- --
--   >>> :set -XTypeApplications
--   
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> toListMem (emptyMem @(MBytes 'Inc)) :: [Int]
--   []
--   
emptyMem :: forall ma. MemAlloc ma => FrozenMem ma -- | Allocate a region of immutable memory that holds a single element. -- --

Example

-- --
--   >>> :set -XTypeApplications
--   
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> toListMem (singletonMem @Word16 @(MBytes 'Inc) 0xffff) :: [Word8]
--   [255,255]
--   
singletonMem :: forall e ma. (MemAlloc ma, Prim e) => e -> FrozenMem ma -- | Place n copies of supplied region of memory one after another -- in a newly allocated contiguous chunk of memory. Similar to -- stimes, but the source memory memRead does not have to -- match the type of FrozenMem ma. -- --

Example

-- --
--   >>> :set -XTypeApplications
--   
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> let b = fromListMem @Word8 @(MBytes 'Inc) [0xde, 0xad, 0xbe, 0xef]
--   
--   >>> cycleMemN @(MBytes 'Inc) 2 b
--   [0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef]
--   
cycleMemN :: forall ma mr. (MemAlloc ma, MemRead mr) => Int -> mr -> FrozenMem ma createMemST :: forall e b ma. (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> (b, FrozenMem ma) createMemST_ :: (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> FrozenMem ma createZeroMemST :: forall e ma b. (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> (b, FrozenMem ma) -- | Same as createMemST_, except it ensures that the memory gets -- reset with zeros prior to applying the ST filling action -- fillAction. -- -- -- --

Example

-- -- Note that this example will work correctly only on little-endian -- machines: -- --
--   >>> :set -XTypeApplications
--   
--   >>> import Data.Prim
--   
--   >>> import Control.Monad
--   
--   >>> let ibs = zip [0, 4 ..] [0x48,0x61,0x73,0x6b,0x65,0x6c,0x6c] :: [(Off Word8, Word8)]
--   
--   >>> let c = Count (length ibs) :: Count Char
--   
--   >>> let bc = createZeroMemST_ @_ @(MBytes 'Inc) c $ \m -> forM_ ibs $ \(i, b) -> writeByteOffMem m i b
--   
--   >>> toListMem bc :: String
--   "Haskell"
--   
createZeroMemST_ :: forall e ma b. (MemAlloc ma, Prim e) => Count e -> (forall s. ma s -> ST s b) -> FrozenMem ma -- | Copy all of the data from the source into a newly allocate memory -- region of identical size. -- --

Examples

-- --
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> let xs = fromByteListMem @(MBytes 'Pin) [0..15] :: Bytes 'Pin
--   
--   >>> let ys = cloneMem xs
--   
--   >>> let report bEq pEq = print $ "Bytes equal: " ++ show bEq ++ ", their pointers equal: " ++ show pEq
--   
--   >>> withPtrBytes xs $ \ xsPtr -> withPtrBytes ys $ \ ysPtr -> report (xs == ys) (xsPtr == ysPtr)
--   "Bytes equal: True, their pointers equal: False"
--   
cloneMem :: forall ma. MemAlloc ma => FrozenMem ma -> FrozenMem ma -- | Similar to copyByteOffMem, but supply offsets in number of -- elements instead of bytes. Copy contiguous chunk of memory from the -- read only memory region into the target mutable memory region. Source -- and target must not refer to the same memory region, otherwise -- that would imply that the source is not immutable which would be a -- violation of some other invariant elsewhere in the code. -- -- copyMem :: (MonadPrim s m, MemRead mr, MemWrite mw, Prim e) => mr -> Off e -> mw s -> Off e -> Count e -> m () -- | Copy contiguous chunk of memory from the read only memory region into -- the target mutable memory region. Source and target must not -- refer to the same memory region, otherwise that would imply that the -- source is not immutable which would be a violation of some other -- invariant elsewhere in the code. -- -- copyByteOffMem :: (MemWrite mw, MonadPrim s m, MemRead mr, Prim e) => mr -> Off Word8 -> mw s -> Off Word8 -> Count e -> m () -- | Copy contiguous chunk of memory from the read only memory into the -- target mutable MBytes. Source and target must not refer -- to the same memory region, otherwise that would imply that the source -- is not immutable which would be a violation of some other invariant -- elsewhere in the code. -- -- copyByteOffToMBytesMem :: (MemRead mr, MonadPrim s m, Prim e) => mr -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () -- | Copy contiguous chunk of memory from the read only memory into the -- target mutable Ptr. Source and target must not refer to -- the same memory region, otherwise that would imply that the source is -- not immutable which would be a violation of some other invariant -- elsewhere in the code. -- -- copyByteOffToPtrMem :: (MemRead mr, MonadPrim s m, Prim e) => mr -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () -- | Compare two memory regions byte-by-byte. False is returned -- immediately when sizes reported by byteCountMem do not match. -- Computation may be short-circuited on the first mismatch, but it is -- MemRead implementation specific. eqMem :: (MemRead mr1, MemRead mr2) => mr1 -> mr2 -> Bool -- | Compare two regions of memory byte-by-byte. It will return EQ -- whenever both regions are exactly the same and LT or GT -- as soon as the first byte is reached that is less than or greater than -- respectfully in the first region when compared to the second one. It -- is safe for both regions to refer to the same part of memory, since -- this is a pure function and both regions of memory are read-only. compareMem :: forall e mr1 mr2. (MemRead mr1, MemRead mr2, Prim e) => mr1 -> Off e -> mr2 -> Off e -> Count e -> Ordering -- | Compare two read-only regions of memory byte-by-byte. The very first -- mismatched byte will cause this function to produce LT if the -- byte in memRead1 is smaller than the one in memRead2 -- and GT if it is bigger. It is not a requirement to -- short-circuit on the first mismatch, but it is a good optimization to -- have for non-sensitive data. Memory regions that store security -- critical data may choose to implement this function to work in -- constant time. -- -- This function is usually implemented by either one of -- compareByteOffToPtrMem or compareByteOffToBytesMem, -- depending on the nature of mr type. However it differs from -- the aforementioned functions with a fact that it is pure non-monadic -- computation. -- -- compareByteOffMem :: (MemRead mr, MemRead mr', Prim e) => mr' -> Off Word8 -> mr -> Off Word8 -> Count e -> Ordering -- | Same as compareByteOffMem, but compare the read-only memory -- region to a region addressed by a Ptr inside of a -- MonadPrim. -- -- compareByteOffToPtrMem :: (MemRead mr, MonadPrim s m, Prim e) => mr -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m Ordering -- | Same as compareByteOffMem, but compare the read-only memory -- region to Bytes. -- -- compareByteOffToBytesMem :: (MemRead mr, Prim e) => mr -> Off Word8 -> Bytes p -> Off Word8 -> Count e -> Ordering -- | O(n) - Convert a read-only memory region into a newly allocated -- other type of memory region -- --
--   >>> import Data.ByteString (pack)
--   
--   >>> bs = pack [0x10 .. 0x20]
--   
--   >>> bs
--   "\DLE\DC1\DC2\DC3\DC4\NAK\SYN\ETB\CAN\EM\SUB\ESC\FS\GS\RS\US "
--   
--   >>> convertMem bs :: Bytes 'Inc
--   [0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20]
--   
convertMem :: (MemRead mr, MemAlloc ma) => mr -> FrozenMem ma -- | Convert an immutable memory region to a list. Whenever memory byte -- count is not exactly divisible by the size of the element there will -- be some slack left unaccounted for. In order to get a hold of this -- slack use toListSlackMem instead. -- --

Examples

-- --
--   >>> import Data.Prim.Memory
--   
--   >>> import Numeric (showHex)
--   
--   >>> let b = fromByteListMem [0x48,0x61,0x73,0x6b,0x65,0x6c,0x6c] :: Bytes 'Inc
--   
--   >>> toListMem b :: [Int8]
--   [72,97,115,107,101,108,108]
--   
--   >>> let xs = toListMem b :: [Word32]
--   
--   >>> xs
--   [1802723656]
--   
--   >>> showHex (head xs) ""
--   "6b736148"
--   
toListMem :: forall e mr. (MemRead mr, Prim e) => mr -> [e] -- | Same as toListMem, except when there is some slack towards the -- end of the memory region that didn't fit into a list it will be -- returned as a list of bytes. -- --

Examples

-- --
--   >>> import Data.Word
--   
--   >>> :set -XDataKinds
--   
--   >>> a = fromListMem [0 .. 10 :: Word8] :: Bytes 'Pin
--   
--   >>> a
--   [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]
--   
--   >>> toListSlackMem a :: ([Word8], [Word8])
--   ([0,1,2,3,4,5,6,7,8,9,10],[])
--   
--   >>> toListSlackMem a :: ([Word16], [Word8])
--   ([256,770,1284,1798,2312],[10])
--   
--   >>> toListSlackMem a :: ([Word32], [Word8])
--   ([50462976,117835012],[8,9,10])
--   
--   >>> toListSlackMem a :: ([Word64], [Word8])
--   ([506097522914230528],[8,9,10])
--   
toListSlackMem :: forall e mr. (MemRead mr, Prim e) => mr -> ([e], [Word8]) -- | Convert a memory region to a list of bytes. Equivalent to -- unpack for ByteString -- --

Example

-- --
--   >>> toByteListMem (fromByteListMem [0..10] :: Bytes 'Pin)
--   [0,1,2,3,4,5,6,7,8,9,10]
--   
toByteListMem :: forall ma. MemAlloc ma => FrozenMem ma -> [Word8] -- | Right fold that is useful for converting to a list while tapping into -- list fusion. -- -- foldrCountMem :: forall e b mr. (MemRead mr, Prim e) => Count e -> (e -> b -> b) -> b -> mr -> b -- | A list of ShowS which covert bytes to base16 encoded strings. -- Each element of the list is a function that will convert one byte. -- --

Example

-- --
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> concatMap ($ " ") $ showsHexMem (fromListMem [1 :: Int16 .. 15] :: Bytes 'Inc)
--   "01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 09 00 0a 00 0b 00 0c 00 0d 00 0e 00 0f 00 "
--   
showsHexMem :: MemRead mr => mr -> [ShowS] -- | Just like fromListMemN, except it ensures safety by using the -- length of the list for allocation. Because it has to figure out the -- length of the list first it will be just a little bit slower, but that -- much safer. -- --

Examples

-- --
--   >>> import Data.Prim.Memory
--   
--   >>> :set -XDataKinds
--   
--   >>> fromListMem "Hi" :: Bytes 'Inc
--   [0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00]
--   
fromListMem :: forall e ma. (Prim e, MemAlloc ma) => [e] -> FrozenMem ma -- | Same as fromListMem but restricted to a list of Word8. -- Load a list of bytes into a newly allocated memory region. Equivalent -- to pack for ByteString -- --

Examples

-- --
--   >>> fromByteListMem [0..10] :: Bytes 'Pin
--   [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a]
--   
fromByteListMem :: forall ma. MemAlloc ma => [Word8] -> FrozenMem ma -- | Similarly to fromListMem load a list into a newly allocated -- memory region, but unlike the aforementioned function it also accepts -- a hint of how many elements is expected to be in the list. Because the -- number of expected an actual elements might not match we return not -- only the frozen memory region, but also: -- -- -- -- In the latter case a zero value would indicate that the list did fit -- into the newly allocated memory region exactly, which is perfectly -- fine. But a positive value would mean that the tail of the memory -- region is still unset and might contain garbage data. Make sure to -- overwrite the surplus memory yourself or use the safe version -- fromListZeroMemN that fills the surplus with zeros. -- -- -- --

Examples

-- --
--   >>> :set -XTypeApplications
--   
--   >>> fromListMemN @Char @(MBytes 'Inc) 3 "Hello"
--   (Left "lo",[0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00])
--   
--   >>> fromListMemN @Char @(MBytes 'Inc) 2 "Hi"
--   (Left "",[0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00])
--   
--   >>> fst $ fromListMemN @Char @(MBytes 'Inc) 5 "Hi"
--   Right (Count {unCount = 2})
--   
fromListMemN :: forall e ma. (Prim e, MemAlloc ma) => Count e -> [e] -> (Either [e] (Count e), FrozenMem ma) -- | Just like fromListMemN, except it ensures safety by filling -- tail with zeros, whenever the list is not long enough. -- --

Examples

-- --
--   >>> import Data.Prim.Memory
--   
--   >>> :set -XTypeApplications
--   
--   >>> fromListZeroMemN @Char @(MBytes 'Inc) 3 "Hi"
--   (Right (Count {unCount = 2}),[0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
--   
fromListZeroMemN :: forall e ma. (Prim e, MemAlloc ma) => Count e -> [e] -> (Either [e] (Count e), FrozenMem ma) -- | Same as fromListZeroMemN, but ignore the extra information -- about how the loading went. -- --

Examples

-- --
--   >>> import Data.Prim.Memory
--   
--   >>> fromListZeroMemN_ 3 "Hi" :: Bytes 'Inc
--   [0x48,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
--   
fromListZeroMemN_ :: forall e ma. (Prim e, MemAlloc ma) => Count e -> [e] -> FrozenMem ma -- | Mutable region of memory which was allocated either as pinned or -- unpinned. -- -- Constructor is not exported for safety. Violating type level -- Pinned kind is very dangerous. Type safe constructor -- fromMutableByteArray# and unwrapper toMutableByteArray# -- should be used instead. As a backdoor, of course, the actual -- constructor is available in Data.Prim.Memory.Internal module -- and specially unsafe function castPinnedMBytes was crafted. data MBytes (p :: Pinned) s -- | Type class that can be implemented for a mutable data type that -- provides direct read and write access to memory class MemWrite mw -- | Generalized memory allocation and pure/mutable state conversion. class (MemRead (FrozenMem ma), MemWrite ma) => MemAlloc ma where { -- | Memory region in the immutable state. Types for frozen and thawed -- states of memory region are in one-to-one correspondence, therefore -- ma - FrozeMem ma will always uniquely identify each -- other, which is an extremely useful property when it comes to type -- inference. type family FrozenMem ma = (fm :: Type) | fm -> ma; } -- | A wrapper that adds a phantom state token. It can be used with types -- that either doesn't have such state token or are designed to work in -- IO and therefore restricted to RW. Using this wrapper is -- very much unsafe, so make sure you know what you are doing. newtype MemState a s MemState :: a -> MemState a s [unMemState] :: MemState a s -> a getCountMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e) getCountRemMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> m (Count e, Count Word8) -- | Extract from the mutable memory region information about how many -- bytes it can hold. getByteCountMem :: (MemAlloc ma, MonadPrim s m) => ma s -> m (Count Word8) -- | Read an element with an offset in number of elements, rather than -- bytes as it is the case with readByteOffMem. -- -- readOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> m e -- | Read an element with an offset in number of bytes. -- -- readByteOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> m e -- | Write an element with an offset in number of elements, rather than -- bytes as it is the case with writeByteOffMem. -- -- writeOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> e -> m () -- | Write an element with an offset in number of bytes. -- -- writeByteOffMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> e -> m () -- | Write the same value memCount times into each cell of -- memTarget starting at an offset memTargetOff. -- -- setMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> Count e -> e -> m () modifyFetchOldMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e modifyFetchOldMemM :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e modifyFetchNewMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> e) -> m e modifyFetchNewMemM :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off e -> (e -> m e) -> m e -- | Allocate a mutable memory region for specified number of elements. -- Memory is not reset and will likely hold some garbage data, therefore -- prefer to use allocZeroMem, unless it is guaranteed that all of -- allocated memory will be overwritten. -- -- allocMem :: (MemAlloc ma, Prim e, MonadPrim s m) => Count e -> m (ma s) -- | Same as allocMem, but also use setMem to reset all of -- newly allocated memory to zeros. -- -- -- --

Example

-- --
--   >>> :set -XTypeApplications
--   
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> mb <- allocZeroMem @Int @(MBytes 'Inc) 10
--   
--   >>> b <- freezeMem mb
--   
--   >>> toListMem b :: [Int]
--   [0,0,0,0,0,0,0,0,0,0]
--   
allocZeroMem :: forall e ma m s. (MemAlloc ma, MonadPrim s m, Prim e) => Count e -> m (ma s) -- | Convert the state of an immutable memory region to the mutable one. -- This is a no copy operation, as such it is fast, but dangerous. See -- thawCopyMem for a safe alternative. -- -- thawMem :: (MemAlloc ma, MonadPrim s m) => FrozenMem ma -> m (ma s) thawCloneMem :: forall mr ma m s. (MemRead mr, MemAlloc ma, MonadPrim s m) => mr -> m (ma s) thawCopyMem :: forall e mr ma m s. (Prim e, MemRead mr, MemAlloc ma, MonadPrim s m) => mr -> Off e -> Count e -> m (ma s) -- | Convert the state of a mutable memory region to the immutable one. -- This is a no copy operation, as such it is fast, but dangerous. See -- freezeCopyMem for a safe alternative. -- -- freezeMem :: (MemAlloc ma, MonadPrim s m) => ma s -> m (FrozenMem ma) freezeCloneMem :: forall ma m s. (MemAlloc ma, MonadPrim s m) => ma s -> m (FrozenMem ma) freezeCopyMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => ma s -> Off e -> Count e -> m (FrozenMem ma) -- | Either grow or shrink currently allocated mutable region of memory. -- For some implementations it might be possible to change the size of -- the allocated region in-place, i.e. without copy. However in all -- implementations there is a good chance that the memory region has to -- be allocated anew, in which case all of the contents up to the minimum -- of new and old sizes will get copied over. After the resize operation -- is complete the supplied memSource region must not be used -- anymore. Moreover, no reference to the old one should be kept in order -- to allow garbage collection of the original in case a new one had to -- be allocated. -- -- resizeMem :: (MemAlloc ma, MonadPrim s m, Prim e) => ma s -> Count e -> m (ma s) -- | Ensure that memory is filled with zeros before and after it gets used. -- PtrAccess is not used directly, but istead is used to guarantee -- that the memory is pinned and its contents do get moved around by the -- garbage collector. withScrubbedMem :: forall e ma m a. (MonadUnliftPrim RW m, Prim e, MemAlloc ma, PtrAccess RW (ma RW)) => Count e -> (ma RW -> m a) -> m a moveMem :: (MonadPrim s m, MemWrite mw1, MemWrite mw2, Prim e) => mw1 s -> Off e -> mw2 s -> Off e -> Count e -> m () -- | Copy contiguous chunk of memory from a mutable memory region into the -- target mutable memory region. Source and target may refer to -- the same memory region. -- -- moveByteOffMem :: (MemWrite mw, MonadPrim s m, MemWrite mw', Prim e) => mw' s -> Off Word8 -> mw s -> Off Word8 -> Count e -> m () -- | Copy contiguous chunk of memory from the source mutable memory into -- the target mutable MBytes. Source and target may refer -- to overlapping memory regions. -- -- moveByteOffToMBytesMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> MBytes p s -> Off Word8 -> Count e -> m () -- | Copy contiguous chunk of memory from the source mutable memory into -- the target Ptr. Source and target may refer to -- overlapping memory regions. -- -- moveByteOffToPtrMem :: (MemWrite mw, MonadPrim s m, Prim e) => mw s -> Off Word8 -> Ptr e -> Off Word8 -> Count e -> m () -- | Same as loadListMemN, but tries to fit as many elements as -- possible into the mutable memory region starting at the beginning. -- This operation is always safe. -- --

Examples

-- --
--   >>> import Data.Prim.Memory
--   
--   >>> ma <- allocMem (5 :: Count Char) :: IO (MBytes 'Inc RW)
--   
--   >>> loadListMem "HelloWorld" ma
--   ("World",Count {unCount = 5})
--   
--   >>> freezeMem ma
--   [0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]
--   
--   >>> loadListMem (replicate 6 (0xff :: Word8)) ma
--   ([],Count {unCount = 6})
--   
--   >>> freezeMem ma
--   [0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]
--   
loadListMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => [e] -> ma s -> m ([e], Count e) -- | Same as loadListMem, but ignores the result. Equivalence as -- property: -- --
--   let c = fromInteger (abs i) :: Count Int in (createZeroMemST_ c (loadListMem_ (xs :: [Int])) :: Bytes 'Inc) == createZeroMemST_ c (void . loadListMem xs)
--   
loadListMem_ :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => [e] -> ma s -> m () -- | Same as loadListOffMemN, but start loading at 0 -- offset. -- -- loadListMemN :: forall e mw m s. (MemWrite mw, MonadPrim s m, Prim e) => Count e -> [e] -> mw s -> m ([e], Count e) -- | Same as loadListMemN, but ignores the result. -- -- loadListMemN_ :: forall e mw m s. (Prim e, MemWrite mw, MonadPrim s m) => Count e -> [e] -> mw s -> m () -- | Same as loadListOffMemN, but infer the count from number of -- bytes that is available in the target memory region. -- -- loadListOffMem :: forall e ma m s. (Prim e, MemAlloc ma, MonadPrim s m) => [e] -> ma s -> Off e -> m ([e], Count e) -- | Same as loadListByteOffMemN, but works with offset in number of -- elements instead of bytes. -- -- loadListOffMemN :: (MemWrite mw, MonadPrim s m, Prim e) => Count e -> [e] -> mw s -> Off e -> m ([e], Count e) -- | Same as loadListByteOffMemN, but infer the count from number of -- bytes that is available in the target memory region. -- -- -- --

Examples

-- --
--   >>> :set -XDataKinds
--   
--   >>> import Data.Prim.Memory
--   
--   >>> ma <- allocZeroMem (5 :: Count Char) :: IO (MBytes 'Inc RW)
--   
--   >>> freezeMem ma
--   [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
--   
--   >>> loadListByteOffMem "Hello World" ma 0
--   (" World",Count {unCount = 5})
--   
--   >>> freezeMem ma
--   [0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]
--   
--   >>> loadListByteOffMem ([0xff,0xff,0xff] :: [Word8]) ma 1
--   ([],Count {unCount = 3})
--   
--   >>> freezeMem ma
--   [0x48,0xff,0xff,0xff,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6f,0x00,0x00,0x00]
--   
loadListByteOffMem :: (MemAlloc ma, MonadPrim s m, Prim e) => [e] -> ma s -> Off Word8 -> m ([e], Count e) -- | Load elements from the supplied list into a mutable memory region. -- Loading will start at the supplied offset in number of bytes and will -- stop when either supplied elemCount number is reached or -- there are no more elements left in the list to load. This action -- returns a list of elements that did not get loaded and the count of -- how many elements did get loaded. -- -- -- --

Examples

-- -- For example load the Hell somewhere in the middle of -- MBytes: -- --
--   >>> ma <- allocZeroMem (6 :: Count Char) :: IO (MBytes 'Inc RW)
--   
--   >>> loadListByteOffMemN 4 "Hello!" ma (toByteOff (1 :: Off Char))
--   ("o!",Count {unCount = 4})
--   
--   >>> freezeMem ma
--   [0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
--   
-- -- Or something more usful like loading prefixes from nested lists: -- --
--   >>> import Control.Monad
--   
--   >>> foldM_ (\o xs -> (+ o) . countToByteOff . snd <$> loadListByteOffMemN 4 xs ma o) 2 [[x..] | x <- [1..5] :: [Word8]]
--   
--   >>> freezeMem ma
--   [0x00,0x00,0x01,0x02,0x03,0x04,0x02,0x03,0x04,0x05,0x03,0x04,0x05,0x06,0x04,0x05,0x06,0x07,0x05,0x06,0x07,0x08,0x00,0x00]
--   
loadListByteOffMemN :: (MemWrite mw, MonadPrim s m, Prim e) => Count e -> [e] -> mw s -> Off Word8 -> m ([e], Count e)