    {-# LANGUAGE RecordWildCards, TupleSections #-}

    module Development.Shake.Internal.Core.Pool(
        addPoolWait, actionFenceSteal, actionFenceRequeue,
        actionAlwaysRequeue, actionAlwaysRequeuePriority,
        addPoolWait_,
        actionFenceRequeueBy
        ) where

    import Control.Exception
    import General.Pool
    import Development.Shake.Internal.Core.Types
    import Development.Shake.Internal.Core.Monad
    import System.Time.Extra
    import Data.Either.Extra
    import Control.Monad.IO.Class
    import General.Fence

    priority :: Either a b -> PoolPriority
    priority Either a b
    x = if Either a b -> Bool
    forall a b. Either a b -> Bool
    isLeft Either a b
    x then PoolPriority
    PoolException else PoolPriority
    PoolResume

    -- | Enqueue an Action into the pool and return a Fence to wait for it.
    --   Returns the value along with how long it spent executing.
    addPoolWait :: PoolPriority -> Action a -> Action (Fence IO (Either SomeException (Seconds, a)))
    addPoolWait :: forall a.
    PoolPriority
    -> Action a
    -> Action (Fence IO (Either SomeException (Seconds, a)))
    addPoolWait PoolPriority
    pri Action a
    act = do
        ro@Global{..} <- RAW ([String], [Key]) [Value] Global Local Global -> Action Global
    forall a. RAW ([String], [Key]) [Value] Global Local a -> Action a
    Action RAW ([String], [Key]) [Value] Global Local Global
    forall k v ro rw. RAW k v ro rw ro
    getRO
        rw <- Action getRW
        liftIO $ do
            fence <- newFence
            let act2 = do offset <- IO (IO Seconds) -> Action (IO Seconds)
    forall a. IO a -> Action a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO (IO Seconds)
    offsetTime; res <- act; offset <- liftIO offset; pure (offset, res)
            addPool pri globalPool $ runAction ro rw act2 $ signalFence fence
            pure fence

    -- | Like 'addPoolWait' but doesn't provide a fence to wait for it - a fire and forget version.
    --   Warning: If Action throws an exception, it would be lost, so must be executed with try. Seconds are not tracked.
    addPoolWait_ :: PoolPriority -> Action a -> Action ()
    addPoolWait_ :: forall a. PoolPriority -> Action a -> Action ()
    addPoolWait_ PoolPriority
    pri Action a
    act = do
        ro@Global{..} <- RAW ([String], [Key]) [Value] Global Local Global -> Action Global
    forall a. RAW ([String], [Key]) [Value] Global Local a -> Action a
    Action RAW ([String], [Key]) [Value] Global Local Global
    forall k v ro rw. RAW k v ro rw ro
    getRO
        rw <- Action getRW
        liftIO $ addPool pri globalPool $ runAction ro rw act $ \Either SomeException a
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()

    actionFenceSteal :: Fence IO (Either SomeException a) -> Action (Seconds, a)
    actionFenceSteal :: forall a. Fence IO (Either SomeException a) -> Action (Seconds, a)
    actionFenceSteal Fence IO (Either SomeException a)
    fence = do
        res <- IO (Maybe (Either SomeException a))
    -> Action (Maybe (Either SomeException a))
    forall a. IO a -> Action a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe (Either SomeException a))
     -> Action (Maybe (Either SomeException a)))
    -> IO (Maybe (Either SomeException a))
    -> Action (Maybe (Either SomeException a))
    forall a b. (a -> b) -> a -> b
    $ Fence IO (Either SomeException a)
    -> IO (Maybe (Either SomeException a))
    forall (m :: * -> *) a. Fence m a -> IO (Maybe a)
    testFence Fence IO (Either SomeException a)
    fence
        case res of
            Just (Left SomeException
    e) -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    -> Action (Seconds, a)
    forall a. RAW ([String], [Key]) [Value] Global Local a -> Action a
    Action (RAW ([String], [Key]) [Value] Global Local (Seconds, a)
     -> Action (Seconds, a))
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    -> Action (Seconds, a)
    forall a b. (a -> b) -> a -> b
    $ SomeException
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    forall e k v ro rw a. Exception e => e -> RAW k v ro rw a
    throwRAW SomeException
    e
            Just (Right a
    v) -> (Seconds, a) -> Action (Seconds, a)
    forall a. a -> Action a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Seconds
    0, a
    v)
            Maybe (Either SomeException a)
    Nothing -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    -> Action (Seconds, a)
    forall a. RAW ([String], [Key]) [Value] Global Local a -> Action a
    Action (RAW ([String], [Key]) [Value] Global Local (Seconds, a)
     -> Action (Seconds, a))
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    -> Action (Seconds, a)
    forall a b. (a -> b) -> a -> b
    $ Capture (Either SomeException (Seconds, a))
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    forall a k v ro rw.
    Capture (Either SomeException a) -> RAW k v ro rw a
    captureRAW (Capture (Either SomeException (Seconds, a))
     -> RAW ([String], [Key]) [Value] Global Local (Seconds, a))
    -> Capture (Either SomeException (Seconds, a))
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    forall a b. (a -> b) -> a -> b
    $ \Either SomeException (Seconds, a) -> IO ()
    continue -> do
                offset <- IO (IO Seconds)
    offsetTime
                waitFence fence $ \Either SomeException a
    v -> do
                    offset <- IO Seconds
    offset
                    continue $ (offset,) <$> v

    actionFenceRequeue :: Fence IO (Either SomeException b) -> Action (Seconds, b)
    actionFenceRequeue :: forall a. Fence IO (Either SomeException a) -> Action (Seconds, a)
    actionFenceRequeue = (Either SomeException b -> Either SomeException b)
    -> Fence IO (Either SomeException b) -> Action (Seconds, b)
    forall a b.
    (a -> Either SomeException b) -> Fence IO a -> Action (Seconds, b)
    actionFenceRequeueBy Either SomeException b -> Either SomeException b
    forall a. a -> a
    id

    actionFenceRequeueBy :: (a -> Either SomeException b) -> Fence IO a -> Action (Seconds, b)
    actionFenceRequeueBy :: forall a b.
    (a -> Either SomeException b) -> Fence IO a -> Action (Seconds, b)
    actionFenceRequeueBy a -> Either SomeException b
    op Fence IO a
    fence = RAW ([String], [Key]) [Value] Global Local (Seconds, b)
    -> Action (Seconds, b)
    forall a. RAW ([String], [Key]) [Value] Global Local a -> Action a
    Action (RAW ([String], [Key]) [Value] Global Local (Seconds, b)
     -> Action (Seconds, b))
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, b)
    -> Action (Seconds, b)
    forall a b. (a -> b) -> a -> b
    $ do
        res <- IO (Maybe a)
    -> RAW ([String], [Key]) [Value] Global Local (Maybe a)
    forall a. IO a -> RAW ([String], [Key]) [Value] Global Local a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe a)
     -> RAW ([String], [Key]) [Value] Global Local (Maybe a))
    -> IO (Maybe a)
    -> RAW ([String], [Key]) [Value] Global Local (Maybe a)
    forall a b. (a -> b) -> a -> b
    $ Fence IO a -> IO (Maybe a)
    forall (m :: * -> *) a. Fence m a -> IO (Maybe a)
    testFence Fence IO a
    fence
        case fmap op res of
            Just (Left SomeException
    e) -> SomeException
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, b)
    forall e k v ro rw a. Exception e => e -> RAW k v ro rw a
    throwRAW SomeException
    e
            Just (Right b
    v) -> (Seconds, b)
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, b)
    forall a. a -> RAW ([String], [Key]) [Value] Global Local a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (Seconds
    0, b
    v)
            Maybe (Either SomeException b)
    Nothing -> do
                Global{..} <- RAW ([String], [Key]) [Value] Global Local Global
    forall k v ro rw. RAW k v ro rw ro
    getRO
                offset <- liftIO offsetTime
                captureRAW $ \Either SomeException (Seconds, b) -> IO ()
    continue -> Fence IO a -> (a -> IO ()) -> IO ()
    forall (m :: * -> *) a.
    MonadIO m =>
    Fence m a -> (a -> m ()) -> m ()
    waitFence Fence IO a
    fence ((a -> IO ()) -> IO ()) -> (a -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \a
    v -> do
                    let v2 :: Either SomeException b
    v2 = a -> Either SomeException b
    op a
    v
                    PoolPriority -> Pool -> IO () -> IO ()
    forall a. PoolPriority -> Pool -> IO a -> IO ()
    addPool (Either SomeException b -> PoolPriority
    forall {a} {b}. Either a b -> PoolPriority
    priority Either SomeException b
    v2) Pool
    globalPool (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                        offset <- IO Seconds
    offset
                        continue $ (offset,) <$> v2

    actionAlwaysRequeue :: Either SomeException a -> Action (Seconds, a)
    actionAlwaysRequeue :: forall a. Either SomeException a -> Action (Seconds, a)
    actionAlwaysRequeue Either SomeException a
    res = PoolPriority -> Either SomeException a -> Action (Seconds, a)
    forall a.
    PoolPriority -> Either SomeException a -> Action (Seconds, a)
    actionAlwaysRequeuePriority (Either SomeException a -> PoolPriority
    forall {a} {b}. Either a b -> PoolPriority
    priority Either SomeException a
    res) Either SomeException a
    res

    actionAlwaysRequeuePriority :: PoolPriority -> Either SomeException a -> Action (Seconds, a)
    actionAlwaysRequeuePriority :: forall a.
    PoolPriority -> Either SomeException a -> Action (Seconds, a)
    actionAlwaysRequeuePriority PoolPriority
    pri Either SomeException a
    res = RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    -> Action (Seconds, a)
    forall a. RAW ([String], [Key]) [Value] Global Local a -> Action a
    Action (RAW ([String], [Key]) [Value] Global Local (Seconds, a)
     -> Action (Seconds, a))
    -> RAW ([String], [Key]) [Value] Global Local (Seconds, a)
    -> Action (Seconds, a)
    forall a b. (a -> b) -> a -> b
    $ do
        Global{..} <- RAW ([String], [Key]) [Value] Global Local Global
    forall k v ro rw. RAW k v ro rw ro
    getRO
        offset <- liftIO offsetTime
        captureRAW $ \Either SomeException (Seconds, a) -> IO ()
    continue ->
            PoolPriority -> Pool -> IO () -> IO ()
    forall a. PoolPriority -> Pool -> IO a -> IO ()
    addPool PoolPriority
    pri Pool
    globalPool (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
                offset <- IO Seconds
    offset
                continue $ (offset,) <$> res