{-# LANGUAGE MagicHash #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 800
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
#endif
module Data.Primitive.PVar
(
PVar
, newPVar
, withPVarST
, readPVar
, writePVar
, modifyPVar
, modifyPVar_
, fetchModifyPVar
, modifyFetchPVar
, modifyPVarM
, modifyPVarM_
, fetchModifyPVarM
, modifyFetchPVarM
, swapPVars_
, swapPVars
, copyPVar
, sizeOfPVar
, alignmentPVar
, newPinnedPVar
, newAlignedPinnedPVar
, withPtrPVar
, withStorablePVar
, withAlignedStorablePVar
, copyPVarToPtr
, toForeignPtrPVar
, isPinnedPVar
, peekPrim, pokePrim
, atomicModifyIntPVar
, atomicModifyIntPVar_
, atomicFetchModifyIntPVar
, atomicModifyFetchIntPVar
, atomicReadIntPVar
, atomicWriteIntPVar
, casIntPVar
, atomicAddIntPVar
, atomicSubIntPVar
, atomicAndIntPVar
, atomicNandIntPVar
, atomicOrIntPVar
, atomicXorIntPVar
, atomicNotIntPVar
, Prim
, PrimMonad(PrimState)
, RealWorld
, sizeOf
, alignment
, ST
, runST
, S.Storable(peek, poke)
) where
import Control.Monad (void)
import Control.Monad.Primitive (PrimMonad(primitive), PrimState, primitive_,
touch)
import Control.Monad.ST (ST, runST)
import Data.Primitive.PVar.Internal
import Data.Primitive.PVar.Unsafe
import Data.Primitive.Types
import qualified Foreign.Storable as S
import GHC.Exts
import GHC.ForeignPtr
withPVarST ::
Prim p
=> p
-> (forall s. PVar (ST s) p -> ST s a)
-> a
withPVarST x st = runST (newPVar x >>= st)
{-# INLINE withPVarST #-}
withPtrPVar :: (PrimMonad m, Prim a) => PVar n a -> (Ptr a -> m b) -> m (Maybe b)
withPtrPVar pvar f =
case toPtrPVar pvar of
Nothing -> return Nothing
Just ptr -> do
r <- f ptr
touch pvar
return $ Just r
{-# INLINE withPtrPVar #-}
toForeignPtrPVar :: PVar IO a -> Maybe (ForeignPtr a)
toForeignPtrPVar pvar
| isPinnedPVar pvar = Just $ unsafeToForeignPtrPVar pvar
| otherwise = Nothing
{-# INLINE toForeignPtrPVar #-}
copyPVar ::
(PrimMonad m, Prim a)
=> PVar m a
-> PVar m a
-> m ()
copyPVar pvar@(PVar mbas#) (PVar mbad#) =
primitive_ (copyMutableByteArray# mbas# 0# mbad# 0# (sizeOfPVar# pvar))
{-# INLINE copyPVar #-}
copyPVarToPtr :: (PrimMonad m, Prim a) => PVar m a -> Ptr a -> m ()
copyPVarToPtr pvar@(PVar mbas#) (Ptr addr#) =
primitive_ (copyMutableByteArrayToAddr# mbas# 0# addr# (sizeOfPVar# pvar))
{-# INLINE copyPVarToPtr #-}
modifyPVar :: (PrimMonad m, Prim a) => PVar m a -> (a -> (a, b)) -> m b
modifyPVar pvar f = modifyPVarM pvar (return . f)
{-# INLINE modifyPVar #-}
modifyPVar_ :: (PrimMonad m, Prim a) => PVar m a -> (a -> a) -> m ()
modifyPVar_ pvar f = modifyPVarM_ pvar (return . f)
{-# INLINE modifyPVar_ #-}
fetchModifyPVar :: (PrimMonad m, Prim a) => PVar m a -> (a -> a) -> m a
fetchModifyPVar pvar f = fetchModifyPVarM pvar (return . f)
{-# INLINE fetchModifyPVar #-}
modifyFetchPVar :: (PrimMonad m, Prim a) => PVar m a -> (a -> a) -> m a
modifyFetchPVar pvar f = modifyFetchPVarM pvar (return . f)
{-# INLINE modifyFetchPVar #-}
modifyPVarM :: (PrimMonad m, Prim a) => PVar m a -> (a -> m (a, b)) -> m b
modifyPVarM pvar f = do
a <- readPVar pvar
(a', b) <- f a
b <$ writePVar pvar a'
{-# INLINE modifyPVarM #-}
fetchModifyPVarM :: (PrimMonad m, Prim a) => PVar m a -> (a -> m a) -> m a
fetchModifyPVarM pvar f = do
a <- readPVar pvar
a <$ (writePVar pvar =<< f a)
{-# INLINE fetchModifyPVarM #-}
modifyFetchPVarM :: (PrimMonad m, Prim a) => PVar m a -> (a -> m a) -> m a
modifyFetchPVarM pvar f = do
a <- readPVar pvar
a' <- f a
a' <$ writePVar pvar a'
{-# INLINE modifyFetchPVarM #-}
modifyPVarM_ :: (PrimMonad m, Prim a) => PVar m a -> (a -> m a) -> m ()
modifyPVarM_ pvar f = readPVar pvar >>= f >>= writePVar pvar
{-# INLINE modifyPVarM_ #-}
swapPVars :: (PrimMonad m, Prim a) => PVar m a -> PVar m a -> m (a, a)
swapPVars pvar1 pvar2 = do
a1 <- readPVar pvar1
a2 <- fetchModifyPVar pvar2 (const a1)
(a1, a2) <$ writePVar pvar1 a2
{-# INLINE swapPVars #-}
swapPVars_ :: (PrimMonad m, Prim a) => PVar m a -> PVar m a -> m ()
swapPVars_ pvar1 pvar2 = void $ swapPVars pvar1 pvar2
{-# INLINE swapPVars_ #-}
withStorablePVar ::
(PrimMonad m, S.Storable a)
=> a
-> (PVar m a -> Ptr a -> m b)
-> m b
withStorablePVar a f = do
pvar <- rawStorablePVar
runWithPokedPtr pvar a f
{-# INLINE withStorablePVar #-}
withAlignedStorablePVar ::
(PrimMonad m, S.Storable a)
=> a
-> (PVar m a -> Ptr a -> m b)
-> m b
withAlignedStorablePVar a f = do
pvar <- rawAlignedStorablePVar
runWithPokedPtr pvar a f
{-# INLINE withAlignedStorablePVar #-}
atomicReadIntPVar :: PrimMonad m => PVar m Int -> m Int
atomicReadIntPVar (PVar mba#) =
primitive $ \s# ->
case atomicReadIntArray# mba# 0# s# of
(# s'#, i# #) -> (# s'#, I# i# #)
{-# INLINE atomicReadIntPVar #-}
atomicWriteIntPVar :: PrimMonad m => PVar m Int -> Int -> m ()
atomicWriteIntPVar (PVar mba#) a = primitive_ (atomicWriteIntArray# mba# 0# (unI# a))
{-# INLINE atomicWriteIntPVar #-}
atomicFetchModifyIntPVar ::
PrimMonad m => PVar m Int -> (Int -> Int) -> m Int
atomicFetchModifyIntPVar pvar f =
atomicModifyIntPVar pvar $ \a ->
let a' = f a
in a' `seq` (a', a)
{-# INLINE atomicFetchModifyIntPVar #-}
atomicModifyFetchIntPVar ::
PrimMonad m => PVar m Int -> (Int -> Int) -> m Int
atomicModifyFetchIntPVar pvar f =
atomicModifyIntPVar pvar $ \a ->
let a' = f a
in a' `seq` (a', a')
{-# INLINE atomicModifyFetchIntPVar #-}
casIntPVar ::
PrimMonad m
=> PVar m Int
-> Int
-> Int
-> m Int
casIntPVar (PVar mba#) old new =
primitive $ \s# ->
case casIntArray# mba# 0# (unI# old) (unI# new) s# of
(# s'#, i'# #) -> (# s'#, I# i'# #)
{-# INLINE casIntPVar #-}
atomicAddIntPVar :: PrimMonad m => PVar m Int -> Int -> m Int
atomicAddIntPVar (PVar mba#) a =
primitive $ \s# ->
case fetchAddIntArray# mba# 0# (unI# a) s# of
(# s'#, p# #) -> (# s'#, I# p# #)
{-# INLINE atomicAddIntPVar #-}
atomicSubIntPVar :: PrimMonad m => PVar m Int -> Int -> m Int
atomicSubIntPVar (PVar mba#) a =
primitive $ \s# ->
case fetchSubIntArray# mba# 0# (unI# a) s# of
(# s'#, p# #) -> (# s'#, I# p# #)
{-# INLINE atomicSubIntPVar #-}
atomicAndIntPVar :: PrimMonad m => PVar m Int -> Int -> m Int
atomicAndIntPVar (PVar mba#) a =
primitive $ \s# ->
case fetchAndIntArray# mba# 0# (unI# a) s# of
(# s'#, p# #) -> (# s'#, I# p# #)
{-# INLINE atomicAndIntPVar #-}
atomicNandIntPVar :: PrimMonad m => PVar m Int -> Int -> m Int
atomicNandIntPVar (PVar mba#) a =
primitive $ \s# ->
case fetchNandIntArray# mba# 0# (unI# a) s# of
(# s'#, p# #) -> (# s'#, I# p# #)
{-# INLINE atomicNandIntPVar #-}
atomicOrIntPVar :: PrimMonad m => PVar m Int -> Int -> m Int
atomicOrIntPVar (PVar mba#) a =
primitive $ \s# ->
case fetchOrIntArray# mba# 0# (unI# a) s# of
(# s'#, p# #) -> (# s'#, I# p# #)
{-# INLINE atomicOrIntPVar #-}
atomicXorIntPVar :: PrimMonad m => PVar m Int -> Int -> m Int
atomicXorIntPVar (PVar mba#) a =
primitive $ \s# ->
case fetchXorIntArray# mba# 0# (unI# a) s# of
(# s'#, p# #) -> (# s'#, I# p# #)
{-# INLINE atomicXorIntPVar #-}
atomicNotIntPVar :: PrimMonad m => PVar m Int -> m Int
atomicNotIntPVar (PVar mba#) =
primitive $ \s# ->
case fetchXorIntArray# mba# 0# fullInt# s# of
(# s'#, p# #) -> (# s'#, I# p# #)
where
fullInt# =
case maxBound :: Word of
W# w# -> word2Int# w#
{-# INLINE atomicNotIntPVar #-}