module Simulation.Aivika.Experiment.MRef
(MRef,
newMRef,
readMRef,
maybeReadMRef,
writeMRef,
maybeWriteMRef,
modifyMRef) where
import Control.Concurrent.MVar
import Data.Maybe
import Data.IORef
data MRef a =
MRef { mrefLock :: MVar (),
mrefData :: IORef a
}
newMRef :: a -> IO (MRef a)
newMRef a =
do v <- newMVar ()
r <- newIORef a
return MRef { mrefLock = v,
mrefData = r }
readMRef :: MRef a -> IO a
readMRef = readIORef . mrefData
maybeReadMRef :: b -> (a -> b) -> MRef (Maybe a) -> IO b
maybeReadMRef b0 f x =
do a <- readIORef (mrefData x)
case a of
Just a -> return (f a)
Nothing ->
withMVar (mrefLock x) $ \() ->
do a <- readIORef (mrefData x)
case a of
Just a -> return (f a)
Nothing -> return b0
writeMRef :: MRef a -> a -> IO ()
writeMRef x a =
withMVar (mrefLock x) $ \() ->
writeIORef (mrefData x) a
maybeWriteMRef :: MRef (Maybe a) -> IO a -> (a -> b) -> IO b
maybeWriteMRef x m0 f =
do a <- readIORef (mrefData x)
case a of
Just a -> return (f a)
Nothing ->
withMVar (mrefLock x) $ \() ->
do a <- readIORef (mrefData x)
case a of
Just a -> return (f a)
Nothing ->
do a0 <- m0
writeIORef (mrefData x) (Just a0)
return (f a0)
modifyMRef :: MRef a -> (a -> a) -> IO ()
modifyMRef x f =
withMVar (mrefLock x) $ \() ->
modifyIORef (mrefData x) f