module Control.Concurrent.AtomicModify
( AtomicModify (..)
, atomicModifyStrict_
, atomicModifyLazy_
) where
import Control.Concurrent.MVar (MVar, modifyMVar)
import Control.Concurrent.STM (STM, TMVar, TVar, atomically, putTMVar, readTVar,
takeTMVar, writeTVar)
import Data.IORef (IORef, atomicModifyIORef, atomicModifyIORef')
import Prelude (IO, pure, ($), ($!))
class AtomicModify ref m where
atomicModifyStrict :: ref a -> (a -> (a, b)) -> m b
atomicModifyLazy :: ref a -> (a -> (a, b)) -> m b
atomicModifyStrict_ :: AtomicModify v m => v a -> (a -> a) -> m ()
atomicModifyStrict_ ref f = atomicModifyStrict ref (\a -> (f a, ()))
atomicModifyLazy_ :: AtomicModify v m => v a -> (a -> a) -> m ()
atomicModifyLazy_ ref f = atomicModifyLazy ref (\a -> (f a, ()))
instance AtomicModify IORef IO where
atomicModifyLazy ref f = atomicModifyIORef ref f
atomicModifyStrict ref f = atomicModifyIORef' ref f
instance AtomicModify MVar IO where
atomicModifyLazy ref f = modifyMVar ref (\x -> pure $ f x)
atomicModifyStrict ref f = modifyMVar ref (\x -> pure $! f x)
instance AtomicModify TVar STM where
atomicModifyLazy ref f = do
a <- readTVar ref
let (a', b) = f a
writeTVar ref a'
pure b
atomicModifyStrict ref f = do
a <- readTVar ref
let (a', b) = f a
writeTVar ref $! a'
pure $! b
instance AtomicModify TMVar STM where
atomicModifyLazy ref f = do
a <- takeTMVar ref
let (a', b) = f a
putTMVar ref a'
pure b
atomicModifyStrict ref f = do
a <- takeTMVar ref
let (a', b) = f a
putTMVar ref $! a'
pure $! b
instance AtomicModify TVar IO where
atomicModifyLazy ref f = atomically (atomicModifyLazy ref f)
atomicModifyStrict ref f = atomically (atomicModifyStrict ref f)
instance AtomicModify TMVar IO where
atomicModifyLazy ref f = atomically (atomicModifyLazy ref f)
atomicModifyStrict ref f = atomically (atomicModifyStrict ref f)