io-classes-1.8.0.0: src/Control/Monad/Class/MonadFork.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeFamilies #-}
-- | A generalisation of
-- <https://hackage.haskell.org/package/base/docs/Control-Concurrent.html Control.Concurrent>
-- API to both 'IO' and <https://hackage.haskell.org/package/io-sim IOSim>.
--
module Control.Monad.Class.MonadFork
( MonadThread (..)
, labelThisThread
, MonadFork (..)
) where
import Control.Concurrent qualified as IO
import Control.Exception (AsyncException (ThreadKilled), Exception,
SomeException)
import Control.Monad.Reader (ReaderT (..), lift)
import Data.Kind (Type)
import GHC.Conc.Sync qualified as IO
class (Monad m, Eq (ThreadId m),
Ord (ThreadId m),
Show (ThreadId m)) => MonadThread m where
type ThreadId m :: Type
myThreadId :: m (ThreadId m)
labelThread :: ThreadId m -> String -> m ()
-- | Requires ghc-9.6.1 or newer.
--
-- @since 1.8.0.0
threadLabel :: ThreadId m -> m (Maybe String)
-- | Apply the label to the current thread
labelThisThread :: MonadThread m => String -> m ()
labelThisThread label = myThreadId >>= \tid -> labelThread tid label
class MonadThread m => MonadFork m where
forkIO :: m () -> m (ThreadId m)
forkOn :: Int -> m () -> m (ThreadId m)
forkIOWithUnmask :: ((forall a. m a -> m a) -> m ()) -> m (ThreadId m)
forkFinally :: m a -> (Either SomeException a -> m ()) -> m (ThreadId m)
throwTo :: Exception e => ThreadId m -> e -> m ()
killThread :: ThreadId m -> m ()
killThread tid = throwTo tid ThreadKilled
yield :: m ()
getNumCapabilities :: m Int
instance MonadThread IO where
type ThreadId IO = IO.ThreadId
myThreadId = IO.myThreadId
labelThread = IO.labelThread
#if MIN_VERSION_base(4,18,0)
threadLabel = IO.threadLabel
#else
threadLabel = \_ -> pure Nothing
#endif
instance MonadFork IO where
forkIO = IO.forkIO
forkOn = IO.forkOn
forkIOWithUnmask = IO.forkIOWithUnmask
forkFinally = IO.forkFinally
throwTo = IO.throwTo
killThread = IO.killThread
yield = IO.yield
getNumCapabilities = IO.getNumCapabilities
instance MonadThread m => MonadThread (ReaderT r m) where
type ThreadId (ReaderT r m) = ThreadId m
myThreadId = lift myThreadId
labelThread t l = lift (labelThread t l)
threadLabel = lift . threadLabel
instance MonadFork m => MonadFork (ReaderT e m) where
forkIO (ReaderT f) = ReaderT $ \e -> forkIO (f e)
forkOn n (ReaderT f) = ReaderT $ \e -> forkOn n (f e)
forkIOWithUnmask k = ReaderT $ \e -> forkIOWithUnmask $ \restore ->
let restore' :: ReaderT e m a -> ReaderT e m a
restore' (ReaderT f) = ReaderT $ restore . f
in runReaderT (k restore') e
forkFinally f k = ReaderT $ \e -> forkFinally (runReaderT f e)
$ \err -> runReaderT (k err) e
throwTo e t = lift (throwTo e t)
yield = lift yield
getNumCapabilities = lift getNumCapabilities