    {-# LANGUAGE RankNTypes #-}
    -- | Unlifted "Control.Concurrent".
    --
    -- This module is not reexported by "UnliftIO",
    -- use it only if "UnliftIO.Async" is not enough.
    --
    -- @since 0.1.1.0
    module UnliftIO.Concurrent
      (
        -- * Concurrent Haskell
        ThreadId,

        -- * Basic concurrency operations
        myThreadId, forkIO, forkWithUnmask, forkIOWithUnmask,  forkFinally, killThread, throwTo,

        -- ** Threads with affinity
        forkOn, forkOnWithUnmask, getNumCapabilities, setNumCapabilities,
        threadCapability,

        -- * Scheduling
        yield,

        -- ** Waiting
        threadDelay, threadWaitRead, threadWaitWrite,

        -- * Communication abstractions
        module UnliftIO.MVar, module UnliftIO.Chan,

        -- * Bound Threads
        C.rtsSupportsBoundThreads, forkOS, isCurrentThreadBound, runInBoundThread,
        runInUnboundThread,

        -- * Weak references to ThreadIds
        mkWeakThreadId
      ) where

    import Control.Monad.IO.Class (MonadIO, liftIO)
    import System.Posix.Types (Fd)
    import System.Mem.Weak (Weak)
    import Control.Concurrent (ThreadId)
    import qualified Control.Concurrent as C
    import Control.Monad.IO.Unlift
    import UnliftIO.MVar
    import UnliftIO.Chan
    import UnliftIO.Exception (throwTo, SomeException)

    -- | Lifted version of 'C.myThreadId'.
    --
    -- @since 0.1.1.0
    myThreadId :: MonadIO m => m ThreadId
    myThreadId = liftIO C.myThreadId
    {-# INLINABLE myThreadId #-}

    -- | Unlifted version of 'C.forkIO'.
    --
    -- @since 0.1.1.0
    forkIO :: MonadUnliftIO m => m () -> m ThreadId
    forkIO m = withRunInIO $ \run -> C.forkIO $ run m
    {-# INLINABLE forkIO #-}

    -- | Unlifted version of 'C.forkIOWithUnmask'.
    --
    -- @since 0.2.11
    forkIOWithUnmask :: MonadUnliftIO m => ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forkIOWithUnmask m =
      withRunInIO $ \run -> C.forkIOWithUnmask $ \unmask -> run $ m $ liftIO . unmask . run
    {-# INLINABLE forkIOWithUnmask #-}

    -- | Please use 'forkIOWithUnmask' instead. This function has been deprecated
    -- in release 0.2.11 and will be removed in the next major release.
    --
    -- @since 0.1.1.0
    forkWithUnmask :: MonadUnliftIO m => ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forkWithUnmask = forkIOWithUnmask
    {-# INLINABLE forkWithUnmask #-}
    {-# DEPRECATED forkWithUnmask "forkWithUnmask has been renamed to forkIOWithUnmask" #-}

    -- | Unlifted version of 'C.forkFinally'.
    --
    -- @since 0.1.1.0
    forkFinally :: MonadUnliftIO m => m a -> (Either SomeException a -> m ()) -> m ThreadId
    forkFinally m1 m2 = withRunInIO $ \run -> C.forkFinally (run m1) $ run . m2
    {-# INLINABLE forkFinally #-}

    -- | Lifted version of 'C.killThread'.
    --
    -- @since 0.1.1.0
    killThread :: MonadIO m => ThreadId -> m ()
    killThread = liftIO . C.killThread
    {-# INLINABLE  killThread #-}

    -- | Unlifted version of 'C.forkOn'.
    --
    -- @since 0.1.1.0
    forkOn :: MonadUnliftIO m => Int -> m () -> m ThreadId
    forkOn i m = withRunInIO $ \run -> C.forkOn i $ run m
    {-# INLINABLE forkOn #-}

    -- | Unlifted version of 'C.forkOnWithUnmask'.
    --
    -- @since 0.1.1.0
    forkOnWithUnmask :: MonadUnliftIO m => Int -> ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forkOnWithUnmask i m =
      withRunInIO $ \run -> C.forkOnWithUnmask i $ \unmask -> run $ m $ liftIO . unmask . run
    {-# INLINABLE forkOnWithUnmask #-}

    -- | Lifted version of 'C.getNumCapabilities'.
    --
    -- @since 0.1.1.0
    getNumCapabilities :: MonadIO m => m Int
    getNumCapabilities = liftIO C.getNumCapabilities
    {-# INLINABLE getNumCapabilities #-}

    -- | Lifted version of 'C.setNumCapabilities'.
    --
    -- @since 0.1.1.0
    setNumCapabilities :: MonadIO m => Int -> m ()
    setNumCapabilities = liftIO . C.setNumCapabilities
    {-# INLINABLE setNumCapabilities #-}

    -- | Lifted version of 'C.threadCapability'.
    --
    -- @since 0.1.1.0
    threadCapability :: MonadIO m => ThreadId -> m (Int, Bool)
    threadCapability = liftIO . C.threadCapability
    {-# INLINABLE threadCapability #-}

    -- | Lifted version of 'C.yield'.
    --
    -- @since 0.1.1.0
    yield :: MonadIO m => m ()
    yield = liftIO C.yield
    {-# INLINABLE yield #-}

    -- | Lifted version of 'C.threadDelay'.
    --
    -- @since 0.1.1.0
    threadDelay :: MonadIO m => Int -> m ()
    threadDelay = liftIO .  C.threadDelay
    {-# INLINABLE threadDelay #-}

    -- | Lifted version of 'C.threadWaitRead'.
    --
    -- @since 0.1.1.0
    threadWaitRead :: MonadIO m => Fd -> m ()
    threadWaitRead = liftIO . C.threadWaitRead
    {-# INLINABLE threadWaitRead #-}

    -- | Lifted version of 'C.threadWaitWrite'.
    --
    -- @since 0.1.1.0
    threadWaitWrite :: MonadIO m => Fd -> m ()
    threadWaitWrite = liftIO . C.threadWaitWrite
    {-# INLINABLE threadWaitWrite #-}

    -- | Unflifted version of 'C.forkOS'.
    --
    -- @since 0.1.1.0
    forkOS :: MonadUnliftIO m => m () -> m ThreadId
    forkOS m = withRunInIO $ \run -> C.forkOS $ run m
    {-# INLINABLE forkOS #-}

    -- | Lifted version of 'C.isCurrentThreadBound'.
    --
    -- @since 0.1.1.0
    isCurrentThreadBound :: MonadIO m => m Bool
    isCurrentThreadBound = liftIO C.isCurrentThreadBound
    {-# INLINABLE isCurrentThreadBound #-}

    -- | Unlifted version of 'C.runInBoundThread'.
    --
    -- @since 0.1.1.0
    runInBoundThread :: MonadUnliftIO m => m a -> m a
    runInBoundThread m = withRunInIO $ \run -> C.runInBoundThread $ run m
    {-# INLINABLE runInBoundThread #-}

    -- | Unlifted version of 'C.runInUnboundThread'.
    --
    -- @since 0.1.1.0
    runInUnboundThread :: MonadUnliftIO m => m a -> m a
    runInUnboundThread m = withRunInIO $ \run -> C.runInUnboundThread $ run m
    {-# INLINABLE runInUnboundThread #-}

    -- | Lifted version of 'C.mkWeakThreadId'.
    --
    -- @since 0.1.1.0
    mkWeakThreadId :: MonadIO m => ThreadId -> m (Weak ThreadId)
    mkWeakThreadId = liftIO . C.mkWeakThreadId
    {-# INLINABLE mkWeakThreadId #-}