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 qualified Control.Exception 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 (m :: Type -> Type) r.
MonadTunnelIO m =>
((forall a. m a -> IO (TunnelIO m a)) -> IO (TunnelIO m r)) -> m r
tunnelIO forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO (TunnelIO m a)
unlift -> forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
CE.mask forall a b. (a -> b) -> a -> b
$ \forall a. IO a -> IO a
restore -> forall a. m a -> IO (TunnelIO m a)
unlift forall a b. (a -> b) -> a -> b
$ (forall a. m a -> m a) -> m b
call forall a b. (a -> b) -> a -> b
$ forall (m :: Type -> Type).
MonadHoistIO m =>
(forall a. IO a -> IO a) -> m --> m
hoistIO 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 (m :: Type -> Type) b.
MonadTunnelIO m =>
((forall a. m a -> m a) -> m b) -> m b
mask forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
        a
a <- m a
before
        b
b <- forall (m :: Type -> Type) a.
MonadException m =>
m a -> m () -> m a
onException (forall a. m a -> m a
restore (a -> m b
thing a
a)) (a -> m ()
after a
a)
        a -> m ()
after a
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 = forall (m :: Type -> Type) a b.
(MonadException m, MonadTunnelIO m) =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracket (forall (m :: Type -> Type) a. Monad m => a -> m a
return ()) (forall a b. a -> b -> a
const m ()
handler) (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 = forall (m :: Type -> Type) a b.
(MonadException m, MonadTunnelIO m) =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracket m ()
before (forall a b. a -> b -> a
const m ()
after) (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 <- 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
    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 = forall (m :: Type -> Type) a b.
MonadException m =>
m a -> (a -> m ()) -> (a -> m b) -> m b
bracketNoMask m ()
before (forall a b. a -> b -> a
const m ()
after) (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
    forall (m :: Type -> Type) a. Monad m => a -> m a
return b
b