module Control.Monad.Ology.General.Exception
    ( module Control.Monad.Ology.General.Exception.Class
    , module Control.Monad.Ology.General.Exception
    , CE.SomeException
    , CE.evaluate
    ) where

import Control.Exception qualified as CE
import Control.Monad.Ology.General.Exception.Class
import Control.Monad.Ology.General.Function
import Control.Monad.Ology.General.Trans.Hoist
import Control.Monad.Ology.General.Trans.Tunnel
import Import

-- | Run with asynchronous exceptions masked, passing an unmask function.
mask ::
       forall m b. MonadTunnelIO m
    => ((forall a. m a -> m a) -> m b)
    -> m b
mask :: forall (m :: Type -> Type) b.
MonadTunnelIO m =>
((forall a. m a -> m a) -> m b) -> m b
mask (forall a. m a -> m a) -> m b
call = ((forall a. m a -> IO (TunnelIO m a)) -> IO (TunnelIO m b)) -> m b
forall r.
((forall a. m a -> IO (TunnelIO m a)) -> IO (TunnelIO m r)) -> m r
forall (m :: Type -> Type) r.
MonadTunnelIO m =>
((forall a. m a -> IO (TunnelIO m a)) -> IO (TunnelIO m r)) -> m r
tunnelIO (((forall a. m a -> IO (TunnelIO m a)) -> IO (TunnelIO m b))
 -> m b)
-> ((forall a. m a -> IO (TunnelIO m a)) -> IO (TunnelIO m b))
-> m b
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO (TunnelIO m a)
unlift -> ((forall a. IO a -> IO a) -> IO (TunnelIO m b))
-> IO (TunnelIO m b)
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
CE.mask (((forall a. IO a -> IO a) -> IO (TunnelIO m b))
 -> IO (TunnelIO m b))
-> ((forall a. IO a -> IO a) -> IO (TunnelIO m b))
-> IO (TunnelIO m b)
forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
restore -> m b -> IO (TunnelIO m b)
forall a. m a -> IO (TunnelIO m a)
unlift (m b -> IO (TunnelIO m b)) -> m b -> IO (TunnelIO m b)
forall a b. (a -> b) -> a -> b
$ (forall a. m a -> m a) -> m b
call ((forall a. m a -> m a) -> m b) -> (forall a. m a -> m a) -> m b
forall a b. (a -> b) -> a -> b
$ (forall a. IO a -> IO a) -> forall a. m a -> m a
forall (m :: Type -> Type).
MonadHoistIO m =>
(forall a. IO a -> IO a) -> m --> m
hoistIO IO a -> IO a
forall a. IO a -> IO a
restore

-- | Bracket an operation with before and after operations.
-- The whole thing is masked, with the main operation unmasked.
bracket ::
       forall m a b. (MonadException m, MonadTunnelIO m)
    => m a
    -> (a -> m ())
    -> (a -> m b)
    -> m b
bracket :: forall (m :: Type -> Type) a b.
(MonadException m, MonadTunnelIO m) =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracket m a
before a -> m ()
after a -> m b
thing =
    ((forall a. m a -> m a) -> m b) -> m b
forall (m :: Type -> Type) b.
MonadTunnelIO m =>
((forall a. m a -> m a) -> m b) -> m b
mask (((forall a. m a -> m a) -> m b) -> m b)
-> ((forall a. m a -> m a) -> m b) -> m b
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
        a
a <- m a
before
        b
b <- m b -> m () -> m b
forall (m :: Type -> Type) a.
MonadException m =>
m a -> m () -> m a
onException (m b -> m b
forall a. m a -> m a
restore (a -> m b
thing a
a)) (a -> m ()
after a
a)
        a -> m ()
after a
a
        b -> m b
forall a. a -> m a
forall (m :: Type -> Type) a. Monad m => a -> m a
return b
b

-- | Variant of 'bracket'.
finally ::
       forall m a. (MonadException m, MonadTunnelIO m)
    => m a
    -> m ()
    -> m a
finally :: forall (m :: Type -> Type) a.
(MonadException m, MonadTunnelIO m) =>
m a -> m () -> m a
finally m a
ma m ()
handler = m () -> (() -> m ()) -> (() -> m a) -> m a
forall (m :: Type -> Type) a b.
(MonadException m, MonadTunnelIO m) =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracket (() -> m ()
forall a. a -> m a
forall (m :: Type -> Type) a. Monad m => a -> m a
return ()) (m () -> () -> m ()
forall a b. a -> b -> a
const m ()
handler) (m a -> () -> m a
forall a b. a -> b -> a
const m a
ma)

-- | Variant of 'bracket'.
bracket_ ::
       forall m. (MonadException m, MonadTunnelIO m)
    => m ()
    -> m ()
    -> m --> m
bracket_ :: forall (m :: Type -> Type).
(MonadException m, MonadTunnelIO m) =>
m () -> m () -> m --> m
bracket_ m ()
before m ()
after m a
thing = m () -> (() -> m ()) -> (() -> m a) -> m a
forall (m :: Type -> Type) a b.
(MonadException m, MonadTunnelIO m) =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracket m ()
before (m () -> () -> m ()
forall a b. a -> b -> a
const m ()
after) (m a -> () -> m a
forall a b. a -> b -> a
const m a
thing)

-- | Like 'bracket', but doesn\'t mask asynchronous exceptions.
bracketNoMask ::
       forall m a b. MonadException m
    => m a
    -> (a -> m ())
    -> (a -> m b)
    -> m b
bracketNoMask :: forall (m :: Type -> Type) a b.
MonadException m =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracketNoMask m a
before a -> m ()
after a -> m b
thing = do
    a
a <- m a
before
    b
b <- m b -> m () -> m b
forall (m :: Type -> Type) a.
MonadException m =>
m a -> m () -> m a
onException (a -> m b
thing a
a) (a -> m ()
after a
a)
    a -> m ()
after a
a
    b -> m b
forall a. a -> m a
forall (m :: Type -> Type) a. Monad m => a -> m a
return b
b

-- | Variant of 'bracketNoMask'.
bracketNoMask_ ::
       forall m. MonadException m
    => m ()
    -> m ()
    -> m --> m
bracketNoMask_ :: forall (m :: Type -> Type).
MonadException m =>
m () -> m () -> m --> m
bracketNoMask_ m ()
before m ()
after m a
thing = m () -> (() -> m ()) -> (() -> m a) -> m a
forall (m :: Type -> Type) a b.
MonadException m =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracketNoMask m ()
before (m () -> () -> m ()
forall a b. a -> b -> a
const m ()
after) (m a -> () -> m a
forall a b. a -> b -> a
const m a
thing)

-- | Like 'bracketNoMask', but doesn\'t catch any exceptions.
bracketFake ::
       forall m a b. Monad m
    => m a
    -> (a -> m ())
    -> (a -> m b)
    -> m b
bracketFake :: forall (m :: Type -> Type) a b.
Monad m =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracketFake m a
before a -> m ()
after a -> m b
thing = do
    a
a <- m a
before
    b
b <- a -> m b
thing a
a
    a -> m ()
after a
a
    b -> m b
forall a. a -> m a
forall (m :: Type -> Type) a. Monad m => a -> m a
return b
b