module Control.Concurrent.STM.DTVar
( DTVar
, newDTVar
, newDTVarIO
, writeDTVar
, writeDTVarIO
, readDTVar
, readDTVarIO
, listenDTVar
, listenDTVarIO
, listenDTVars
, listenDTVarsIO
, modifyDTVar
) where
import Control.Monad
import Control.Concurrent.STM
data DTVar a = DTVar
{ var :: TVar a
, dirty :: TVar Bool
}
newDTVar :: a -> STM (DTVar a)
newDTVar x = do
a_var <- newTVar x
t_var <- newTVar True
return (DTVar a_var t_var)
newDTVarIO :: a -> IO (DTVar a)
newDTVarIO = atomically . newDTVar
writeDTVar :: DTVar a -> a -> STM ()
writeDTVar (DTVar v d) x = do
writeTVar v x
writeTVar d True
writeDTVarIO :: DTVar a -> a -> IO ()
writeDTVarIO u x = atomically (writeDTVar u x)
readDTVar :: DTVar a -> STM a
readDTVar = readTVar . var
readDTVarIO :: DTVar a -> IO a
readDTVarIO = atomically . readDTVar
listenDTVar :: DTVar a -> STM a
listenDTVar u = do
d <- readTVar (dirty u)
unless d retry
writeTVar (dirty u) False
readTVar (var u)
listenDTVarIO :: DTVar a -> IO a
listenDTVarIO = atomically . listenDTVar
listenDTVars :: [DTVar a] -> STM [a]
listenDTVars us = do
ds <- mapM (readTVar . dirty) us
unless (or ds || null ds) retry
mapM_ ((`writeTVar` False) . dirty) us
mapM (readTVar . var) us
listenDTVarsIO :: [DTVar a] -> IO [a]
listenDTVarsIO = atomically . listenDTVars
modifyDTVar :: DTVar a -> (a -> a) -> STM ()
modifyDTVar d f = do
x <- readDTVar d
writeDTVar d (f x)