{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TypeFamilies #-}
module Control.Exception.Enclosed
(
catchAny
, handleAny
, tryAny
, catchDeep
, catchAnyDeep
, handleAnyDeep
, tryDeep
, tryAnyDeep
, catchIO
, handleIO
, tryIO
, asIOException
, asSomeException
) where
import Prelude
import Control.Concurrent (forkIOWithUnmask)
import Control.Concurrent.MVar (newEmptyMVar, putMVar, readMVar)
import Control.Exception
import Control.Monad (liftM)
import Control.Monad.Base (liftBase)
import Control.Monad.Trans.Control (MonadBaseControl, liftBaseWith, restoreM)
import Control.DeepSeq (NFData, ($!!))
import qualified Control.Exception.Lifted
catchAny :: MonadBaseControl IO m => m a -> (SomeException -> m a) -> m a
catchAny :: forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (SomeException -> m a) -> m a
catchAny m a
action SomeException -> m a
onE = m a -> m (Either SomeException a)
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> m (Either SomeException a)
tryAny m a
action m (Either SomeException a)
-> (Either SomeException a -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (SomeException -> m a)
-> (a -> m a) -> Either SomeException a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either SomeException -> m a
onE a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
handleAny :: MonadBaseControl IO m => (SomeException -> m a) -> m a -> m a
handleAny :: forall (m :: * -> *) a.
MonadBaseControl IO m =>
(SomeException -> m a) -> m a -> m a
handleAny = (m a -> (SomeException -> m a) -> m a)
-> (SomeException -> m a) -> m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip m a -> (SomeException -> m a) -> m a
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (SomeException -> m a) -> m a
catchAny
tryAny :: MonadBaseControl IO m => m a -> m (Either SomeException a)
tryAny :: forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> m (Either SomeException a)
tryAny m a
m =
(RunInBase m IO -> IO (Either SomeException (StM m a)))
-> m (Either SomeException (StM m a))
forall a. (RunInBase m IO -> IO a) -> m a
forall (b :: * -> *) (m :: * -> *) a.
MonadBaseControl b m =>
(RunInBase m b -> b a) -> m a
liftBaseWith (\RunInBase m IO
runInIO -> IO (StM m a) -> IO (Either SomeException (StM m a))
forall a. IO a -> IO (Either SomeException a)
tryAnyIO (m a -> IO (StM m a)
RunInBase m IO
runInIO m a
m)) m (Either SomeException (StM m a))
-> (Either SomeException (StM m a) -> m (Either SomeException a))
-> m (Either SomeException a)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
(SomeException -> m (Either SomeException a))
-> (StM m a -> m (Either SomeException a))
-> Either SomeException (StM m a)
-> m (Either SomeException a)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Either SomeException a -> m (Either SomeException a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either SomeException a -> m (Either SomeException a))
-> (SomeException -> Either SomeException a)
-> SomeException
-> m (Either SomeException a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> Either SomeException a
forall a b. a -> Either a b
Left) ((a -> Either SomeException a) -> m a -> m (Either SomeException a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> Either SomeException a
forall a b. b -> Either a b
Right (m a -> m (Either SomeException a))
-> (StM m a -> m a) -> StM m a -> m (Either SomeException a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StM m a -> m a
forall a. StM m a -> m a
forall (b :: * -> *) (m :: * -> *) a.
MonadBaseControl b m =>
StM m a -> m a
restoreM)
where
tryAnyIO :: IO a -> IO (Either SomeException a)
tryAnyIO :: forall a. IO a -> IO (Either SomeException a)
tryAnyIO IO a
action = do
MVar (Either SomeException a)
result <- IO (MVar (Either SomeException a))
forall a. IO (MVar a)
newEmptyMVar
IO ThreadId
-> (ThreadId -> IO ())
-> (ThreadId -> IO (Either SomeException a))
-> IO (Either SomeException a)
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
(((forall a. IO a -> IO a) -> IO ()) -> IO ThreadId
forkIOWithUnmask (\forall a. IO a -> IO a
restore -> IO a -> IO (Either SomeException a)
forall e a. Exception e => IO a -> IO (Either e a)
try (IO a -> IO a
forall a. IO a -> IO a
restore IO a
action) IO (Either SomeException a)
-> (Either SomeException a -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MVar (Either SomeException a) -> Either SomeException a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either SomeException a)
result))
(\ThreadId
t -> ThreadId -> AsyncException -> IO ()
forall e. Exception e => ThreadId -> e -> IO ()
throwTo ThreadId
t AsyncException
ThreadKilled)
(\ThreadId
_ -> Int -> IO (Either SomeException a) -> IO (Either SomeException a)
forall a. Int -> IO a -> IO a
retryCount Int
10 (MVar (Either SomeException a) -> IO (Either SomeException a)
forall a. MVar a -> IO a
readMVar MVar (Either SomeException a)
result))
retryCount :: Int -> IO a -> IO a
retryCount :: forall a. Int -> IO a -> IO a
retryCount Int
cnt0 IO a
action =
Int -> IO a
loop Int
cnt0
where
loop :: Int -> IO a
loop Int
0 = IO a
action
loop Int
cnt = IO a
action IO a -> (BlockedIndefinitelyOnMVar -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`Control.Exception.catch`
\BlockedIndefinitelyOnMVar
BlockedIndefinitelyOnMVar -> Int -> IO a
loop (Int
cnt Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
catchDeep :: (Exception e, NFData a, MonadBaseControl IO m) => m a -> (e -> m a) -> m a
catchDeep :: forall e a (m :: * -> *).
(Exception e, NFData a, MonadBaseControl IO m) =>
m a -> (e -> m a) -> m a
catchDeep m a
action e -> m a
onE = m a -> m (Either e a)
forall e a (m :: * -> *).
(Exception e, NFData a, MonadBaseControl IO m) =>
m a -> m (Either e a)
tryDeep m a
action m (Either e a) -> (Either e a -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (e -> m a) -> (a -> m a) -> Either e a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either e -> m a
onE a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
catchAnyDeep :: (NFData a, MonadBaseControl IO m) => m a -> (SomeException -> m a) -> m a
catchAnyDeep :: forall a (m :: * -> *).
(NFData a, MonadBaseControl IO m) =>
m a -> (SomeException -> m a) -> m a
catchAnyDeep m a
action SomeException -> m a
onE = m a -> m (Either SomeException a)
forall a (m :: * -> *).
(NFData a, MonadBaseControl IO m) =>
m a -> m (Either SomeException a)
tryAnyDeep m a
action m (Either SomeException a)
-> (Either SomeException a -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (SomeException -> m a)
-> (a -> m a) -> Either SomeException a -> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either SomeException -> m a
onE a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
handleAnyDeep :: (NFData a, MonadBaseControl IO m) => (SomeException -> m a) -> m a -> m a
handleAnyDeep :: forall a (m :: * -> *).
(NFData a, MonadBaseControl IO m) =>
(SomeException -> m a) -> m a -> m a
handleAnyDeep = (m a -> (SomeException -> m a) -> m a)
-> (SomeException -> m a) -> m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip m a -> (SomeException -> m a) -> m a
forall a (m :: * -> *).
(NFData a, MonadBaseControl IO m) =>
m a -> (SomeException -> m a) -> m a
catchAnyDeep
tryDeep :: (Exception e, NFData a, MonadBaseControl IO m)
=> m a
-> m (Either e a)
tryDeep :: forall e a (m :: * -> *).
(Exception e, NFData a, MonadBaseControl IO m) =>
m a -> m (Either e a)
tryDeep m a
m = m a -> m (Either e a)
forall (m :: * -> *) e a.
(MonadBaseControl IO m, Exception e) =>
m a -> m (Either e a)
Control.Exception.Lifted.try (m a -> m (Either e a)) -> m a -> m (Either e a)
forall a b. (a -> b) -> a -> b
$ do
a
x <- m a
m
IO a -> m a
forall α. IO α -> m α
forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ a -> IO a
forall a. a -> IO a
evaluate (a -> IO a) -> a -> IO a
forall a b. NFData a => (a -> b) -> a -> b
$!! a
x
tryAnyDeep :: (NFData a, MonadBaseControl IO m)
=> m a
-> m (Either SomeException a)
tryAnyDeep :: forall a (m :: * -> *).
(NFData a, MonadBaseControl IO m) =>
m a -> m (Either SomeException a)
tryAnyDeep m a
m = m a -> m (Either SomeException a)
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> m (Either SomeException a)
tryAny (m a -> m (Either SomeException a))
-> m a -> m (Either SomeException a)
forall a b. (a -> b) -> a -> b
$ do
a
x <- m a
m
IO a -> m a
forall α. IO α -> m α
forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ a -> IO a
forall a. a -> IO a
evaluate (a -> IO a) -> a -> IO a
forall a b. NFData a => (a -> b) -> a -> b
$!! a
x
catchIO :: MonadBaseControl IO m => m a -> (IOException -> m a) -> m a
catchIO :: forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (IOException -> m a) -> m a
catchIO = m a -> (IOException -> m a) -> m a
forall (m :: * -> *) e a.
(MonadBaseControl IO m, Exception e) =>
m a -> (e -> m a) -> m a
Control.Exception.Lifted.catch
handleIO :: MonadBaseControl IO m => (IOException -> m a) -> m a -> m a
handleIO :: forall (m :: * -> *) a.
MonadBaseControl IO m =>
(IOException -> m a) -> m a -> m a
handleIO = (IOException -> m a) -> m a -> m a
forall (m :: * -> *) e a.
(MonadBaseControl IO m, Exception e) =>
(e -> m a) -> m a -> m a
Control.Exception.Lifted.handle
tryIO :: MonadBaseControl IO m => m a -> m (Either IOException a)
tryIO :: forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> m (Either IOException a)
tryIO = m a -> m (Either IOException a)
forall (m :: * -> *) e a.
(MonadBaseControl IO m, Exception e) =>
m a -> m (Either e a)
Control.Exception.Lifted.try
asSomeException :: SomeException -> SomeException
asSomeException :: SomeException -> SomeException
asSomeException = SomeException -> SomeException
forall a. a -> a
id
asIOException :: IOException -> IOException
asIOException :: IOException -> IOException
asIOException = IOException -> IOException
forall a. a -> a
id