Blame Control/Concurrent/Lifted.hs

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