-
Jens Nolte authored
Co-authored-by:
Jan Beinke <git@janbeinke.com>
Jens Nolte authoredCo-authored-by:
Jan Beinke <git@janbeinke.com>
Async.hs 3.09 KiB
module Quasar.Async (
-- * Async
async,
async_,
asyncWithUnmask,
asyncWithUnmask_,
-- ** Async with explicit error handling
asyncWithHandler,
asyncWithHandler_,
asyncWithHandlerAndUnmask,
asyncWithHandlerAndUnmask_,
-- ** Async exceptions
CancelAsync(..),
AsyncDisposed(..),
AsyncException(..),
) where
import Control.Monad.Catch
import Control.Monad.Reader
import Quasar.Async.Unmanaged
import Quasar.Awaitable
import Quasar.Prelude
import Quasar.ResourceManager
-- | TODO: Documentation
--
-- The action will be run with asynchronous exceptions unmasked.
async :: MonadResourceManager m => (ResourceManagerIO a) -> m (Awaitable a)
async action = asyncWithUnmask \unmask -> unmask action
-- | TODO: Documentation
--
-- The action will be run with asynchronous exceptions masked and will be passed an action that can be used to unmask.
asyncWithUnmask :: MonadResourceManager m => ((ResourceManagerIO a -> ResourceManagerIO a) -> ResourceManagerIO r) -> m (Awaitable r)
asyncWithUnmask action = do
resourceManager <- askResourceManager
asyncWithHandlerAndUnmask (throwToResourceManager resourceManager . AsyncException) action
async_ :: MonadResourceManager m => (ResourceManagerIO ()) -> m ()
async_ action = void $ async action
asyncWithUnmask_ :: MonadResourceManager m => ((ResourceManagerIO a -> ResourceManagerIO a) -> ResourceManagerIO ()) -> m ()
asyncWithUnmask_ action = void $ asyncWithUnmask action
-- | TODO: Documentation
--
-- The action will be run with asynchronous exceptions unmasked. When an exception is thrown that is not caused from
-- the disposable instance (i.e. the task being canceled), the handler is called with that exception.
asyncWithHandlerAndUnmask :: MonadResourceManager m => (SomeException -> IO ()) -> ((ResourceManagerIO a -> ResourceManagerIO a) -> ResourceManagerIO r) -> m (Awaitable r)
asyncWithHandlerAndUnmask handler action = do
resourceManager <- askResourceManager
toAwaitable <$> registerNewResource do
unmanagedAsyncWithHandlerAndUnmask wrappedHandler \unmask ->
onResourceManager resourceManager (action (liftUnmask unmask))
where
wrappedHandler :: SomeException -> IO ()
wrappedHandler (fromException -> Just AsyncDisposed) = pure ()
wrappedHandler ex = handler ex
liftUnmask :: (forall b. IO b -> IO b) -> ResourceManagerIO a -> ResourceManagerIO a
liftUnmask unmask innerAction = do
resourceManager <- askResourceManager
liftIO $ unmask $ onResourceManager resourceManager innerAction
asyncWithHandlerAndUnmask_ :: MonadResourceManager m => (SomeException -> IO ()) -> ((ResourceManagerIO a -> ResourceManagerIO a) -> ResourceManagerIO r) -> m ()
asyncWithHandlerAndUnmask_ handler action = void $ asyncWithHandlerAndUnmask handler action
asyncWithHandler :: MonadResourceManager m => (SomeException -> IO ()) -> ResourceManagerIO r -> m (Awaitable r)
asyncWithHandler handler action = asyncWithHandlerAndUnmask handler \unmask -> unmask action
asyncWithHandler_ :: MonadResourceManager m => (SomeException -> IO ()) -> ResourceManagerIO r -> m ()
asyncWithHandler_ handler action = void $ asyncWithHandler handler action