module Ki.Internal.Scope
( Scope,
scoped,
awaitAll,
fork,
forkWith,
forkWith_,
fork_,
forkTry,
forkTryWith,
)
where
import qualified Control.Concurrent
import Control.Exception
( Exception (fromException, toException),
MaskingState (..),
SomeAsyncException,
asyncExceptionFromException,
asyncExceptionToException,
catch,
pattern ErrorCall,
)
import qualified Data.IntMap.Lazy as IntMap
import Data.Void (Void, absurd)
import GHC.Conc
( STM,
TVar,
atomically,
enableAllocationLimit,
labelThread,
newTVarIO,
readTVar,
retry,
setAllocationCounter,
throwSTM,
writeTVar,
)
import GHC.IO (unsafeUnmask)
import Ki.Internal.ByteCount
import Ki.Internal.Counter
import Ki.Internal.Prelude
import Ki.Internal.Thread
import GHC.Conc.Sync (readTVarIO)
data Scope = Scope
{
Scope -> MVar SomeException
childExceptionVar :: {-# UNPACK #-} !(MVar SomeException),
Scope -> TVar (IntMap ThreadId)
childrenVar :: {-# UNPACK #-} !(TVar (IntMap ThreadId)),
Scope -> Counter
nextChildIdCounter :: {-# UNPACK #-} !Counter,
Scope -> ThreadId
parentThreadId :: {-# UNPACK #-} !ThreadId,
Scope -> TVar Int
startingVar :: {-# UNPACK #-} !(TVar Int)
}
data ScopeClosing
= ScopeClosing
instance Show ScopeClosing where
show :: ScopeClosing -> String
show ScopeClosing
_ = String
"ScopeClosing"
instance Exception ScopeClosing where
toException :: ScopeClosing -> SomeException
toException = forall e. Exception e => e -> SomeException
asyncExceptionToException
fromException :: SomeException -> Maybe ScopeClosing
fromException = forall e. Exception e => SomeException -> Maybe e
asyncExceptionFromException
isScopeClosingException :: SomeException -> Bool
isScopeClosingException :: SomeException -> Bool
isScopeClosingException SomeException
exception =
case forall e. Exception e => SomeException -> Maybe e
fromException SomeException
exception of
Just ScopeClosing
ScopeClosing -> Bool
True
Maybe ScopeClosing
_ -> Bool
False
pattern IsScopeClosingException :: SomeException
pattern $mIsScopeClosingException :: forall {r}. SomeException -> ((# #) -> r) -> ((# #) -> r) -> r
IsScopeClosingException <- (isScopeClosingException -> True)
scoped :: (Scope -> IO a) -> IO a
scoped :: forall a. (Scope -> IO a) -> IO a
scoped Scope -> IO a
action = do
scope :: Scope
scope@Scope {MVar SomeException
childExceptionVar :: MVar SomeException
$sel:childExceptionVar:Scope :: Scope -> MVar SomeException
childExceptionVar, TVar (IntMap ThreadId)
childrenVar :: TVar (IntMap ThreadId)
$sel:childrenVar:Scope :: Scope -> TVar (IntMap ThreadId)
childrenVar, TVar Int
startingVar :: TVar Int
$sel:startingVar:Scope :: Scope -> TVar Int
startingVar} <- IO Scope
allocateScope
forall b. ((forall a. IO a -> IO a) -> IO b) -> IO b
uninterruptibleMask \forall a. IO a -> IO a
restore -> do
Either SomeException a
result <- forall e a. Exception e => IO a -> IO (Either e a)
try (forall a. IO a -> IO a
restore (Scope -> IO a
action Scope
scope))
!IntMap ThreadId
livingChildren <- do
IntMap ThreadId
livingChildren0 <-
forall a. STM a -> IO a
atomically do
TVar Int -> STM ()
blockUntil0 TVar Int
startingVar
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
startingVar (-Int
1)
forall a. TVar a -> STM a
readTVar TVar (IntMap ThreadId)
childrenVar
forall (f :: * -> *) a. Applicative f => a -> f a
pure case Either SomeException a
result of
Left (forall e. Exception e => SomeException -> Maybe e
fromException -> Just ThreadFailed {Int
$sel:childId:ThreadFailed :: ThreadFailed -> Int
childId :: Int
childId}) -> forall a. Int -> IntMap a -> IntMap a
IntMap.delete Int
childId IntMap ThreadId
livingChildren0
Either SomeException a
_ -> IntMap ThreadId
livingChildren0
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (forall a. IntMap a -> [a]
IntMap.elems IntMap ThreadId
livingChildren) \ThreadId
livingChild -> forall e. Exception e => ThreadId -> e -> IO ()
throwTo ThreadId
livingChild ScopeClosing
ScopeClosing
forall a. STM a -> IO a
atomically (forall a. TVar (IntMap a) -> STM ()
blockUntilEmpty TVar (IntMap ThreadId)
childrenVar)
case Either SomeException a
result of
Left SomeException
exception -> forall e a. Exception e => e -> IO a
throwIO (SomeException -> SomeException
unwrapThreadFailed SomeException
exception)
Right a
value ->
forall a. MVar a -> IO (Maybe a)
tryTakeMVar MVar SomeException
childExceptionVar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe SomeException
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
value
Just SomeException
exception -> forall e a. Exception e => e -> IO a
throwIO SomeException
exception
allocateScope :: IO Scope
allocateScope :: IO Scope
allocateScope = do
MVar SomeException
childExceptionVar <- forall a. IO (MVar a)
newEmptyMVar
TVar (IntMap ThreadId)
childrenVar <- forall a. a -> IO (TVar a)
newTVarIO forall a. IntMap a
IntMap.empty
Counter
nextChildIdCounter <- IO Counter
newCounter
ThreadId
parentThreadId <- IO ThreadId
myThreadId
TVar Int
startingVar <- forall a. a -> IO (TVar a)
newTVarIO Int
0
forall (f :: * -> *) a. Applicative f => a -> f a
pure Scope {MVar SomeException
childExceptionVar :: MVar SomeException
$sel:childExceptionVar:Scope :: MVar SomeException
childExceptionVar, TVar (IntMap ThreadId)
childrenVar :: TVar (IntMap ThreadId)
$sel:childrenVar:Scope :: TVar (IntMap ThreadId)
childrenVar, Counter
nextChildIdCounter :: Counter
$sel:nextChildIdCounter:Scope :: Counter
nextChildIdCounter, ThreadId
parentThreadId :: ThreadId
$sel:parentThreadId:Scope :: ThreadId
parentThreadId, TVar Int
startingVar :: TVar Int
$sel:startingVar:Scope :: TVar Int
startingVar}
spawn :: Scope -> ThreadOptions -> (Int -> (forall x. IO x -> IO x) -> UnexceptionalIO ()) -> IO ThreadId
spawn :: Scope
-> ThreadOptions
-> (Int -> (forall a. IO a -> IO a) -> UnexceptionalIO ())
-> IO ThreadId
spawn
Scope {TVar (IntMap ThreadId)
childrenVar :: TVar (IntMap ThreadId)
$sel:childrenVar:Scope :: Scope -> TVar (IntMap ThreadId)
childrenVar, Counter
nextChildIdCounter :: Counter
$sel:nextChildIdCounter:Scope :: Scope -> Counter
nextChildIdCounter, TVar Int
startingVar :: TVar Int
$sel:startingVar:Scope :: Scope -> TVar Int
startingVar}
ThreadOptions {ThreadAffinity
$sel:affinity:ThreadOptions :: ThreadOptions -> ThreadAffinity
affinity :: ThreadAffinity
affinity, Maybe ByteCount
$sel:allocationLimit:ThreadOptions :: ThreadOptions -> Maybe ByteCount
allocationLimit :: Maybe ByteCount
allocationLimit, String
$sel:label:ThreadOptions :: ThreadOptions -> String
label :: String
label, $sel:maskingState:ThreadOptions :: ThreadOptions -> MaskingState
maskingState = MaskingState
requestedChildMaskingState}
Int -> (forall a. IO a -> IO a) -> UnexceptionalIO ()
action = do
forall a. IO a -> IO a
interruptiblyMasked do
forall a. STM a -> IO a
atomically do
Int
n <- forall a. TVar a -> STM a
readTVar TVar Int
startingVar
if Int
n forall a. Ord a => a -> a -> Bool
< Int
0
then forall e a. Exception e => e -> STM a
throwSTM (String -> ErrorCall
ErrorCall String
"ki: scope closed")
else forall a. TVar a -> a -> STM ()
writeTVar TVar Int
startingVar forall a b. (a -> b) -> a -> b
$! Int
n forall a. Num a => a -> a -> a
+ Int
1
Int
childId <- Counter -> IO Int
incrCounter Counter
nextChildIdCounter
ThreadId
childThreadId <-
ThreadAffinity -> IO () -> IO ThreadId
forkWithAffinity ThreadAffinity
affinity do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
label)) do
ThreadId
childThreadId <- IO ThreadId
myThreadId
ThreadId -> String -> IO ()
labelThread ThreadId
childThreadId String
label
case Maybe ByteCount
allocationLimit of
Maybe ByteCount
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Just ByteCount
bytes -> do
Int64 -> IO ()
setAllocationCounter (ByteCount -> Int64
byteCountToInt64 ByteCount
bytes)
IO ()
enableAllocationLimit
let
atRequestedMaskingState :: IO a -> IO a
atRequestedMaskingState :: forall a. IO a -> IO a
atRequestedMaskingState =
case MaskingState
requestedChildMaskingState of
MaskingState
Unmasked -> forall a. IO a -> IO a
unsafeUnmask
MaskingState
MaskedInterruptible -> forall a. a -> a
id
MaskingState
MaskedUninterruptible -> forall a. IO a -> IO a
uninterruptiblyMasked
forall a. UnexceptionalIO a -> IO a
runUnexceptionalIO (Int -> (forall a. IO a -> IO a) -> UnexceptionalIO ()
action Int
childId forall a. IO a -> IO a
atRequestedMaskingState)
forall a. STM a -> IO a
atomically (TVar (IntMap ThreadId) -> Int -> STM ()
unrecordChild TVar (IntMap ThreadId)
childrenVar Int
childId)
forall a. STM a -> IO a
atomically do
Int
n <- forall a. TVar a -> STM a
readTVar TVar Int
startingVar
forall a. TVar a -> a -> STM ()
writeTVar TVar Int
startingVar forall a b. (a -> b) -> a -> b
$! Int
n forall a. Num a => a -> a -> a
- Int
1
TVar (IntMap ThreadId) -> Int -> ThreadId -> STM ()
recordChild TVar (IntMap ThreadId)
childrenVar Int
childId ThreadId
childThreadId
forall (f :: * -> *) a. Applicative f => a -> f a
pure ThreadId
childThreadId
recordChild :: TVar (IntMap ThreadId) -> Int -> ThreadId -> STM ()
recordChild :: TVar (IntMap ThreadId) -> Int -> ThreadId -> STM ()
recordChild TVar (IntMap ThreadId)
childrenVar Int
childId ThreadId
childThreadId = do
IntMap ThreadId
children <- forall a. TVar a -> STM a
readTVar TVar (IntMap ThreadId)
childrenVar
forall a. TVar a -> a -> STM ()
writeTVar TVar (IntMap ThreadId)
childrenVar forall a b. (a -> b) -> a -> b
$! forall a. (Maybe a -> Maybe a) -> Int -> IntMap a -> IntMap a
IntMap.alter (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a. a -> Maybe a
Just ThreadId
childThreadId) (forall a b. a -> b -> a
const forall a. Maybe a
Nothing)) Int
childId IntMap ThreadId
children
unrecordChild :: TVar (IntMap ThreadId) -> Int -> STM ()
unrecordChild :: TVar (IntMap ThreadId) -> Int -> STM ()
unrecordChild TVar (IntMap ThreadId)
childrenVar Int
childId = do
IntMap ThreadId
children <- forall a. TVar a -> STM a
readTVar TVar (IntMap ThreadId)
childrenVar
forall a. TVar a -> a -> STM ()
writeTVar TVar (IntMap ThreadId)
childrenVar forall a b. (a -> b) -> a -> b
$! forall a. (Maybe a -> Maybe a) -> Int -> IntMap a -> IntMap a
IntMap.alter (forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a. a -> Maybe a
Just forall a. HasCallStack => a
undefined) (forall a b. a -> b -> a
const forall a. Maybe a
Nothing)) Int
childId IntMap ThreadId
children
forkWithAffinity :: ThreadAffinity -> IO () -> IO ThreadId
forkWithAffinity :: ThreadAffinity -> IO () -> IO ThreadId
forkWithAffinity = \case
ThreadAffinity
Unbound -> IO () -> IO ThreadId
forkIO
Capability Int
n -> Int -> IO () -> IO ThreadId
forkOn Int
n
ThreadAffinity
OsThread -> IO () -> IO ThreadId
Control.Concurrent.forkOS
awaitAll :: Scope -> STM ()
awaitAll :: Scope -> STM ()
awaitAll Scope {TVar (IntMap ThreadId)
childrenVar :: TVar (IntMap ThreadId)
$sel:childrenVar:Scope :: Scope -> TVar (IntMap ThreadId)
childrenVar, TVar Int
startingVar :: TVar Int
$sel:startingVar:Scope :: Scope -> TVar Int
startingVar} = do
forall a. TVar (IntMap a) -> STM ()
blockUntilEmpty TVar (IntMap ThreadId)
childrenVar
TVar Int -> STM ()
blockUntil0 TVar Int
startingVar
blockUntilEmpty :: TVar (IntMap a) -> STM ()
blockUntilEmpty :: forall a. TVar (IntMap a) -> STM ()
blockUntilEmpty TVar (IntMap a)
var = do
IntMap a
x <- forall a. TVar a -> STM a
readTVar TVar (IntMap a)
var
if forall a. IntMap a -> Bool
IntMap.null IntMap a
x then forall (f :: * -> *) a. Applicative f => a -> f a
pure () else forall a. STM a
retry
blockUntil0 :: TVar Int -> STM ()
blockUntil0 :: TVar Int -> STM ()
blockUntil0 TVar Int
var = do
Int
x <- forall a. TVar a -> STM a
readTVar TVar Int
var
if Int
x forall a. Eq a => a -> a -> Bool
== Int
0 then forall (f :: * -> *) a. Applicative f => a -> f a
pure () else forall a. STM a
retry
fork :: Scope -> IO a -> IO (Thread a)
fork :: forall a. Scope -> IO a -> IO (Thread a)
fork Scope
scope =
forall a. Scope -> ThreadOptions -> IO a -> IO (Thread a)
forkWith Scope
scope ThreadOptions
defaultThreadOptions
fork_ :: Scope -> IO Void -> IO ()
fork_ :: Scope -> IO Void -> IO ()
fork_ Scope
scope =
Scope -> ThreadOptions -> IO Void -> IO ()
forkWith_ Scope
scope ThreadOptions
defaultThreadOptions
forkWith :: Scope -> ThreadOptions -> IO a -> IO (Thread a)
forkWith :: forall a. Scope -> ThreadOptions -> IO a -> IO (Thread a)
forkWith Scope
scope ThreadOptions
opts IO a
action = do
TVar (Maybe (Either SomeException a))
resultVar <- forall a. a -> IO (TVar a)
newTVarIO forall a. Maybe a
Nothing
ThreadId
ident <-
Scope
-> ThreadOptions
-> (Int -> (forall a. IO a -> IO a) -> UnexceptionalIO ())
-> IO ThreadId
spawn Scope
scope ThreadOptions
opts \Int
childId forall a. IO a -> IO a
masking -> do
Either SomeException a
result <- forall a. IO a -> UnexceptionalIO (Either SomeException a)
unexceptionalTry (forall a. IO a -> IO a
masking IO a
action)
case Either SomeException a
result of
Left SomeException
exception ->
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when
(Bool -> Bool
not (SomeException -> Bool
isScopeClosingException SomeException
exception))
(Scope -> Int -> SomeException -> UnexceptionalIO ()
propagateException Scope
scope Int
childId SomeException
exception)
Right a
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
forall a. IO a -> UnexceptionalIO a
UnexceptionalIO (forall a. STM a -> IO a
atomically (forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe (Either SomeException a))
resultVar (forall a. a -> Maybe a
Just Either SomeException a
result)))
let doAwait :: STM a
doAwait =
forall a. TVar a -> STM a
readTVar TVar (Maybe (Either SomeException a))
resultVar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe (Either SomeException a)
Nothing -> forall a. STM a
retry
Just (Left SomeException
exception) -> forall e a. Exception e => e -> STM a
throwSTM SomeException
exception
Just (Right a
value) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure a
value
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. ThreadId -> STM a -> Thread a
makeThread ThreadId
ident STM a
doAwait)
forkWith_ :: Scope -> ThreadOptions -> IO Void -> IO ()
forkWith_ :: Scope -> ThreadOptions -> IO Void -> IO ()
forkWith_ Scope
scope ThreadOptions
opts IO Void
action = do
ThreadId
_childThreadId <-
Scope
-> ThreadOptions
-> (Int -> (forall a. IO a -> IO a) -> UnexceptionalIO ())
-> IO ThreadId
spawn Scope
scope ThreadOptions
opts \Int
childId forall a. IO a -> IO a
masking ->
forall a b.
(SomeException -> UnexceptionalIO b)
-> (a -> UnexceptionalIO b) -> IO a -> UnexceptionalIO b
unexceptionalTryEither
(\SomeException
exception -> forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (SomeException -> Bool
isScopeClosingException SomeException
exception)) (Scope -> Int -> SomeException -> UnexceptionalIO ()
propagateException Scope
scope Int
childId SomeException
exception))
forall a. Void -> a
absurd
(forall a. IO a -> IO a
masking IO Void
action)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
forkTry :: forall e a. Exception e => Scope -> IO a -> IO (Thread (Either e a))
forkTry :: forall e a.
Exception e =>
Scope -> IO a -> IO (Thread (Either e a))
forkTry Scope
scope =
forall e a.
Exception e =>
Scope -> ThreadOptions -> IO a -> IO (Thread (Either e a))
forkTryWith Scope
scope ThreadOptions
defaultThreadOptions
forkTryWith :: forall e a. Exception e => Scope -> ThreadOptions -> IO a -> IO (Thread (Either e a))
forkTryWith :: forall e a.
Exception e =>
Scope -> ThreadOptions -> IO a -> IO (Thread (Either e a))
forkTryWith Scope
scope ThreadOptions
opts IO a
action = do
TVar (Maybe (Either SomeException a))
resultVar <- forall a. a -> IO (TVar a)
newTVarIO forall a. Maybe a
Nothing
ThreadId
childThreadId <-
Scope
-> ThreadOptions
-> (Int -> (forall a. IO a -> IO a) -> UnexceptionalIO ())
-> IO ThreadId
spawn Scope
scope ThreadOptions
opts \Int
childId forall a. IO a -> IO a
masking -> do
Either SomeException a
result <- forall a. IO a -> UnexceptionalIO (Either SomeException a)
unexceptionalTry (forall a. IO a -> IO a
masking IO a
action)
case Either SomeException a
result of
Left SomeException
exception -> do
let shouldPropagate :: Bool
shouldPropagate =
if SomeException -> Bool
isScopeClosingException SomeException
exception
then Bool
False
else case forall e. Exception e => SomeException -> Maybe e
fromException @e SomeException
exception of
Maybe e
Nothing -> Bool
True
Just e
_ -> SomeException -> Bool
isAsyncException SomeException
exception
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
shouldPropagate (Scope -> Int -> SomeException -> UnexceptionalIO ()
propagateException Scope
scope Int
childId SomeException
exception)
Right a
_value -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
forall a. IO a -> UnexceptionalIO a
UnexceptionalIO (forall a. STM a -> IO a
atomically (forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe (Either SomeException a))
resultVar (forall a. a -> Maybe a
Just Either SomeException a
result)))
let doAwait :: STM (Either e a)
doAwait =
forall a. TVar a -> STM a
readTVar TVar (Maybe (Either SomeException a))
resultVar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe (Either SomeException a)
Nothing -> forall a. STM a
retry
Just (Left SomeException
exception) ->
case forall e. Exception e => SomeException -> Maybe e
fromException @e SomeException
exception of
Maybe e
Nothing -> forall e a. Exception e => e -> STM a
throwSTM SomeException
exception
Just e
expectedException -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. a -> Either a b
Left e
expectedException)
Just (Right a
value) -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a b. b -> Either a b
Right a
value)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. ThreadId -> STM a -> Thread a
makeThread ThreadId
childThreadId STM (Either e a)
doAwait)
where
isAsyncException :: SomeException -> Bool
isAsyncException :: SomeException -> Bool
isAsyncException SomeException
exception =
case forall e. Exception e => SomeException -> Maybe e
fromException @SomeAsyncException SomeException
exception of
Maybe SomeAsyncException
Nothing -> Bool
False
Just SomeAsyncException
_ -> Bool
True
propagateException :: Scope -> Int -> SomeException -> UnexceptionalIO ()
propagateException :: Scope -> Int -> SomeException -> UnexceptionalIO ()
propagateException Scope {MVar SomeException
childExceptionVar :: MVar SomeException
$sel:childExceptionVar:Scope :: Scope -> MVar SomeException
childExceptionVar, ThreadId
parentThreadId :: ThreadId
$sel:parentThreadId:Scope :: Scope -> ThreadId
parentThreadId, TVar Int
startingVar :: TVar Int
$sel:startingVar:Scope :: Scope -> TVar Int
startingVar} Int
childId SomeException
exception =
forall a. IO a -> UnexceptionalIO a
UnexceptionalIO (forall a. TVar a -> IO a
readTVarIO TVar Int
startingVar) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
-1 -> UnexceptionalIO ()
tryPutChildExceptionVar
Int
_ -> UnexceptionalIO ()
loop
where
loop :: UnexceptionalIO ()
loop :: UnexceptionalIO ()
loop =
forall a. IO a -> UnexceptionalIO (Either SomeException a)
unexceptionalTry (forall e. Exception e => ThreadId -> e -> IO ()
throwTo ThreadId
parentThreadId ThreadFailed {Int
childId :: Int
$sel:childId:ThreadFailed :: Int
childId, SomeException
$sel:exception:ThreadFailed :: SomeException
exception :: SomeException
exception}) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left SomeException
IsScopeClosingException -> UnexceptionalIO ()
tryPutChildExceptionVar
Left SomeException
_ -> UnexceptionalIO ()
loop
Right ()
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
tryPutChildExceptionVar :: UnexceptionalIO ()
tryPutChildExceptionVar :: UnexceptionalIO ()
tryPutChildExceptionVar =
forall a. IO a -> UnexceptionalIO a
UnexceptionalIO (forall (f :: * -> *) a. Functor f => f a -> f ()
void (forall a. MVar a -> a -> IO Bool
tryPutMVar MVar SomeException
childExceptionVar SomeException
exception))
newtype UnexceptionalIO a = UnexceptionalIO
{forall a. UnexceptionalIO a -> IO a
runUnexceptionalIO :: IO a}
deriving newtype (Functor UnexceptionalIO
forall a. a -> UnexceptionalIO a
forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO a
forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO b
forall a b.
UnexceptionalIO (a -> b) -> UnexceptionalIO a -> UnexceptionalIO b
forall a b c.
(a -> b -> c)
-> UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO a
$c<* :: forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO a
*> :: forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO b
$c*> :: forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO b
liftA2 :: forall a b c.
(a -> b -> c)
-> UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO c
$cliftA2 :: forall a b c.
(a -> b -> c)
-> UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO c
<*> :: forall a b.
UnexceptionalIO (a -> b) -> UnexceptionalIO a -> UnexceptionalIO b
$c<*> :: forall a b.
UnexceptionalIO (a -> b) -> UnexceptionalIO a -> UnexceptionalIO b
pure :: forall a. a -> UnexceptionalIO a
$cpure :: forall a. a -> UnexceptionalIO a
Applicative, forall a b. a -> UnexceptionalIO b -> UnexceptionalIO a
forall a b. (a -> b) -> UnexceptionalIO a -> UnexceptionalIO b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> UnexceptionalIO b -> UnexceptionalIO a
$c<$ :: forall a b. a -> UnexceptionalIO b -> UnexceptionalIO a
fmap :: forall a b. (a -> b) -> UnexceptionalIO a -> UnexceptionalIO b
$cfmap :: forall a b. (a -> b) -> UnexceptionalIO a -> UnexceptionalIO b
Functor, Applicative UnexceptionalIO
forall a. a -> UnexceptionalIO a
forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO b
forall a b.
UnexceptionalIO a -> (a -> UnexceptionalIO b) -> UnexceptionalIO b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> UnexceptionalIO a
$creturn :: forall a. a -> UnexceptionalIO a
>> :: forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO b
$c>> :: forall a b.
UnexceptionalIO a -> UnexceptionalIO b -> UnexceptionalIO b
>>= :: forall a b.
UnexceptionalIO a -> (a -> UnexceptionalIO b) -> UnexceptionalIO b
$c>>= :: forall a b.
UnexceptionalIO a -> (a -> UnexceptionalIO b) -> UnexceptionalIO b
Monad)
unexceptionalTry :: forall a. IO a -> UnexceptionalIO (Either SomeException a)
unexceptionalTry :: forall a. IO a -> UnexceptionalIO (Either SomeException a)
unexceptionalTry =
coerce :: forall a b. Coercible a b => a -> b
coerce @(IO a -> IO (Either SomeException a)) forall e a. Exception e => IO a -> IO (Either e a)
try
unexceptionalTryEither ::
forall a b.
(SomeException -> UnexceptionalIO b) ->
(a -> UnexceptionalIO b) ->
IO a ->
UnexceptionalIO b
unexceptionalTryEither :: forall a b.
(SomeException -> UnexceptionalIO b)
-> (a -> UnexceptionalIO b) -> IO a -> UnexceptionalIO b
unexceptionalTryEither SomeException -> UnexceptionalIO b
onFailure a -> UnexceptionalIO b
onSuccess IO a
action =
forall a. IO a -> UnexceptionalIO a
UnexceptionalIO do
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join do
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch
(coerce :: forall a b. Coercible a b => a -> b
coerce @_ @(a -> IO b) a -> UnexceptionalIO b
onSuccess forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO a
action)
(forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce @_ @(SomeException -> IO b) SomeException -> UnexceptionalIO b
onFailure)