{-# LANGUAGE BangPatterns, MagicHash, UnboxedTuples, CPP #-}
module Data.Atomics.Counter
(
AtomicCounter,
newCounter,
CTicket, peekCTicket,
casCounter, incrCounter, incrCounter_,
readCounter, readCounterForCAS,
writeCounter
)
where
import Data.Atomics.Internal
import GHC.Base hiding ((==#))
import qualified GHC.PrimopWrappers as GPW
(==#) :: Int# -> Int# -> Bool
==# :: Int# -> Int# -> Bool
(==#) Int#
x Int#
y = case Int#
x Int# -> Int# -> Int#
GPW.==# Int#
y of { Int#
0# -> Bool
False; Int#
_ -> Bool
True }
#ifndef __GLASGOW_HASKELL__
#error "Counter: this library is not portable to other Haskell's"
#endif
#include "MachDeps.h"
#ifndef SIZEOF_HSINT
#define SIZEOF_HSINT INT_SIZE_IN_BYTES
#endif
data AtomicCounter = AtomicCounter (MutableByteArray# RealWorld)
type CTicket = Int
{-# INLINE newCounter #-}
newCounter :: Int -> IO AtomicCounter
newCounter :: Int -> IO AtomicCounter
newCounter Int
n = do
AtomicCounter
c <- IO AtomicCounter
newRawCounter
AtomicCounter -> Int -> IO ()
writeCounter AtomicCounter
c Int
n
AtomicCounter -> IO AtomicCounter
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return AtomicCounter
c
{-# INLINE newRawCounter #-}
newRawCounter :: IO AtomicCounter
newRawCounter :: IO AtomicCounter
newRawCounter = (State# RealWorld -> (# State# RealWorld, AtomicCounter #))
-> IO AtomicCounter
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, AtomicCounter #))
-> IO AtomicCounter)
-> (State# RealWorld -> (# State# RealWorld, AtomicCounter #))
-> IO AtomicCounter
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->
case Int#
-> State# RealWorld
-> (# State# RealWorld, MutableByteArray# RealWorld #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newByteArray# Int#
size State# RealWorld
s of { (# State# RealWorld
s', MutableByteArray# RealWorld
arr #) ->
(# State# RealWorld
s', MutableByteArray# RealWorld -> AtomicCounter
AtomicCounter MutableByteArray# RealWorld
arr #) }
where !(I# Int#
size) = SIZEOF_HSINT
{-# INLINE readCounter #-}
readCounter :: AtomicCounter -> IO Int
readCounter :: AtomicCounter -> IO Int
readCounter (AtomicCounter MutableByteArray# RealWorld
arr) = (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
s ->
case MutableByteArray# RealWorld
-> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)
readIntArray# MutableByteArray# RealWorld
arr Int#
0# State# RealWorld
s of { (# State# RealWorld
s', Int#
i #) ->
(# State# RealWorld
s', Int# -> Int
I# Int#
i #) }
{-# INLINE writeCounter #-}
writeCounter :: AtomicCounter -> Int -> IO ()
writeCounter :: AtomicCounter -> Int -> IO ()
writeCounter (AtomicCounter MutableByteArray# RealWorld
arr) (I# Int#
i) = (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
s ->
case MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> State# RealWorld
forall d.
MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
writeIntArray# MutableByteArray# RealWorld
arr Int#
0# Int#
i State# RealWorld
s of { State# RealWorld
s' ->
(# State# RealWorld
s', () #) }
{-# INLINE readCounterForCAS #-}
readCounterForCAS :: AtomicCounter -> IO CTicket
readCounterForCAS :: AtomicCounter -> IO Int
readCounterForCAS = AtomicCounter -> IO Int
readCounter
{-# INLINE peekCTicket #-}
peekCTicket :: CTicket -> Int
peekCTicket :: Int -> Int
peekCTicket !Int
x = Int
x
{-# INLINE casCounter #-}
casCounter :: AtomicCounter -> CTicket -> Int -> IO (Bool, CTicket)
casCounter :: AtomicCounter -> Int -> Int -> IO (Bool, Int)
casCounter (AtomicCounter MutableByteArray# RealWorld
mba#) (I# Int#
old#) newBox :: Int
newBox@(I# Int#
new#) = (State# RealWorld -> (# State# RealWorld, (Bool, Int) #))
-> IO (Bool, Int)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO((State# RealWorld -> (# State# RealWorld, (Bool, Int) #))
-> IO (Bool, Int))
-> (State# RealWorld -> (# State# RealWorld, (Bool, Int) #))
-> IO (Bool, Int)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s1# ->
let (# State# RealWorld
s2#, Int#
res# #) = MutableByteArray# RealWorld
-> Int#
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> Int# -> State# d -> (# State# d, Int# #)
casIntArray# MutableByteArray# RealWorld
mba# Int#
0# Int#
old# Int#
new# State# RealWorld
s1# in
case Int#
res# Int# -> Int# -> Bool
==# Int#
old# of
Bool
False -> (# State# RealWorld
s2#, (Bool
False, Int# -> Int
I# Int#
res# ) #)
Bool
True -> (# State# RealWorld
s2#, (Bool
True , Int
newBox ) #)
{-# INLINE incrCounter #-}
incrCounter :: Int -> AtomicCounter -> IO Int
incrCounter :: Int -> AtomicCounter -> IO Int
incrCounter (I# Int#
incr#) (AtomicCounter MutableByteArray# RealWorld
mba#) = (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#
incr# State# RealWorld
s1# in
(# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res Int# -> Int# -> Int#
+# Int#
incr#)) #)
{-# INLINE incrCounter_ #-}
incrCounter_ :: Int -> AtomicCounter -> IO ()
incrCounter_ :: Int -> AtomicCounter -> IO ()
incrCounter_ (I# Int#
incr#) (AtomicCounter MutableByteArray# RealWorld
mba#) = (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#
incr# State# RealWorld
s1# in
(# State# RealWorld
s2#, () #)