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