module Data.IORef.Unboxed
(
IORefU
, newIORefU
, readIORefU
, writeIORefU
, modifyIORefU
, Counter
, newCounter
, atomicAddCounter
, atomicSubCounter
, atomicAndCounter
, atomicNandCounter
, atomicOrCounter
, atomicXorCounter
) where
import Data.Primitive.Types
import Data.Primitive.ByteArray
import GHC.Prim
import GHC.Types
import GHC.ST
import Control.Monad.ST.Unsafe (unsafeSTToIO)
import Data.STRef.Unboxed.Internal
newtype IORefU a = IORefU (STRefU RealWorld a)
newIORefU :: Prim a => a -> IO (IORefU a)
newIORefU init = IORefU `fmap` unsafeSTToIO (newSTRefU init)
readIORefU :: Prim a => IORefU a -> IO a
readIORefU (IORefU stRefU) = unsafeSTToIO (readSTRefU stRefU)
writeIORefU :: Prim a => IORefU a -> a -> IO ()
writeIORefU (IORefU stRefU) x = unsafeSTToIO (writeSTRefU stRefU x)
modifyIORefU :: Prim a => IORefU a -> (a -> a) -> IO ()
modifyIORefU ref f = readIORefU ref >>= writeIORefU ref . f
type Counter = IORefU Int
newCounter :: Int -> IO Counter
newCounter = newIORefU
atomicAddCounter :: Counter -> Int -> IO Int
atomicAddCounter (IORefU (STRefU (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->
let (# s2#, res #) = fetchAddIntArray# mba# 0# x# s1# in (# s2#, (I# (res +# x#)) #)
atomicSubCounter :: Counter -> Int -> IO Int
atomicSubCounter (IORefU (STRefU (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->
let (# s2#, res #) = fetchSubIntArray# mba# 0# x# s1# in (# s2#, (I# (res -# x#)) #)
atomicAndCounter :: Counter -> Int -> IO Int
atomicAndCounter (IORefU (STRefU (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->
let (# s2#, res #) = fetchAndIntArray# mba# 0# x# s1# in (# s2#, (I# (res `andI#` x#)) #)
atomicNandCounter :: Counter -> Int -> IO Int
atomicNandCounter (IORefU (STRefU (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->
let (# s2#, res #) = fetchNandIntArray# mba# 0# x# s1# in (# s2#, (I# (notI# (res `andI#` x#))) #)
atomicOrCounter :: Counter -> Int -> IO Int
atomicOrCounter (IORefU (STRefU (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->
let (# s2#, res #) = fetchOrIntArray# mba# 0# x# s1# in (# s2#, (I# (res `orI#` x#)) #)
atomicXorCounter :: Counter -> Int -> IO Int
atomicXorCounter (IORefU (STRefU (MutableByteArray mba#))) (I# x#) = IO $ \ s1# ->
let (# s2#, res #) = fetchXorIntArray# mba# 0# x# s1# in (# s2#, (I# (res `xorI#` x#)) #)