monadIO-0.11.0.0: src/Control/Concurrent/MonadIO.hs
--------------------------------------------------------------------------
{- |
Module : Control.Concurrent.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
Overloads the standard operations on MVars, Chans, and threads,
as defined in Control.Concurrent. This module is name-for-name
swappable with Control.Concurrent unless ghc-specific
operations like 'mergeIO' or 'threadWaitRead' are used.
The standard operations on 'MVar' and 'Chan' (such as
'newEmptyMVar', or 'putChan') are overloaded over the
'MonadIO' class. A monad @m@ is declared an instance of
'MonadIO' by defining a function
> liftIO :: IO a -> m a
The explicit concurrency operations over threads are
available if a monad @m@ is declared an instance of the
'HasFork' class, by defining a function
> fork :: m () -> m ThreadId
* Example use.
Suppose you define a new monad (EIO say) which is like
'IO' except that it provides an environment too.
You will need to declare EIO and instance of the 'Monad' class. In
addition, you can declare it in the 'MonadIO' class. For example:
> newtype EIO a = EIO {useEnv :: Env -> IO a}
>
> instance MonadIO EIO where
> liftIO m = EIO $ (\_ -> m)
Now the standard operations on 'MVar' and 'Chan' (such as
'newEmptyMVar', or 'putChan' are immediately available as
EIO operations. To enable EIO to fork explicit threads, and to
access operations such as 'killThread' and 'threadDelay', use
the declaration
> instance HasFork EIO where
> fork em = EIO $ \e -> forkIO (em `useEnv` e)
* Notes.
The 'MVar' operations do not include: withMVar, modifyMVar, or
addMVarFinalizer. Consider using TMVars for these instead. In particular,
modifyMVar seems to promise atomicity, but it is NOT atomic. In
contrast TMVars can be used just like MVars, and they
will behave the way you expect (module Control.Concurrent.STM.MonadIO).
-}
--------------------------------------------------------------------------
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
module Control.Concurrent.MonadIO (
MonadIO(..)
, C.MVar
, newEmptyMVar
, newMVar
, takeMVar
, putMVar
, readMVar
, swapMVar
, tryTakeMVar
, tryPutMVar
, isEmptyMVar
, C.Chan
, newChan
, writeChan
, readChan
, dupChan
, unGetChan
, getChanContents
, writeList2Chan
, HasFork(..)
, C.ThreadId
, forkIO
, myThreadId
, killThread
, throwTo
, yield
, threadDelay
)
where
import Control.Monad.Trans(MonadIO(..))
import qualified Control.Concurrent as C
import qualified Control.Exception as E
newEmptyMVar :: MonadIO io => io (C.MVar a)
newEmptyMVar = liftIO $ C.newEmptyMVar
newMVar :: MonadIO io => a -> io (C.MVar a)
newMVar x = liftIO $ C.newMVar x
takeMVar :: MonadIO io => C.MVar a -> io a
takeMVar m = liftIO $ C.takeMVar m
putMVar :: MonadIO io => C.MVar a -> a -> io ()
putMVar m x = liftIO $ C.putMVar m x
readMVar :: MonadIO io => C.MVar a -> io a
readMVar m = liftIO $ C.readMVar m
swapMVar :: MonadIO io => C.MVar a -> a -> io a
swapMVar m x = liftIO $ C.swapMVar m x
tryTakeMVar :: MonadIO io => C.MVar a -> io (Maybe a)
tryTakeMVar m = liftIO $ C.tryTakeMVar m
tryPutMVar :: MonadIO io => C.MVar a -> a -> io Bool
tryPutMVar m x = liftIO $ C.tryPutMVar m x
isEmptyMVar :: MonadIO io => C.MVar a -> io Bool
isEmptyMVar m = liftIO $ C.isEmptyMVar m
-------------------------------------------------------------------------
newChan :: MonadIO io => io (C.Chan a)
newChan = liftIO $ C.newChan
writeChan :: MonadIO io => C.Chan a -> a -> io ()
writeChan c x = liftIO $ C.writeChan c x
readChan :: MonadIO io => C.Chan a -> io a
readChan c = liftIO $ C.readChan c
dupChan :: MonadIO io => C.Chan a -> io (C.Chan a)
dupChan c = liftIO $ C.dupChan c
unGetChan :: MonadIO io => C.Chan a -> a -> io ()
unGetChan c x = liftIO $ unGetChan c x
getChanContents :: MonadIO io => C.Chan a -> io [a]
getChanContents c = liftIO $ C.getChanContents c
writeList2Chan :: MonadIO io => C.Chan a -> [a] -> io ()
writeList2Chan c xs = liftIO $ C.writeList2Chan c xs
-------------------------------------------------------------------------
class MonadIO io => HasFork io where
fork :: io () -> io C.ThreadId
instance HasFork IO where
fork m = C.forkIO m
-- | Included to maintain name-for-name compatibility
-- with Control.Concurrent
forkIO :: IO () -> IO C.ThreadId
forkIO = C.forkIO
myThreadId :: HasFork io => io C.ThreadId
myThreadId = liftIO $ C.myThreadId
killThread :: HasFork io => C.ThreadId -> io ()
killThread i = liftIO $ C.killThread i
throwTo :: (E.Exception e, HasFork io) => C.ThreadId -> e -> io ()
throwTo i e = liftIO $ C.throwTo i e
yield :: HasFork io => io ()
yield = liftIO $ C.yield
threadDelay :: HasFork io => Int -> io ()
threadDelay n = liftIO $ C.threadDelay n