|
Packit |
1d883e |
{-# LANGUAGE CPP, NoImplicitPrelude, FlexibleContexts, RankNTypes #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if __GLASGOW_HASKELL__ >= 702
|
|
Packit |
1d883e |
{-# LANGUAGE Safe #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
{- |
|
|
Packit |
1d883e |
Module : Control.Concurrent.Lifted
|
|
Packit |
1d883e |
Copyright : Bas van Dijk
|
|
Packit |
1d883e |
License : BSD-style
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
Maintainer : Bas van Dijk <v.dijk.bas@gmail.com>
|
|
Packit |
1d883e |
Stability : experimental
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
This is a wrapped version of "Control.Concurrent" with types generalized
|
|
Packit |
1d883e |
from 'IO' to all monads in either 'MonadBase' or 'MonadBaseControl'.
|
|
Packit |
1d883e |
-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
module Control.Concurrent.Lifted
|
|
Packit |
1d883e |
( -- * Concurrent Haskell
|
|
Packit |
1d883e |
ThreadId
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Basic concurrency operations
|
|
Packit |
1d883e |
, myThreadId
|
|
Packit |
1d883e |
, fork
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
, forkWithUnmask
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
, forkFinally
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
, killThread
|
|
Packit |
1d883e |
, throwTo
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
-- ** Threads with affinity
|
|
Packit |
1d883e |
, forkOn
|
|
Packit |
1d883e |
, forkOnWithUnmask
|
|
Packit |
1d883e |
, getNumCapabilities
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
, setNumCapabilities
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
, threadCapability
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Scheduling
|
|
Packit |
1d883e |
, yield
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- ** Blocking
|
|
Packit |
1d883e |
-- ** Waiting
|
|
Packit |
1d883e |
, threadDelay
|
|
Packit |
1d883e |
, threadWaitRead
|
|
Packit |
1d883e |
, threadWaitWrite
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Communication abstractions
|
|
Packit |
1d883e |
, module Control.Concurrent.MVar.Lifted
|
|
Packit |
1d883e |
, module Control.Concurrent.Chan.Lifted
|
|
Packit |
1d883e |
, module Control.Concurrent.QSem.Lifted
|
|
Packit |
1d883e |
, module Control.Concurrent.QSemN.Lifted
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,7,0)
|
|
Packit |
1d883e |
, module Control.Concurrent.SampleVar.Lifted
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
-- * Merging of streams
|
|
Packit |
1d883e |
, merge
|
|
Packit |
1d883e |
, nmerge
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Bound Threads
|
|
Packit |
1d883e |
, C.rtsSupportsBoundThreads
|
|
Packit |
1d883e |
, forkOS
|
|
Packit |
1d883e |
, isCurrentThreadBound
|
|
Packit |
1d883e |
, runInBoundThread
|
|
Packit |
1d883e |
, runInUnboundThread
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
-- * Weak references to ThreadIds
|
|
Packit |
1d883e |
, mkWeakThreadId
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
) where
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- Imports
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from base:
|
|
Packit |
1d883e |
import Prelude ( (.) )
|
|
Packit |
1d883e |
import Data.Bool ( Bool )
|
|
Packit |
1d883e |
import Data.Int ( Int )
|
|
Packit |
1d883e |
import Data.Function ( ($) )
|
|
Packit |
1d883e |
import System.IO ( IO )
|
|
Packit |
1d883e |
import System.Posix.Types ( Fd )
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
import Control.Monad ( (>>=) )
|
|
Packit |
1d883e |
import Data.Either ( Either )
|
|
Packit |
1d883e |
import System.Mem.Weak ( Weak )
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
import Control.Concurrent ( ThreadId )
|
|
Packit |
1d883e |
import qualified Control.Concurrent as C
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from transformers-base:
|
|
Packit |
1d883e |
import Control.Monad.Base ( MonadBase, liftBase )
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from monad-control:
|
|
Packit |
1d883e |
import Control.Monad.Trans.Control ( MonadBaseControl, liftBaseOp_, liftBaseDiscard )
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
import Control.Monad.Trans.Control ( liftBaseWith )
|
|
Packit |
1d883e |
import Control.Monad ( void )
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from lifted-base (this package):
|
|
Packit |
1d883e |
import Control.Concurrent.MVar.Lifted
|
|
Packit |
1d883e |
import Control.Concurrent.Chan.Lifted
|
|
Packit |
1d883e |
import Control.Concurrent.QSem.Lifted
|
|
Packit |
1d883e |
import Control.Concurrent.QSemN.Lifted
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,7,0)
|
|
Packit |
1d883e |
import Control.Concurrent.SampleVar.Lifted
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
import Control.Exception.Lifted ( throwTo
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
, SomeException, try, mask
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
)
|
|
Packit |
1d883e |
#include "inlinable.h"
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- Control.Concurrent
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.myThreadId'.
|
|
Packit |
1d883e |
myThreadId :: MonadBase IO m => m ThreadId
|
|
Packit |
1d883e |
myThreadId = liftBase C.myThreadId
|
|
Packit |
1d883e |
{-# INLINABLE myThreadId #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.forkIO'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that, while the forked computation @m ()@ has access to the captured
|
|
Packit |
1d883e |
-- state, all its side-effects in @m@ are discarded. It is run only for its
|
|
Packit |
1d883e |
-- side-effects in 'IO'.
|
|
Packit |
1d883e |
fork :: MonadBaseControl IO m => m () -> m ThreadId
|
|
Packit |
1d883e |
fork = liftBaseDiscard C.forkIO
|
|
Packit |
1d883e |
{-# INLINABLE fork #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
-- | Generalized version of 'C.forkIOWithUnmask'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that, while the forked computation @m ()@ has access to the captured
|
|
Packit |
1d883e |
-- state, all its side-effects in @m@ are discarded. It is run only for its
|
|
Packit |
1d883e |
-- side-effects in 'IO'.
|
|
Packit |
1d883e |
forkWithUnmask :: MonadBaseControl IO m => ((forall a. m a -> m a) -> m ()) -> m ThreadId
|
|
Packit |
1d883e |
forkWithUnmask f = liftBaseWith $ \runInIO ->
|
|
Packit |
1d883e |
C.forkIOWithUnmask $ \unmask ->
|
|
Packit |
1d883e |
void $ runInIO $ f $ liftBaseOp_ unmask
|
|
Packit |
1d883e |
{-# INLINABLE forkWithUnmask #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
-- | Generalized version of 'C.forkFinally'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that in @forkFinally action and_then@, while the forked
|
|
Packit |
1d883e |
-- @action@ and the @and_then@ function have access to the captured
|
|
Packit |
1d883e |
-- state, all their side-effects in @m@ are discarded. They're run
|
|
Packit |
1d883e |
-- only for their side-effects in 'IO'.
|
|
Packit |
1d883e |
forkFinally :: MonadBaseControl IO m
|
|
Packit |
1d883e |
=> m a -> (Either SomeException a -> m ()) -> m ThreadId
|
|
Packit |
1d883e |
forkFinally action and_then =
|
|
Packit |
1d883e |
mask $ \restore ->
|
|
Packit |
1d883e |
fork $ try (restore action) >>= and_then
|
|
Packit |
1d883e |
{-# INLINABLE forkFinally #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.killThread'.
|
|
Packit |
1d883e |
killThread :: MonadBase IO m => ThreadId -> m ()
|
|
Packit |
1d883e |
killThread = liftBase . C.killThread
|
|
Packit |
1d883e |
{-# INLINABLE killThread #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
-- | Generalized version of 'C.forkOn'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that, while the forked computation @m ()@ has access to the captured
|
|
Packit |
1d883e |
-- state, all its side-effects in @m@ are discarded. It is run only for its
|
|
Packit |
1d883e |
-- side-effects in 'IO'.
|
|
Packit |
1d883e |
forkOn :: MonadBaseControl IO m => Int -> m () -> m ThreadId
|
|
Packit |
1d883e |
forkOn = liftBaseDiscard . C.forkOn
|
|
Packit |
1d883e |
{-# INLINABLE forkOn #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.forkOnWithUnmask'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that, while the forked computation @m ()@ has access to the captured
|
|
Packit |
1d883e |
-- state, all its side-effects in @m@ are discarded. It is run only for its
|
|
Packit |
1d883e |
-- side-effects in 'IO'.
|
|
Packit |
1d883e |
forkOnWithUnmask :: MonadBaseControl IO m => Int -> ((forall a. m a -> m a) -> m ()) -> m ThreadId
|
|
Packit |
1d883e |
forkOnWithUnmask cap f = liftBaseWith $ \runInIO ->
|
|
Packit |
1d883e |
C.forkOnWithUnmask cap $ \unmask ->
|
|
Packit |
1d883e |
void $ runInIO $ f $ liftBaseOp_ unmask
|
|
Packit |
1d883e |
{-# INLINABLE forkOnWithUnmask #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.getNumCapabilities'.
|
|
Packit |
1d883e |
getNumCapabilities :: MonadBase IO m => m Int
|
|
Packit |
1d883e |
getNumCapabilities = liftBase C.getNumCapabilities
|
|
Packit |
1d883e |
{-# INLINABLE getNumCapabilities #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
-- | Generalized version of 'C.setNumCapabilities'.
|
|
Packit |
1d883e |
setNumCapabilities :: MonadBase IO m => Int -> m ()
|
|
Packit |
1d883e |
setNumCapabilities = liftBase . C.setNumCapabilities
|
|
Packit |
1d883e |
{-# INLINABLE setNumCapabilities #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.threadCapability'.
|
|
Packit |
1d883e |
threadCapability :: MonadBase IO m => ThreadId -> m (Int, Bool)
|
|
Packit |
1d883e |
threadCapability = liftBase . C.threadCapability
|
|
Packit |
1d883e |
{-# INLINABLE threadCapability #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.yield'.
|
|
Packit |
1d883e |
yield :: MonadBase IO m => m ()
|
|
Packit |
1d883e |
yield = liftBase C.yield
|
|
Packit |
1d883e |
{-# INLINABLE yield #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.threadDelay'.
|
|
Packit |
1d883e |
threadDelay :: MonadBase IO m => Int -> m ()
|
|
Packit |
1d883e |
threadDelay = liftBase . C.threadDelay
|
|
Packit |
1d883e |
{-# INLINABLE threadDelay #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.threadWaitRead'.
|
|
Packit |
1d883e |
threadWaitRead :: MonadBase IO m => Fd -> m ()
|
|
Packit |
1d883e |
threadWaitRead = liftBase . C.threadWaitRead
|
|
Packit |
1d883e |
{-# INLINABLE threadWaitRead #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.threadWaitWrite'.
|
|
Packit |
1d883e |
threadWaitWrite :: MonadBase IO m => Fd -> m ()
|
|
Packit |
1d883e |
threadWaitWrite = liftBase . C.threadWaitWrite
|
|
Packit |
1d883e |
{-# INLINABLE threadWaitWrite #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
-- | Generalized version of 'C.mergeIO'.
|
|
Packit |
1d883e |
merge :: MonadBase IO m => [a] -> [a] -> m [a]
|
|
Packit |
1d883e |
merge xs ys = liftBase $ C.mergeIO xs ys
|
|
Packit |
1d883e |
{-# INLINABLE merge #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.nmergeIO'.
|
|
Packit |
1d883e |
nmerge :: MonadBase IO m => [[a]] -> m [a]
|
|
Packit |
1d883e |
nmerge = liftBase . C.nmergeIO
|
|
Packit |
1d883e |
{-# INLINABLE nmerge #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.forkOS'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that, while the forked computation @m ()@ has access to the captured
|
|
Packit |
1d883e |
-- state, all its side-effects in @m@ are discarded. It is run only for its
|
|
Packit |
1d883e |
-- side-effects in 'IO'.
|
|
Packit |
1d883e |
forkOS :: MonadBaseControl IO m => m () -> m ThreadId
|
|
Packit |
1d883e |
forkOS = liftBaseDiscard C.forkOS
|
|
Packit |
1d883e |
{-# INLINABLE forkOS #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.isCurrentThreadBound'.
|
|
Packit |
1d883e |
isCurrentThreadBound :: MonadBase IO m => m Bool
|
|
Packit |
1d883e |
isCurrentThreadBound = liftBase C.isCurrentThreadBound
|
|
Packit |
1d883e |
{-# INLINABLE isCurrentThreadBound #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.runInBoundThread'.
|
|
Packit |
1d883e |
runInBoundThread :: MonadBaseControl IO m => m a -> m a
|
|
Packit |
1d883e |
runInBoundThread = liftBaseOp_ C.runInBoundThread
|
|
Packit |
1d883e |
{-# INLINABLE runInBoundThread #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.runInUnboundThread'.
|
|
Packit |
1d883e |
runInUnboundThread :: MonadBaseControl IO m => m a -> m a
|
|
Packit |
1d883e |
runInUnboundThread = liftBaseOp_ C.runInUnboundThread
|
|
Packit |
1d883e |
{-# INLINABLE runInUnboundThread #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,6,0)
|
|
Packit |
1d883e |
-- | Generalized versio of 'C.mkWeakThreadId'.
|
|
Packit |
1d883e |
mkWeakThreadId :: MonadBase IO m => ThreadId -> m (Weak ThreadId)
|
|
Packit |
1d883e |
mkWeakThreadId = liftBase . C.mkWeakThreadId
|
|
Packit |
1d883e |
{-# INLINABLE mkWeakThreadId #-}
|
|
Packit |
1d883e |
#endif
|