module Streamly.Internal.Data.Atomics
(
atomicModifyIORefCAS
, atomicModifyIORefCAS_
, writeBarrier
, storeLoadBarrier
)
where
import Data.IORef (IORef, atomicModifyIORef)
#ifdef ghcjs_HOST_OS
import Data.IORef (modifyIORef)
#else
import qualified Data.Atomics as A
#endif
#ifndef ghcjs_HOST_OS
{-# INLINE atomicModifyIORefCAS #-}
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
tkt <- forall a. IORef a -> IO (Ticket a)
A.readForCAS IORef a
ref
forall {t}. (Eq t, Num t) => Ticket a -> t -> IO b
loop Ticket a
tkt Int
retries
where
retries :: Int
retries = Int
25 :: Int
loop :: Ticket a -> t -> IO b
loop Ticket a
_ t
0 = 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
let (a
new, b
result) = a -> (a, b)
fn forall a b. (a -> b) -> a -> b
$ forall a. Ticket a -> a
A.peekTicket Ticket a
old
(Bool
success, Ticket a
tkt) <- forall a. IORef a -> Ticket a -> a -> IO (Bool, Ticket a)
A.casIORef IORef a
ref Ticket a
old a
new
if Bool
success
then forall (m :: * -> *) a. Monad m => a -> m a
return b
result
else Ticket a -> t -> IO b
loop Ticket a
tkt (t
tries forall a. Num a => a -> a -> a
- t
1)
{-# INLINE atomicModifyIORefCAS_ #-}
atomicModifyIORefCAS_ :: IORef t -> (t -> t) -> IO ()
atomicModifyIORefCAS_ :: forall t. IORef t -> (t -> t) -> IO ()
atomicModifyIORefCAS_ = forall t. IORef t -> (t -> t) -> IO ()
A.atomicModifyIORefCAS_
{-# INLINE writeBarrier #-}
writeBarrier :: IO ()
writeBarrier :: IO ()
writeBarrier = IO ()
A.writeBarrier
{-# INLINE storeLoadBarrier #-}
storeLoadBarrier :: IO ()
storeLoadBarrier :: IO ()
storeLoadBarrier = IO ()
A.storeLoadBarrier
#else
{-# INLINE atomicModifyIORefCAS #-}
atomicModifyIORefCAS :: IORef a -> (a -> (a,b)) -> IO b
atomicModifyIORefCAS = atomicModifyIORef
{-# INLINE atomicModifyIORefCAS_ #-}
atomicModifyIORefCAS_ :: IORef a -> (a -> a) -> IO ()
atomicModifyIORefCAS_ = modifyIORef
{-# INLINE writeBarrier #-}
writeBarrier :: IO ()
writeBarrier = return ()
{-# INLINE storeLoadBarrier #-}
storeLoadBarrier :: IO ()
storeLoadBarrier = return ()
#endif