-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | A fundamental solution to ghost threads and silent exceptions
--
-- Vanilla thread management in Haskell is low level and it does not
-- approach the problems related to thread deaths. When it's used naively
-- the following typical problems arise:
--
--
-- - When a forked thread dies due to an uncaught exception, the
-- exception does not get raised in the main thread, which is why the
-- program continues to run as if nothing happened, i.e., with the
-- presumption that the already dead thread is running normally.
-- Naturally this may very well bring your program to a chaotic
-- state.
-- - Another issue is that one thread dying does not affect any of the
-- threads forked from it. That's why your program may be accumulating
-- ghost threads.
-- - Ever dealt with your program ignoring the <Ctrl-C>
-- strikes?
--
--
-- This library solves all the issues above with a concept of a slave
-- thread. A slave thread has the following properties:
--
--
-- - When it dies for whatever reason (exception or finishing normally)
-- it kills all the slave threads that were forked from it. This protects
-- you from ghost threads.
-- - It waits for all slaves to die and execute their finalizers before
-- executing its own finalizer and getting released itself. This gives
-- you hierarchical releasing of resources.
-- - When a slave thread dies with an uncaught exception it reraises it
-- in the master thread. This protects you from silent exceptions and
-- lets you be sure of getting informed if your program gets brought to
-- an erroneous state.
--
@package slave-thread
@version 1.1.0.3
-- | Vanilla thread management in Haskell is low level and it does not
-- approach the problems related to thread deaths. When it's used naively
-- the following typical problems arise:
--
--
-- - When a forked thread dies due to an uncaught exception, the
-- exception does not get raised in the main thread, which is why the
-- program continues to run as if nothing happened, i.e., with the
-- presumption that the already dead thread is running normally.
-- Naturally this may very well bring your program to a chaotic
-- state.
-- - Another issue is that one thread dying does not affect any of the
-- threads forked from it. That's why your program may be accumulating
-- ghost threads.
-- - Ever dealt with your program ignoring the <Ctrl-C>
-- strikes?
--
--
-- This library solves all the issues above with a concept of a slave
-- thread. A slave thread has the following properties:
--
--
-- - When it dies for whatever reason (exception or finishing normally)
-- it kills all the slave threads that were forked from it. This protects
-- you from ghost threads.
-- - It waits for all slaves to die and execute their finalizers before
-- executing its own finalizer and getting released itself. This gives
-- you hierarchical releasing of resources.
-- - When a slave thread dies with an uncaught exception it reraises it
-- in the master thread. This protects you from silent exceptions and
-- lets you be sure of getting informed if your program gets brought to
-- an erroneous state.
--
module SlaveThread
-- | Fork a slave thread to run a computation on.
fork :: IO a -> IO ThreadId
-- | Like fork, but provides the computation a function that unmasks
-- asynchronous exceptions. See Note [Unmask] at the bottom of
-- this module.
forkWithUnmask :: ((forall x. IO x -> IO x) -> IO a) -> IO ThreadId
-- | Fork a slave thread with a finalizer action to run a computation on.
-- The finalizer gets executed when the thread dies for whatever reason:
-- due to being killed or an uncaught exception, or a normal termination.
--
-- Note the order of arguments:
--
--
-- forkFinally finalizer computation
--
forkFinally :: IO a -> IO b -> IO ThreadId
-- | Like forkFinally, but provides the computation a function that
-- unmasks asynchronous exceptions. See Note [Unmask] at the
-- bottom of this module.
forkFinallyWithUnmask :: IO a -> ((forall x. IO x -> IO x) -> IO b) -> IO ThreadId
-- | A slave thread crashed. This exception is classified as
-- asynchronous, meaning it extends from
-- SomeAsyncException.
--
-- In general,
--
--
-- - Synchronous exceptions such as IOException are
-- thrown by IO actions that are explicitly called by the thread that
-- receives them, and may be caught, inspected, and handled by resuming
-- execution.
-- - Asynchronous exceptions such as ThreadKilled should
-- normally only be caught temporarily in order to run finalizers, then
-- re-thrown.
--
--
-- SlaveThreadCrashed being asynchronous means it should, by
-- default, cause the entire thread hierarchy to come crashing down,
-- ultimately terminating the program.
--
-- If you want more sophisticated behavior, such as a "supervisor" thread
-- that monitors and restarts worker threads when they fail, you have to
-- program that yourself.
--
-- N.B. Consider using a library like safe-exceptions or
-- unliftio, which carefully distinguish synchronous and
-- asynchronous exceptions, unlike base.
data SlaveThreadCrashed
SlaveThreadCrashed :: !ThreadId -> !SomeException -> SlaveThreadCrashed
instance GHC.Show.Show SlaveThread.SlaveThreadCrashed
instance GHC.Exception.Type.Exception SlaveThread.SlaveThreadCrashed