-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Simple Haskel thread management in hierarchical manner
--   
--   This package provides parent-child association and guaranteed clean-up
--   of children over plain Haskell thread. You can terminate all child
--   threads and grand child threads by just killing their parent thread.
--   asynchronous exception.
@package thread-hierarchy
@version 0.3.0.0


-- | Internal implementations of Control.Concurrent.Hierarchy
module Control.Concurrent.HierarchyInternal

-- | FinishMarker is created as empty MVar when a thread is created. It is
--   automatically filled by () when the thread exits.
newtype FinishMarker
FinishMarker :: (MVar ()) -> FinishMarker

-- | Mutable map containing thread ID and finish marker.
newtype ThreadMap
ThreadMap :: (TVar (Map ThreadId FinishMarker)) -> ThreadMap

-- | Create a new empty <a>ThreadMap</a>.
newThreadMap :: IO ThreadMap

-- | Create a new thread and register it to given <a>ThreadMap</a>.
newChild :: ThreadMap -> (ThreadMap -> IO ()) -> IO ThreadId

-- | Kill all thread registered in given <a>ThreadMap</a>. This version is
--   exposed as API. This is not called from cleanup routine. Thus it
--   doesn't ignore asynchronous exceptions.
killThreadHierarchy :: ThreadMap -> IO ()

-- | Kill all thread registered in given <a>ThreadMap</a>. This internal
--   version is only called from cleanup routine so this ignores
--   ThreadKilled asynchronous exception.
killThreadHierarchyInternal :: ThreadMap -> IO ()

-- | Thread clean up routine automatically installed by newChild. It first
--   killThreadHierarchy all its child threads and unregister itself. This
--   function is not an API function but for internal use only.
cleanup :: FinishMarker -> ThreadMap -> ThreadMap -> IO ()
instance GHC.Classes.Eq Control.Concurrent.HierarchyInternal.FinishMarker


-- | Managing Haskell threads in hierarchical manner.
--   
--   Threads created by newChild guarantee automatic cleanup on its exit
--   regardless normal exit or cancellation by asynchronous exception.
--   
--   In order to this module works properly, user must ensure following
--   rules.
--   
--   <ul>
--   <li>User provided thread handler must accept <a>ThreadMap</a> as its
--   first argument.</li>
--   <li>When new thread created by newChild, handler receives newly
--   created empty <a>ThreadMap</a>.</li>
--   <li>When the user provided handler creates its child thread, it must
--   use newChild.</li>
--   <li>At the same time, the handler must pass the <a>ThreadMap</a>
--   received via its argument to newChild.</li>
--   </ul>
--   
--   <a>ThreadMap</a> is mutable map holding live threads. Each threads
--   managed by this module has its own <a>ThreadMap</a> instance. Each
--   <a>ThreadMap</a> keeps live "child" threads for future cleanup on
--   exit. Populating <a>ThreadMap</a> is done by newChild automatically.
--   Actually the function newChild accept a <a>ThreadMap</a> then mutate
--   it.
--   
--   At the same time newChild create a new empty <a>ThreadMap</a> for
--   newly created thread and pass it to user provided handler of the new
--   thread. Also newChild automatically install cleanup routine which kill
--   all threads living in the new <a>ThreadMap</a> created for the thread.
--   The cleanup routine also unregister itself from <a>ThreadMap</a> of
--   parent.
--   
--   In order to work this properly, user provided thread handler must use
--   newChild with <a>ThreadMap</a> given via its argument when it creates
--   its child so that cleanup routine can terminate its children properly.
--   
--   <h3>Example</h3>
--   
--   When you create the first thread managed by this module, create a new
--   empty <a>ThreadMap</a> then call newChild with it. The newCall
--   automatically install cleanup routine to the handler you provided.
--   
--   <pre>
--   createRootThread :: IO ThreadId
--   createRootThread = do
--       rootThreadMap &lt;- newThreadMap
--       threadID &lt;- newChild rootThreadMap rootThreadHandler
--       return threadID
--   </pre>
--   
--   When a thread managed by this module creates its child thread, call
--   newChild with <tt>TreadMap</tt> received via handlers argument.
--   
--   <pre>
--   rootThreadHandler :: ThreadMap -&gt; IO ()
--   rootThreadHandler myChildrenThreadMap = do
--       void $ newChild myChildrenThreadMap $ grandChildrenThreadMap -&gt; do
--           yourCode
--           return ()
--   </pre>
--   
--   You can install your own cleanup routine using finally or both
--   resource acquisition and cleanup routine using bracket.
--   
--   <pre>
--   -- Forking a new child with your own cleanup
--   void $ newChild childrenOfCurrentThread $ childrenOfHandler -&gt;
--       yourThreadHandler `finally` yourCleanupRoutine
--   
--   -- Forking a new child with resource acquisition and cleanup
--   void $ newChild childrenOfCurrentThread $ childrenOfHandler -&gt;
--       bracket yourResourceAcquiringRoutine yourCleanupRoutine yourThreadHandler
--   </pre>
--   
--   <h3>Limitation</h3>
--   
--   Currently, unlike async function, this module is not designed to back
--   any return value from child thread to parent thread. This module
--   focuses on guaranteed cleanup on thread termination.
module Control.Concurrent.Hierarchy

-- | FinishMarker is created as empty MVar when a thread is created. It is
--   automatically filled by () when the thread exits.
data FinishMarker

-- | Mutable map containing thread ID and finish marker.
data ThreadMap

-- | Create a new empty <a>ThreadMap</a>.
newThreadMap :: IO ThreadMap

-- | Create a new thread and register it to given <a>ThreadMap</a>.
newChild :: ThreadMap -> (ThreadMap -> IO ()) -> IO ThreadId

-- | Kill all thread registered in given <a>ThreadMap</a>. This version is
--   exposed as API. This is not called from cleanup routine. Thus it
--   doesn't ignore asynchronous exceptions.
killThreadHierarchy :: ThreadMap -> IO ()
