monadIO-0.11.1.0: src/Control/Concurrent/STM/MonadIO.hs
--------------------------------------------------------------------------
{- |
Module : Control.Concurrent.STM.MonadIO
Copyright : (c) 2010 Galois, Inc.
License : BSD-style (see the file libraries/base/LICENSE)
Maintainer : John Launchbury, john@galois.com
Stability : experimental
Portability : concurrency, requires STM
Overloads the standard operations on TVars, and TMVars as defined
in Control.Concurrent.STM.
TVars and MVars are often thought of as variables to be
used in the STM monad. But in practice, they should be used
just as frequently (if not more so) in any IO-like monad, with STM
being used purely when a new atomic transaction is being defined.
Thus we reverse the naming convention, and use
the plain access names when in the IO-like monad, and use an explicit STM
suffix when using the variables tentatively within the STM monad itself.
TMVars are particularly valuable when used in an IO-like monad,
because operations like readTMVar and modifyTMvar
can guarantee the atomicity of the operation (unlike the corresponding
operations over MVars).
The standard operations on 'TVar' and 'TMVar' (such as
'writeTVar' or 'newEmptyTMVar') are overloaded over the
'MonadIO' class. A monad @m@ is declared an instance of
'MonadIO' by defining a function
> liftIO :: IO a -> m a
It also overloads the 'atomically' function, so that STM transactions
can be defined from within any MonadIO monad.
-}
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
module Control.Concurrent.STM.MonadIO (
STM
, atomically
, retry
, orElse
, check
, catchSTM
, S.TVar
, newTVar
, readTVar
, writeTVar
, registerDelay
, modifyTVar
, modifyTVar_
, newTVarSTM
, readTVarSTM
, writeTVarSTM
, S.TMVar
, newTMVar
, newEmptyTMVar
, takeTMVar
, putTMVar
, readTMVar
, swapTMVar
, tryTakeTMVar
, tryPutTMVar
, isEmptyTMVar
, modifyTMVar
, modifyTMVar_
, newTMVarSTM
, newEmptyTMVarSTM
, takeTMVarSTM
, putTMVarSTM
, readTMVarSTM
, swapTMVarSTM
, tryTakeTMVarSTM
, tryPutTMVarSTM
, isEmptyTMVarSTM
)
where
import Control.Monad.STM hiding (atomically)
import qualified Control.Concurrent.STM as S
import Control.Concurrent.MonadIO
import GHC.Conc (readTVarIO)
-------------------------------------------------------------------------
-- | The atomically function allows STM to be called directly from any
-- monad which contains IO, i.e. is a member of MonadIO.
atomically :: MonadIO io => STM a -> io a
atomically m = liftIO $ S.atomically m
-------------------------------------------------------------------------
type TVar = S.TVar
newTVar :: MonadIO io => a -> io (TVar a)
newTVar x = liftIO $ S.newTVarIO x
readTVar :: MonadIO io => TVar a -> io a
readTVar t = liftIO $ readTVarIO t
writeTVar :: MonadIO io => TVar a -> a -> io ()
writeTVar t x = atomically $ writeTVarSTM t x
registerDelay :: MonadIO io => Int -> io (TVar Bool)
registerDelay n = liftIO $ S.registerDelay n
-- | 'modifyTVar' is an atomic update operation which provides both
-- the former value and the newly computed value as a result.
modifyTVar :: MonadIO io => TVar a -> (a -> a) -> io (a,a)
modifyTVar t f = atomically $ do
x <- readTVarSTM t
let y = f x
seq y $ writeTVarSTM t y
return (x,y)
modifyTVar_ :: MonadIO io => TVar a -> (a -> a) -> io ()
modifyTVar_ t f = atomically $ do
x <- readTVarSTM t
let y = f x
seq y $ writeTVarSTM t y
----------------------
newTVarSTM :: a -> STM (TVar a)
newTVarSTM x = S.newTVar x
readTVarSTM :: TVar a -> STM a
readTVarSTM t = S.readTVar t
writeTVarSTM :: TVar a -> a -> STM ()
writeTVarSTM t x = S.writeTVar t x
-------------------------------------------------------------------------
type TMVar a = S.TMVar a
newTMVar :: MonadIO io => a -> io (TMVar a)
newTMVar x = liftIO $ S.newTMVarIO x
newEmptyTMVar :: MonadIO io => io (TMVar a)
newEmptyTMVar = liftIO $ S.newEmptyTMVarIO
takeTMVar :: MonadIO io => TMVar a -> io a
takeTMVar t = atomically $ takeTMVarSTM t
putTMVar :: MonadIO io => TMVar a -> a -> io ()
putTMVar t x = atomically $ putTMVarSTM t x
readTMVar :: MonadIO io => TMVar a -> io a
readTMVar t = atomically $ readTMVarSTM t
swapTMVar :: MonadIO io => TMVar a -> a -> io a
swapTMVar t x = atomically $ swapTMVarSTM t x
tryTakeTMVar :: MonadIO io => TMVar a -> io (Maybe a)
tryTakeTMVar t = atomically $ tryTakeTMVarSTM t
tryPutTMVar :: MonadIO io => TMVar a -> a -> io Bool
tryPutTMVar t x = atomically $ tryPutTMVarSTM t x
isEmptyTMVar :: MonadIO io => TMVar a -> io Bool
isEmptyTMVar t = atomically $ isEmptyTMVarSTM t
-- modifyTMVar is an atomic update operation which provides both
-- the former value and the newly computed value as a result.
modifyTMVar :: MonadIO io => TMVar a -> (a -> a) -> io (a,a)
modifyTMVar t f = atomically $ do
x <- takeTMVarSTM t
let y = f x
seq y $ putTMVarSTM t y
return (x,y)
modifyTMVar_ :: MonadIO io => TMVar a -> (a -> a) -> io ()
modifyTMVar_ t f = atomically $ do
x <- takeTMVarSTM t
let y = f x
seq y $ putTMVarSTM t y
----------------------
newTMVarSTM :: a -> STM (TMVar a)
newTMVarSTM = S.newTMVar
newEmptyTMVarSTM :: STM (TMVar a)
newEmptyTMVarSTM = S.newEmptyTMVar
takeTMVarSTM :: TMVar a -> STM a
takeTMVarSTM = S.takeTMVar
putTMVarSTM :: TMVar a -> a -> STM ()
putTMVarSTM = S.putTMVar
readTMVarSTM :: TMVar a -> STM a
readTMVarSTM = S.readTMVar
swapTMVarSTM :: TMVar a -> a -> STM a
swapTMVarSTM = S.swapTMVar
tryTakeTMVarSTM :: TMVar a -> STM (Maybe a)
tryTakeTMVarSTM = S.tryTakeTMVar
tryPutTMVarSTM :: TMVar a -> a -> STM Bool
tryPutTMVarSTM = S.tryPutTMVar
isEmptyTMVarSTM :: TMVar a -> STM Bool
isEmptyTMVarSTM = S.isEmptyTMVar