{-|
Module      :  Z.Data.PrimRef.PrimRef
Description :  Primitive references
Copyright   :  (c) Dong Han 2017~2019
License     :  BSD-style

Maintainer  :  winterland1989@gmail.com
Stability   :  experimental
Portability :  portable

This package provide fast primitive references for primitive monad, such as ST or IO. Unboxed reference is implemented using single cell @MutableByteArray\/MutableUnliftedArray@ s to eliminate indirection overhead which MutVar# s a carry, on the otherhand primitive reference only support limited type(instances of 'Prim\/PrimUnlifted' class).
-}


module Z.Data.PrimRef
  ( -- * Prim references
    PrimRef(..), PrimIORef
  , newPrimRef
  , readPrimRef
  , writePrimRef
  , modifyPrimRef
  , Prim(..)
    -- * Unlifted references
  , UnliftedRef(..)
  , newUnliftedRef
  , readUnliftedRef
  , writeUnliftedRef
  , modifyUnliftedRef
  , PrimUnlifted(..)
    -- * Atomic operations for @PrimIORef Int@
  , Counter
  , newCounter
  , readCounter
  , writeCounter
  , modifyCounter
    -- ** return value BEFORE atomic operation
  , atomicAddCounter
  , atomicSubCounter
  , atomicAndCounter
  , atomicNandCounter
  , atomicOrCounter
  , atomicXorCounter
    -- ** return value AFTER atomic operation
  , atomicAddCounter'
  , atomicSubCounter'
  , atomicAndCounter'
  , atomicNandCounter'
  , atomicOrCounter'
  , atomicXorCounter'
    -- ** without returning
  , atomicAddCounter_
  , atomicSubCounter_
  , atomicAndCounter_
  , atomicNandCounter_
  , atomicOrCounter_
  , atomicXorCounter_
  ) where

import Control.Monad.Primitive
import Data.Primitive.Types
import Data.Primitive.ByteArray
import GHC.Exts
import GHC.IO
import Z.Data.Array.UnliftedArray

-- | A mutable variable in the 'PrimMonad' which can hold an instance of 'Prim'.
--
newtype PrimRef s a = PrimRef (MutableByteArray s)

-- | Type alias for 'PrimRef' in IO.
type PrimIORef a = PrimRef RealWorld a

-- | Build a new 'PrimRef'
--
newPrimRef :: (Prim a, PrimMonad m) => a -> m (PrimRef (PrimState m) a)
newPrimRef :: a -> m (PrimRef (PrimState m) a)
newPrimRef a
x = do
     MutableByteArray (PrimState m)
