module Data.Atomics.Counter.Fat (
AtomicCounter()
, newCounter
, incrCounter
, readCounter
) where
import Data.Primitive.MachDeps(sIZEOF_INT)
import Control.Monad.Primitive(RealWorld)
import Data.Primitive.ByteArray
import Data.Atomics(fetchAddIntArray)
import Control.Exception(assert)
newtype AtomicCounter = AtomicCounter (MutableByteArray RealWorld)
sIZEOF_CACHELINE :: Int
{-# INLINE sIZEOF_CACHELINE #-}
sIZEOF_CACHELINE = 64
newCounter :: Int -> IO AtomicCounter
{-# INLINE newCounter #-}
newCounter n = do
arr <- newAlignedPinnedByteArray
sIZEOF_CACHELINE
sIZEOF_CACHELINE
writeByteArray arr 0 n
assert (sIZEOF_INT < sIZEOF_CACHELINE) $
return (AtomicCounter arr)
incrCounter :: Int -> AtomicCounter -> IO Int
{-# INLINE incrCounter #-}
incrCounter incr (AtomicCounter arr) =
fetchAddIntArray arr 0 incr
readCounter :: AtomicCounter -> IO Int
{-# INLINE readCounter #-}
readCounter (AtomicCounter arr) =
readByteArray arr 0