{-# LANGUAGE MagicHash, UnboxedTuples, ScopedTypeVariables, BangPatterns, CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
#if __GLASGOW_HASKELL__ >= 909
{-# LANGUAGE GHCForeignImportPrim #-}
{-# LANGUAGE UnliftedFFITypes #-}
#endif
module Data.Atomics
(
Ticket, peekTicket,
readForCAS, casIORef, casIORef2,
atomicModifyIORefCAS, atomicModifyIORefCAS_,
casArrayElem, casArrayElem2, readArrayElem,
casByteArrayInt,
fetchAddIntArray,
fetchSubIntArray,
fetchAndIntArray,
fetchNandIntArray,
fetchOrIntArray,
fetchXorIntArray,
readMutVarForCAS, casMutVar, casMutVar2,
storeLoadBarrier, loadLoadBarrier, writeBarrier,
fetchAddByteArrayInt
) where
import Control.Exception (evaluate)
import Data.Primitive.Array (MutableArray(MutableArray))
import Data.Primitive.ByteArray (MutableByteArray(MutableByteArray))
import Data.Atomics.Internal
import Data.IORef
import GHC.IORef hiding (atomicModifyIORef)
import GHC.STRef
import GHC.Exts hiding ((==#))
import qualified GHC.PrimopWrappers as GPW
import GHC.IO (IO(IO))
#ifdef DEBUG_ATOMICS
#warning "Activating DEBUG_ATOMICS... NOINLINE's and more"
{-# NOINLINE seal #-}
{-# NOINLINE casIORef #-}
{-# NOINLINE casArrayElem2 #-}
{-# NOINLINE readArrayElem #-}
{-# NOINLINE readForCAS #-}
{-# NOINLINE casArrayElem #-}
{-# NOINLINE casIORef2 #-}
{-# NOINLINE readMutVarForCAS #-}
{-# NOINLINE casMutVar #-}
{-# NOINLINE casMutVar2 #-}
{-# NOINLINE casByteArrayInt #-}
{-# NOINLINE fetchAddIntArray #-}
{-# NOINLINE fetchSubIntArray #-}
{-# NOINLINE fetchAndIntArray #-}
{-# NOINLINE fetchNandIntArray #-}
{-# NOINLINE fetchOrIntArray #-}
{-# NOINLINE fetchXorIntArray #-}
#else
{-# INLINE casIORef #-}
{-# INLINE casArrayElem2 #-}
{-# INLINE readArrayElem #-}
{-# INLINE readForCAS #-}
{-# INLINE casArrayElem #-}
{-# INLINE casIORef2 #-}
{-# INLINE readMutVarForCAS #-}
{-# INLINE casMutVar #-}
{-# INLINE casMutVar2 #-}
{-# INLINE fetchAddIntArray #-}
{-# INLINE fetchSubIntArray #-}
{-# INLINE fetchAndIntArray #-}
{-# INLINE fetchNandIntArray #-}
{-# INLINE fetchOrIntArray #-}
{-# INLINE fetchXorIntArray #-}
#endif
(==#) :: 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 }
casArrayElem :: MutableArray RealWorld a -> Int -> Ticket a -> a -> IO (Bool, Ticket a)
casArrayElem :: forall a.
MutableArray RealWorld a
-> Int -> Ticket a -> a -> IO (Bool, Ticket a)
casArrayElem MutableArray RealWorld a
arr Int
i Ticket a
old !a
new = MutableArray RealWorld a
-> Int -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
forall a.
MutableArray RealWorld a
-> Int -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casArrayElem2 MutableArray RealWorld a
arr Int
i Ticket a
old (a -> Ticket a
forall a. a -> Ticket a
seal a
new)
casArrayElem2 :: MutableArray RealWorld a -> Int -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casArrayElem2 :: forall a.
MutableArray RealWorld a
-> Int -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casArrayElem2 (MutableArray MutableArray# RealWorld a
arr#) (I# Int#
i#) Ticket a
old Ticket a
new = (State# RealWorld -> (# State# RealWorld, (Bool, Ticket a) #))
-> IO (Bool, Ticket a)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO((State# RealWorld -> (# State# RealWorld, (Bool, Ticket a) #))
-> IO (Bool, Ticket a))
-> (State# RealWorld -> (# State# RealWorld, (Bool, Ticket a) #))
-> IO (Bool, Ticket a)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s1# ->
case MutableArray# RealWorld a
-> Int#
-> Ticket a
-> Ticket a
-> State# RealWorld
-> (# State# RealWorld, Int#, Ticket a #)
forall a.
MutableArray# RealWorld a
-> Int#
-> Ticket a
-> Ticket a
-> State# RealWorld
-> (# State# RealWorld, Int#, Ticket a #)
casArrayTicketed# MutableArray# RealWorld a
arr# Int#
i# Ticket a
old Ticket a
new State# RealWorld
s1# of
(# State# RealWorld
s2#, Int#
x#, Ticket a
res #) -> (# State# RealWorld
s2#, (Int#
x# Int# -> Int# -> Bool
==# Int#
0#, Ticket a
res) #)
readArrayElem :: forall a . MutableArray RealWorld a -> Int -> IO (Ticket a)
readArrayElem :: forall a. MutableArray RealWorld a -> Int -> IO (Ticket a)
readArrayElem (MutableArray MutableArray# RealWorld a
arr#) (I# Int#
i#) = (State# RealWorld -> (# State# RealWorld, Ticket a #))
-> IO (Ticket a)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO ((State# RealWorld -> (# State# RealWorld, Ticket a #))
-> IO (Ticket a))
-> (State# RealWorld -> (# State# RealWorld, Ticket a #))
-> IO (Ticket a)
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
st -> (# State# RealWorld, a #) -> (# State# RealWorld, Ticket a #)
forall a b. a -> b
unsafeCoerce# (State# RealWorld -> (# State# RealWorld, a #)
fn State# RealWorld
st)
where
fn :: State# RealWorld -> (# State# RealWorld, a #)
fn :: State# RealWorld -> (# State# RealWorld, a #)
fn = MutableArray# RealWorld a
-> Int# -> State# RealWorld -> (# State# RealWorld, a #)
forall d a.
MutableArray# d a -> Int# -> State# d -> (# State# d, a #)
readArray# MutableArray# RealWorld a
arr# Int#
i#
casByteArrayInt :: MutableByteArray RealWorld -> Int -> Int -> Int -> IO Int
casByteArrayInt :: MutableByteArray RealWorld -> Int -> Int -> Int -> IO Int
casByteArrayInt (MutableByteArray MutableByteArray# RealWorld
mba#) (I# Int#
ix#) (I# Int#
old#) (I# Int#
new#) =
(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#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> Int# -> State# d -> (# State# d, Int# #)
casIntArray# MutableByteArray# RealWorld
mba# Int#
ix# Int#
old# Int#
new# State# RealWorld
s1# in
(# State# RealWorld
s2#, (Int# -> Int
I# Int#
res) #)
fetchAddIntArray :: MutableByteArray RealWorld
-> Int
-> Int
-> IO Int
fetchAddIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchAddIntArray (MutableByteArray MutableByteArray# RealWorld
mba#) (I# Int#
offset#) (I# Int#
incr#) = (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#
offset# Int#
incr# State# RealWorld
s1# in
(# State# RealWorld
s2#, (Int# -> Int
I# Int#
res) #)
fetchSubIntArray :: MutableByteArray RealWorld
-> Int
-> Int
-> IO Int
fetchSubIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchSubIntArray = (MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchSubIntArray#
fetchAndIntArray :: MutableByteArray RealWorld
-> Int
-> Int
-> IO Int
fetchAndIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchAndIntArray = (MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchAndIntArray#
fetchNandIntArray :: MutableByteArray RealWorld
-> Int
-> Int
-> IO Int
fetchNandIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchNandIntArray = (MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchNandIntArray#
fetchOrIntArray :: MutableByteArray RealWorld
-> Int
-> Int
-> IO Int
fetchOrIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchOrIntArray = (MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchOrIntArray#
fetchXorIntArray :: MutableByteArray RealWorld
-> Int
-> Int
-> IO Int
fetchXorIntArray :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchXorIntArray = (MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
forall d.
MutableByteArray# d
-> Int# -> Int# -> State# d -> (# State# d, Int# #)
fetchXorIntArray#
{-# INLINE doAtomicRMW #-}
doAtomicRMW :: (MutableByteArray# RealWorld -> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW :: (MutableByteArray# RealWorld
-> Int#
-> Int#
-> State# RealWorld
-> (# State# RealWorld, Int# #))
-> MutableByteArray RealWorld -> Int -> Int -> IO Int
doAtomicRMW MutableByteArray# RealWorld
-> Int# -> Int# -> State# RealWorld -> (# State# RealWorld, Int# #)
atomicOp# =
\(MutableByteArray MutableByteArray# RealWorld
mba#) (I# Int#
offset#) (I# Int#
val#) ->
(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# #)
atomicOp# MutableByteArray# RealWorld
mba# Int#
offset# Int#
val# State# RealWorld
s1# in
(# State# RealWorld
s2#, (Int# -> Int
I# Int#
res) #)
{-# DEPRECATED fetchAddByteArrayInt "Replaced by fetchAddIntArray which returns the OLD value" #-}
fetchAddByteArrayInt :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchAddByteArrayInt :: MutableByteArray RealWorld -> Int -> Int -> IO Int
fetchAddByteArrayInt (MutableByteArray MutableByteArray# RealWorld
mba#) (I# Int#
offset#) (I# Int#
incr#) = (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#
offset# Int#
incr# State# RealWorld
s1# in
(# State# RealWorld
s2#, (Int# -> Int
I# (Int#
res Int# -> Int# -> Int#
+# Int#
incr#)) #)
readForCAS :: IORef a -> IO ( Ticket a )
readForCAS :: forall a. IORef a -> IO (Ticket a)
readForCAS (IORef (STRef MutVar# RealWorld a
mv)) = MutVar# RealWorld a -> IO (Ticket a)
forall a. MutVar# RealWorld a -> IO (Ticket a)
readMutVarForCAS MutVar# RealWorld a
mv
casIORef :: IORef a
-> Ticket a
-> a
-> IO (Bool, Ticket a)
casIORef :: forall a. IORef a -> Ticket a -> a -> IO (Bool, Ticket a)
casIORef (IORef (STRef MutVar# RealWorld a
var)) Ticket a
old !a
new = MutVar# RealWorld a -> Ticket a -> a -> IO (Bool, Ticket a)
forall a.
MutVar# RealWorld a -> Ticket a -> a -> IO (Bool, Ticket a)
casMutVar MutVar# RealWorld a
var Ticket a
old a
new
casIORef2 :: IORef a
-> Ticket a
-> Ticket a
-> IO (Bool, Ticket a)
casIORef2 :: forall a. IORef a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casIORef2 (IORef (STRef MutVar# RealWorld a
var)) Ticket a
old Ticket a
new = MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
forall a.
MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casMutVar2 MutVar# RealWorld a
var Ticket a
old Ticket a
new
{-# NOINLINE peekTicket #-}
peekTicket :: Ticket a -> a
peekTicket :: forall a. Ticket a -> a
peekTicket = Ticket a -> a
forall a b. a -> b
unsafeCoerce#
seal :: a -> Ticket a
seal :: forall a. a -> Ticket a
seal = a -> Ticket a
forall a b. a -> b
unsafeCoerce#
readMutVarForCAS :: MutVar# RealWorld a -> IO ( Ticket a )
readMutVarForCAS :: forall a. MutVar# RealWorld a -> IO (Ticket a)
readMutVarForCAS MutVar# RealWorld a
mv = (State# RealWorld -> (# State# RealWorld, Ticket a #))
-> IO (Ticket a)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO((State# RealWorld -> (# State# RealWorld, Ticket a #))
-> IO (Ticket a))
-> (State# RealWorld -> (# State# RealWorld, Ticket a #))
-> IO (Ticket a)
forall a b. (a -> b) -> a -> b
$ \ State# RealWorld
st -> MutVar# RealWorld a
-> State# RealWorld -> (# State# RealWorld, Ticket a #)
forall a.
MutVar# RealWorld a
-> State# RealWorld -> (# State# RealWorld, Ticket a #)
readForCAS# MutVar# RealWorld a
mv State# RealWorld
st
casMutVar :: MutVar# RealWorld a -> Ticket a -> a -> IO (Bool, Ticket a)
casMutVar :: forall a.
MutVar# RealWorld a -> Ticket a -> a -> IO (Bool, Ticket a)
casMutVar MutVar# RealWorld a
mv Ticket a
tick !a
new =
MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
forall a.
MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casMutVar2 MutVar# RealWorld a
mv Ticket a
tick (a -> Ticket a
forall a. a -> Ticket a
seal a
new)
casMutVar2 :: MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casMutVar2 :: forall a.
MutVar# RealWorld a -> Ticket a -> Ticket a -> IO (Bool, Ticket a)
casMutVar2 MutVar# RealWorld a
mv Ticket a
tick Ticket a
new = (State# RealWorld -> (# State# RealWorld, (Bool, Ticket a) #))
-> IO (Bool, Ticket a)
forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO((State# RealWorld -> (# State# RealWorld, (Bool, Ticket a) #))
-> IO (Bool, Ticket a))
-> (State# RealWorld -> (# State# RealWorld, (Bool, Ticket a) #))
-> IO (Bool, Ticket a)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
st ->
case MutVar# RealWorld a
-> Ticket a
-> Ticket a
-> State# RealWorld
-> (# State# RealWorld, Int#, Ticket a #)
forall a.
MutVar# RealWorld a
-> Ticket a
-> Ticket a
-> State# RealWorld
-> (# State# RealWorld, Int#, Ticket a #)
casMutVarTicketed# MutVar# RealWorld a
mv Ticket a
tick Ticket a
new State# RealWorld
st of
(# State# RealWorld
st', Int#
flag, Ticket a
tick' #) ->
(# State# RealWorld
st', (Int#
flag Int# -> Int# -> Bool
==# Int#
0#, Ticket a
tick') #)
#if __GLASGOW_HASKELL__ >= 909
foreign import prim "hs_atomic_primops_store_load_barrier" storeLoadBarrier#
:: State# RealWorld -> State# RealWorld
storeLoadBarrier :: IO ()
storeLoadBarrier = IO $ \s -> case storeLoadBarrier# s of s' -> (# s', () #)
foreign import prim "hs_atomic_primops_load_load_barrier" loadLoadBarrier#
:: State# RealWorld -> State# RealWorld
loadLoadBarrier :: IO ()
loadLoadBarrier = IO $ \s -> case loadLoadBarrier# s of s' -> (# s', () #)
foreign import prim "hs_atomic_primops_write_barrier" writeBarrier#
:: State# RealWorld -> State# RealWorld
writeBarrier :: IO ()
writeBarrier = IO $ \s -> case writeBarrier# s of s' -> (# s', () #)
#elif !(defined(mingw32_HOST_OS) && __GLASGOW_HASKELL__ < 802)
foreign import ccall unsafe "store_load_barrier" storeLoadBarrier
:: IO ()
foreign import ccall unsafe "load_load_barrier" loadLoadBarrier
:: IO ()
foreign import ccall unsafe "write_barrier" writeBarrier
:: IO ()
#else
#warning "importing store_load_barrier and friends from the package's C code."
foreign import ccall unsafe "DUP_store_load_barrier" storeLoadBarrier
:: IO ()
foreign import ccall unsafe "DUP_load_load_barrier" loadLoadBarrier
:: IO ()
foreign import ccall unsafe "DUP_write_barrier" writeBarrier
:: IO ()
#endif
atomicModifyIORefCAS :: IORef a
-> (a -> (a,b))
-> IO b
atomicModifyIORefCAS :: forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORefCAS IORef a
ref a -> (a, b)
fn = do
Ticket a
tick <- IORef a -> IO (Ticket a)
forall a. IORef a -> IO (Ticket a)
readForCAS IORef a
ref
Ticket a -> Int -> IO b
forall {t}. (Eq t, Num t) => Ticket a -> t -> IO b
loop Ticket a
tick Int
effort
where
effort :: Int
effort = Int
30 :: Int
loop :: Ticket a -> t -> IO b
loop Ticket a
_ t
0 = IORef a -> (a -> (a, b)) -> IO b
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef a
ref a -> (a, b)
fn
loop Ticket a
old t
tries = do
(a
new,b
result) <- (a, b) -> IO (a, b)
forall a. a -> IO a
evaluate ((a, b) -> IO (a, b)) -> (a, b) -> IO (a, b)
forall a b. (a -> b) -> a -> b
$ a -> (a, b)
fn (a -> (a, b)) -> a -> (a, b)
forall a b. (a -> b) -> a -> b
$ Ticket a -> a
forall a. Ticket a -> a
peekTicket Ticket a
old
(Bool
b,Ticket a
tick) <- IORef a -> Ticket a -> a -> IO (Bool, Ticket a)
forall a. IORef a -> Ticket a -> a -> IO (Bool, Ticket a)
casIORef IORef a
ref Ticket a
old a
new
if Bool
b
then b -> IO b
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return b
result
else Ticket a -> t -> IO b
loop Ticket a
tick (t
triest -> t -> t
forall a. Num a => a -> a -> a
-t
1)
atomicModifyIORefCAS_ :: IORef t -> (t -> t) -> IO ()
atomicModifyIORefCAS_ :: forall t. IORef t -> (t -> t) -> IO ()
atomicModifyIORefCAS_ IORef t
ref t -> t
fn = do
Ticket t
tick <- IORef t -> IO (Ticket t)
forall a. IORef a -> IO (Ticket a)
readForCAS IORef t
ref
Ticket t -> Int -> IO ()
forall {t}. (Eq t, Num t) => Ticket t -> t -> IO ()
loop Ticket t
tick Int
effort
where
effort :: Int
effort = Int
30 :: Int
loop :: Ticket t -> t -> IO ()
loop Ticket t
_ t
0 = IORef t -> (t -> (t, ())) -> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef t
ref (\ t
x -> (t -> t
fn t
x, ()))
loop Ticket t
old t
tries = do
t
new <- t -> IO t
forall a. a -> IO a
evaluate (t -> IO t) -> t -> IO t
forall a b. (a -> b) -> a -> b
$ t -> t
fn (t -> t) -> t -> t
forall a b. (a -> b) -> a -> b
$ Ticket t -> t
forall a. Ticket a -> a
peekTicket Ticket t
old
(Bool
b,Ticket t
val) <- IORef t -> Ticket t -> t -> IO (Bool, Ticket t)
forall a. IORef a -> Ticket a -> a -> IO (Bool, Ticket a)
casIORef IORef t
ref Ticket t
old t
new
if Bool
b
then () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
else Ticket t -> t -> IO ()
loop Ticket t
val (t
triest -> t -> t
forall a. Num a => a -> a -> a
-t
1)