{-# LANGUAGE CPP #-}
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 ref fn = do
tkt <- A.readForCAS ref
loop tkt retries
where
retries = 25 :: Int
loop _ 0 = atomicModifyIORef ref fn
loop old tries = do
let (new, result) = fn $ A.peekTicket old
(success, tkt) <- A.casIORef ref old new
if success
then return result
else loop tkt (tries - 1)
{-# INLINE atomicModifyIORefCAS_ #-}
atomicModifyIORefCAS_ :: IORef t -> (t -> t) -> IO ()
atomicModifyIORefCAS_ = A.atomicModifyIORefCAS_
{-# INLINE writeBarrier #-}
writeBarrier :: IO ()
writeBarrier = A.writeBarrier
{-# INLINE storeLoadBarrier #-}
storeLoadBarrier :: IO ()
storeLoadBarrier = 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