mba <- Int -> m (MutableByteArray (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray (Int# -> Int
I# (a -> Int#
forall a. Prim a => a -> Int#
sizeOf# a
x))
     MutableByteArray (PrimState m) -> Int -> a -> m ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray (PrimState m)
mba Int
0 a
x
     PrimRef (PrimState m) a -> m (PrimRef (PrimState m) a)
forall (m :: * -> *) a. Monad m => a -> m a
return (MutableByteArray (PrimState m) -> PrimRef (PrimState m) a
forall k s (a :: k). MutableByteArray s -> PrimRef s a
PrimRef MutableByteArray (PrimState m)
mba)
{-# INLINE newPrimRef #-}

-- | Read the value of an 'PrimRef'
--
readPrimRef :: (Prim a, PrimMonad m) => PrimRef (PrimState m) a -> m a
readPrimRef :: PrimRef (PrimState m) a -> m a
readPrimRef (PrimRef MutableByteArray (PrimState m)
mba) = MutableByteArray (PrimState m) -> Int -> m a
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> m a
readByteArray MutableByteArray (PrimState m)
mba Int
0
{-# INLINE readPrimRef #-}

-- | Write a new value into an 'PrimRef'
--
writePrimRef :: (Prim a, PrimMonad m) => PrimRef (PrimState m) a -> a -> m ()
writePrimRef :: PrimRef (PrimState m) a -> a -> m ()
writePrimRef (PrimRef MutableByteArray (PrimState m)
mba) a
x = MutableByteArray (PrimState m) -> Int -> a -> m ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray (PrimState m)
mba Int
0 a
x
{-# INLINE writePrimRef #-}

-- | Mutate the contents of an 'PrimRef'.
--
--  Unboxed reference is always strict on the value it hold.
--
modifyPrimRef :: (Prim a, PrimMonad m) => PrimRef (PrimState m) a -> (a -> a) -> m ()
modifyPrimRef :: PrimRef (PrimState m) a -> (a -> a) -> m ()
modifyPrimRef PrimRef (PrimState m) a
ref a -> a
f = PrimRef (PrimState m) a -> m a
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
PrimRef (PrimState m) a -> m a
readPrimRef PrimRef (PrimState m) a
ref m a -> (a -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= PrimRef (PrimState m) a -> a -> m ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
PrimRef (PrimState m) a -> a -> m ()
writePrimRef PrimRef (PrimState m) a
ref (a -> m ()) -> (a -> a) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
f
{-# INLINE modifyPrimRef #-}

-- | Alias for 'PrimIORef Int' which support several atomic operations.
type Counter = PrimRef RealWorld Int

-- | Build a new 'Counter'
newCounter :: Int -> IO Counter
newCounter :: Int -> IO Counter
newCounter = Int -> IO Counter
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
a -> m (PrimRef (PrimState m) a)
newPrimRef
{-# INLINE newCounter #-}

-- | Read the value of an 'Counter'.
readCounter :: Counter -> IO Int
readCounter :: Counter -> IO Int
readCounter = Counter -> IO Int
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
PrimRef (PrimState m) a -> m a
readPrimRef
{-# INLINE readCounter #-}

-- | Write a new value into an 'Counter'(non-atomically).
writeCounter :: Counter -> Int -> IO ()
writeCounter :: Counter -> Int -> IO ()
writeCounter = Counter -> Int -> IO ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
PrimRef (PrimState m) a -> a -> m ()
writePrimRef
{-# INLINE writeCounter #-}

-- | Mutate the contents of an 'Counter'(non-atomically).
modifyCounter :: Counter -> (Int -> Int) -> IO ()
modifyCounter :: Counter -> (Int -> Int) -> IO ()
modifyCounter = Counter -> (Int -> Int) -> IO ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
PrimRef (PrimState m) a -> (a -> a) -> m ()
modifyPrimRef
{-# INLINE modifyCounter #-}

-- | Atomically add a 'Counter', return the value AFTER added.
atomicAddCounter' :: Counter -> Int -> IO Int
{-# INLINE atomicAddCounter' #-}
atomicAddCounter' :: Counter -> Int -> IO Int
atomicAddCounter' (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAddIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res# Int# -> Int# -> Int#
+# Int#
x#)) #)

-- | Atomically add a 'Counter', return the value BEFORE added.
atomicAddCounter :: Counter -> Int -> IO Int
{-# INLINE atomicAddCounter #-}
atomicAddCounter :: Counter -> Int -> IO Int
atomicAddCounter (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAddIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# Int#
res#) #)

-- | Atomically add a 'Counter'.
atomicAddCounter_ :: Counter -> Int -> IO ()
atomicAddCounter_ :: Counter -> Int -> IO ()
atomicAddCounter_ (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
_ #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAddIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, () #)
{-# INLINE atomicAddCounter_ #-}


-- | Atomically sub a 'Counter', return the value AFTER subbed.
atomicSubCounter' :: Counter -> Int -> IO Int
{-# INLINE atomicSubCounter' #-}
atomicSubCounter' :: Counter -> Int -> IO Int
atomicSubCounter' (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchSubIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res# Int# -> Int# -> Int#
-# Int#
x#)) #)

-- | Atomically sub a 'Counter', return the value BEFORE subbed.
atomicSubCounter :: Counter -> Int -> IO Int
{-# INLINE atomicSubCounter #-}
atomicSubCounter :: Counter -> Int -> IO Int
atomicSubCounter (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchSubIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# Int#
res#) #)

-- | Atomically sub a 'Counter'
atomicSubCounter_ :: Counter -> Int -> IO ()
atomicSubCounter_ :: Counter -> Int -> IO ()
atomicSubCounter_ (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
_ #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchSubIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, () #)
{-# INLINE atomicSubCounter_ #-}

-- | Atomically and a 'Counter', return the value AFTER anded.
atomicAndCounter' :: Counter -> Int -> IO Int
atomicAndCounter' :: Counter -> Int -> IO Int
atomicAndCounter' (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAndIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res# Int# -> Int# -> Int#
`andI#` Int#
x#)) #)
{-# INLINE atomicAndCounter' #-}

-- | Atomically and a 'Counter', return the value BEFORE anded.
atomicAndCounter :: Counter -> Int -> IO Int
atomicAndCounter :: Counter -> Int -> IO Int
atomicAndCounter (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAndIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# Int#
res#) #)
{-# INLINE atomicAndCounter #-}

-- | Atomically and a 'Counter'
atomicAndCounter_ :: Counter -> Int -> IO ()
atomicAndCounter_ :: Counter -> Int -> IO ()
atomicAndCounter_ (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
_ #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAndIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, () #)
{-# INLINE atomicAndCounter_ #-}

-- | Atomically nand a 'Counter', return the value AFTER nanded.
atomicNandCounter' :: Counter -> Int -> IO Int
atomicNandCounter' :: Counter -> Int -> IO Int
atomicNandCounter' (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchNandIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# (Int# -> Int#
notI# (Int#
res# Int# -> Int# -> Int#
`andI#` Int#
x#))) #)
{-# INLINE atomicNandCounter' #-}

-- | Atomically nand a 'Counter', return the value BEFORE nanded.
atomicNandCounter :: Counter -> Int -> IO Int
atomicNandCounter :: Counter -> Int -> IO Int
atomicNandCounter (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchNandIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# Int#
res#) #)
{-# INLINE atomicNandCounter #-}

-- | Atomically nand a 'Counter'
atomicNandCounter_ :: Counter -> Int -> IO ()
atomicNandCounter_ :: Counter -> Int -> IO ()
atomicNandCounter_ (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
_ #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchNandIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, () #)
{-# INLINE atomicNandCounter_ #-}

-- | Atomically or a 'Counter', return the value AFTER ored.
atomicOrCounter' :: Counter -> Int -> IO Int
atomicOrCounter' :: Counter -> Int -> IO Int
atomicOrCounter' (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchOrIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res# Int# -> Int# -> Int#
`orI#` Int#
x#)) #)
{-# INLINE atomicOrCounter' #-}

-- | Atomically or a 'Counter', return the value BEFORE ored.
atomicOrCounter :: Counter -> Int -> IO Int
atomicOrCounter :: Counter -> Int -> IO Int
atomicOrCounter (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchOrIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# Int#
res#) #)
{-# INLINE atomicOrCounter #-}

-- | Atomically or a 'Counter'
atomicOrCounter_ :: Counter -> Int -> IO ()
atomicOrCounter_ :: Counter -> Int -> IO ()
atomicOrCounter_ (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
_ #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchOrIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, () #)
{-# INLINE atomicOrCounter_ #-}

-- | Atomically xor a 'Counter', return the value AFTER xored.
atomicXorCounter' :: Counter -> Int -> IO Int
atomicXorCounter' :: Counter -> Int -> IO Int
atomicXorCounter' (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchXorIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res# Int# -> Int# -> Int#
`xorI#` Int#
x#)) #)
{-# INLINE atomicXorCounter' #-}

-- | Atomically xor a 'Counter', return the value BEFORE xored.
atomicXorCounter :: Counter -> Int -> IO Int
atomicXorCounter :: Counter -> Int -> IO Int
atomicXorCounter (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int)
-> (State# RealWorld -> (# State# RealWorld, Int #)) -> IO Int
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchXorIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, (Int# -> Int
I# Int#
res#) #)
{-# INLINE atomicXorCounter #-}

-- | Atomically xor a 'Counter'
atomicXorCounter_ :: Counter -> Int -> IO ()
atomicXorCounter_ :: Counter -> Int -> IO ()
atomicXorCounter_ (PrimRef (MutableByteArray MutableByteArray# RealWorld
mba#)) (I# Int#
x#) = (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, () #)) -> IO ())
-> (State# RealWorld -> (# State# RealWorld, () #)) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
s1# ->
    let !(# State# RealWorld
s2#, Int#
_ #) = MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchXorIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
x# State# RealWorld
s1# in (# State# RealWorld
s2#, () #)
{-# INLINE atomicXorCounter_ #-}

-- | A mutable variable in the 'PrimMonad' which can hold an instance of 'PrimUnlifted'.
--
newtype UnliftedRef s a = UnliftedRef (MutableUnliftedArray s a)

-- | Build a new 'UnliftedRef'
--
newUnliftedRef :: (PrimUnlifted a, PrimMonad m) => a -> m (UnliftedRef (PrimState m) a)
newUnliftedRef :: a -> m (UnliftedRef (PrimState m) a)
newUnliftedRef a
x = do
     MutableUnliftedArray (PrimState m) a
mba <- Int -> a -> m (MutableUnliftedArray (PrimState m) a)
forall (m :: * -> *) a.
(PrimMonad m, PrimUnlifted a) =>
Int -> a -> m (MutableUnliftedArray (PrimState m) a)
newUnliftedArray Int
1 a
x
     UnliftedRef (PrimState m) a -> m (UnliftedRef (PrimState m) a)
forall (m :: * -> *) a. Monad m => a -> m a
return (MutableUnliftedArray (PrimState m) a -> UnliftedRef (PrimState m) a
forall k s (a :: k). MutableUnliftedArray s a -> UnliftedRef s a
UnliftedRef MutableUnliftedArray (PrimState m) a
mba)
{-# INLINE newUnliftedRef #-}

-- | Read the value of an 'UnliftedRef'
--
readUnliftedRef :: (PrimUnlifted a, PrimMonad m) => UnliftedRef (PrimState m) a -> m a
readUnliftedRef :: UnliftedRef (PrimState m) a -> m a
readUnliftedRef (UnliftedRef MutableUnliftedArray (PrimState m) a
mba) = MutableUnliftedArray (PrimState m) a -> Int -> m a
forall (m :: * -> *) a.
(PrimMonad m, PrimUnlifted a) =>
MutableUnliftedArray (PrimState m) a -> Int -> m a
readUnliftedArray MutableUnliftedArray (PrimState m) a
mba Int
0
{-# INLINE readUnliftedRef #-}

-- | Write a new value into an 'UnliftedRef'
--
writeUnliftedRef :: (PrimUnlifted a, PrimMonad m) => UnliftedRef (PrimState m) a -> a -> m ()
writeUnliftedRef :: UnliftedRef (PrimState m) a -> a -> m ()
writeUnliftedRef (UnliftedRef MutableUnliftedArray (PrimState m) a
mba) a
x = MutableUnliftedArray (PrimState m) a -> Int -> a -> m ()
forall (m :: * -> *) a.
(PrimMonad m, PrimUnlifted a) =>
MutableUnliftedArray (PrimState m) a -> Int -> a -> m ()
writeUnliftedArray MutableUnliftedArray (PrimState m) a
mba Int
0 a
x
{-# INLINE writeUnliftedRef #-}

-- | Mutate the contents of an 'UnliftedRef'.
--
--  Unlifted reference is always strict on the value it hold.
--
modifyUnliftedRef :: (PrimUnlifted a, PrimMonad m) => UnliftedRef (PrimState m) a -> (a -> a) -> m ()
modifyUnliftedRef :: UnliftedRef (PrimState m) a -> (a -> a) -> m ()
modifyUnliftedRef UnliftedRef (PrimState m) a
ref a -> a
f = UnliftedRef (PrimState m) a -> m a
forall a (m :: * -> *).
(PrimUnlifted a, PrimMonad m) =>
UnliftedRef (PrimState m) a -> m a
readUnliftedRef UnliftedRef (PrimState m) a
ref m a -> (a -> m ()) -> m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= UnliftedRef (PrimState m) a -> a -> m ()
forall a (m :: * -> *).
(PrimUnlifted a, PrimMonad m) =>
UnliftedRef (PrimState m) a -> a -> m ()
writeUnliftedRef UnliftedRef (PrimState m) a
ref (a -> m ()) -> (a -> a) -> a -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
f
{-# INLINE modifyUnliftedRef #-}