    {-# 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 :: forall (m :: * -> *). MonadIO m => m ThreadId
    myThreadId = IO ThreadId -> m ThreadId
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ThreadId
    C.myThreadId
    {-# INLINABLE myThreadId #-}

    -- | Unlifted version of 'C.forkIO'.
    --
    -- @since 0.1.1.0
    forkIO :: MonadUnliftIO m => m () -> m ThreadId
    forkIO :: forall (m :: * -> *). MonadUnliftIO m => m () -> m ThreadId
    forkIO m ()
    m = ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall b. ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId)
    -> ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. m a -> IO a
    run -> IO () -> IO ThreadId
    C.forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ m () -> IO ()
    forall a. m a -> IO a
    run m ()
    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 :: forall (m :: * -> *).
    MonadUnliftIO m =>
    ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forkIOWithUnmask (forall a. m a -> m a) -> m ()
    m =
      ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall b. ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId)
    -> ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. m a -> IO a
    run -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
    C.forkIOWithUnmask (((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId)
    -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. IO a -> IO a
    unmask -> m () -> IO ()
    forall a. m a -> IO a
    run (m () -> IO ()) -> m () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (forall a. m a -> m a) -> m ()
    m ((forall a. m a -> m a) -> m ()) -> (forall a. m a -> m a) -> m ()
    forall a b. (a -> b) -> a -> b
    $ IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> (m a -> IO a) -> m a -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO a -> IO a
    forall a. IO a -> IO a
    unmask (IO a -> IO a) -> (m a -> IO a) -> m a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . m a -> IO a
    forall a. m a -> IO a
    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 :: forall (m :: * -> *).
    MonadUnliftIO m =>
    ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forkWithUnmask = ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forall (m :: * -> *).
    MonadUnliftIO m =>
    ((forall a. m a -> m a) -> m ()) -> m ThreadId
    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 :: forall (m :: * -> *) a.
    MonadUnliftIO m =>
    m a -> (Either SomeException a -> m ()) -> m ThreadId
    forkFinally m a
    m1 Either SomeException a -> m ()
    m2 = ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall b. ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId)
    -> ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. m a -> IO a
    run -> IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
    forall a. IO a -> (Either SomeException a -> IO ()) -> IO ThreadId
    C.forkFinally (m a -> IO a
    forall a. m a -> IO a
    run m a
    m1) ((Either SomeException a -> IO ()) -> IO ThreadId)
    -> (Either SomeException a -> IO ()) -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ m () -> IO ()
    forall a. m a -> IO a
    run (m () -> IO ())
    -> (Either SomeException a -> m ())
    -> Either SomeException a
    -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Either SomeException a -> m ()
    m2
    {-# INLINABLE forkFinally #-}

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

    -- | Unlifted version of 'C.forkOn'.
    --
    -- @since 0.1.1.0
    forkOn :: MonadUnliftIO m => Int -> m () -> m ThreadId
    forkOn :: forall (m :: * -> *). MonadUnliftIO m => Int -> m () -> m ThreadId
    forkOn Int
    i m ()
    m = ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall b. ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId)
    -> ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. m a -> IO a
    run -> Int -> IO () -> IO ThreadId
    C.forkOn Int
    i (IO () -> IO ThreadId) -> IO () -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ m () -> IO ()
    forall a. m a -> IO a
    run m ()
    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 :: forall (m :: * -> *).
    MonadUnliftIO m =>
    Int -> ((forall a. m a -> m a) -> m ()) -> m ThreadId
    forkOnWithUnmask Int
    i (forall a. m a -> m a) -> m ()
    m =
      ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall b. ((forall a. m a -> IO a) -> IO b) -> m b
    forall (m :: * -> *) b.
    MonadUnliftIO m =>
    ((forall a. m a -> IO a) -> IO b) -> m b
    withRunInIO (((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId)
    -> ((forall a. m a -> IO a) -> IO ThreadId) -> m ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. m a -> IO a
    run -> Int -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
    C.forkOnWithUnmask Int
    i (((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId)
    -> ((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
    forall a b. (a -> b) -> a -> b
    $ \forall a. IO a -> IO a
    unmask -> m () -> IO ()
    forall a. m a -> IO a
    run (m () -> IO ()) -> m () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ (forall a. m a -> m a) -> m ()
    m ((forall a. m a -> m a) -> m ()) -> (forall a. m a -> m a) -> m ()
    forall a b. (a -> b) -> a -> b
    $ IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> (m a -> IO a) -> m a -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO a -> IO a
    forall a. IO a -> IO a
    unmask (IO a -> IO a) -> (m a -> IO a) -> m a -> IO a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . m a -> IO a
    forall a. m a -> IO a
    run
    {-# INLINABLE forkOnWithUnmask #-}

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

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

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

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

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

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

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

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

    -- | Lifted version of 'C.isCurrentThreadBound'.
    --
    -- @since 0.1.1.0
    isCurrentThreadBound :: MonadIO m => m Bool
    isCurrentThreadBound :: forall (m :: * -> *). MonadIO m => m Bool
    isCurrentThreadBound = IO Bool -> m Bool
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO Bool
    C.isCurrentThreadBound
    {-# INLINABLE isCurrentThreadBound #-}

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

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

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