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


-- | Run jobs on a limited number of threads and support data dependencies
--   
--   The motivation for this package was to run computations on multiple
--   cores that need to write intermediate results to disk. The functions
--   restrict the number of simultaneously running jobs to a user given
--   number or to the number of capabilities the Haskell program was
--   started with, i.e. the number after the RTS option <tt>-N</tt>.
--   
--   There are some flavors of this functionality:
--   
--   <ul>
--   <li><a>Control.Concurrent.PooledIO.Independent</a>: run independent
--   actions without results in parallel</li>
--   <li><a>Control.Concurrent.PooledIO.Final</a>: run independent actions
--   with a final result in parallel</li>
--   <li><a>Control.Concurrent.PooledIO.InOrder</a>: run jobs in parallel
--   with data dependencies like <tt>make -j n</tt></li>
--   </ul>
--   
--   Additionally there is the module
--   <a>Control.Concurrent.PooledIO.Sequence</a> that helps to serialize
--   I/O actions from multiple threads. It is certainly most useful in
--   connection with <a>Control.Concurrent.PooledIO.Independent</a>.
--   
--   Related packages:
--   
--   <ul>
--   <li><tt>lazyio</tt>: interleave IO actions in a single thread</li>
--   <li><tt>async</tt>: start threads and wait for their results, forward
--   exceptions, but do not throttle concurrency with respect to number of
--   available cores</li>
--   <li><tt>parallel-tasks</tt>:</li>
--   <li><tt>parallel-io</tt>:</li>
--   <li><tt>threadPool</tt>:</li>
--   <li><tt>threads-pool</tt>:</li>
--   <li><tt>cio</tt>:</li>
--   <li><tt>Control-Engine</tt>:</li>
--   <li><tt>taskpool</tt>, <tt>async-pool</tt>:</li>
--   </ul>
@package pooled-io
@version 0.0.2.2

module Control.Concurrent.PooledIO.Independent

-- | Execute all actions parallelly but run at most
--   <tt>numCapabilities</tt> threads at once. Stop when all actions are
--   finished. If a thread throws an exception this terminates only the
--   throwing thread.
run :: [IO ()] -> IO ()
runLimited :: Int -> [IO ()] -> IO ()

-- | Execute all actions parallelly without a bound an the number of
--   threads. Stop when all actions are finished.
runUnlimited :: [IO ()] -> IO ()

-- | If a thread ends with an exception, then terminate all threads and
--   forward that exception. <tt>runException Nothing</tt> chooses to use
--   all capabilities, whereas <tt>runException (Just n)</tt> chooses
--   <tt>n</tt> capabilities.
runException :: Maybe Int -> [IO ()] -> IO ()

module Control.Concurrent.PooledIO.InOrder
data T a

-- | <a>runLimited</a> with a maximum of <tt>numCapabilites</tt> threads.
run :: T a -> IO a

-- | <tt>runLimited n</tt> runs several actions in a pool with at most
--   <tt>n</tt> threads.
runLimited :: Int -> T a -> IO a

-- | <a>fork</a> runs an IO action in parallel while respecting a maximum
--   number of threads. Evaluating the result of <a>T</a> waits for the
--   termination of the according thread.
--   
--   Unfortunately, this means that sometimes threads are bored:
--   
--   <pre>
--   foo a b = do
--      c &lt;- fork $ f a
--      d &lt;- fork $ g c
--      e &lt;- fork $ h b
--   </pre>
--   
--   Here the execution of <tt>g c</tt> reserves a thread but starts with
--   waiting for the evaluation of <tt>c</tt>. It would be certainly better
--   to execute <tt>h b</tt> first. You may relax this problem by moving
--   dependent actions away from another as much as possible. It would be
--   optimal to have an <tt>OutOfOrder</tt> monad, but this is more
--   difficult to implement.
--   
--   Although we fork all actions in order, the fork itself might re-order
--   the actions. Thus the actions must not rely on a particular order
--   other than the order imposed by data dependencies. We enforce with the
--   <a>NFData</a> constraint that the computation is actually completed
--   when the thread terminates.
--   
--   Currently the monad does not handle exceptions. It's certainly best to
--   use a package with explicit exception handling like
--   <tt>explicit-exception</tt> in order to tunnel exception information
--   from the forked action to the main thread.
--   
--   Although <a>fork</a> has almost the same type signature as
--   <a>liftIO</a> we do not define <tt>instance MonadIO InOrder.T</tt>
--   since this definition would not satisfy the laws required by the
--   <tt>MonadIO</tt> class.
fork :: NFData a => IO a -> T a
instance GHC.Base.Functor Control.Concurrent.PooledIO.InOrder.T
instance GHC.Base.Applicative Control.Concurrent.PooledIO.InOrder.T
instance GHC.Base.Monad Control.Concurrent.PooledIO.InOrder.T


-- | This module implements something similar to
--   <a>Control.Concurrent.PooledIO.InOrder</a>, but since it is restricted
--   to an <a>Applicative</a> interface we can implement it without
--   <tt>unsafeInterleaveIO</tt>.
module Control.Concurrent.PooledIO.Final
data T a

-- | <a>runLimited</a> with a maximum of <tt>numCapabilites</tt> threads.
run :: T a -> IO a

-- | <tt>runLimited n</tt> runs several actions in a pool with at most
--   <tt>n</tt> threads.
runLimited :: Int -> T a -> IO a

-- | This runs an action parallelly to the starting thread. Since it is an
--   Applicative Functor and not a Monad, there are no data dependencies
--   between the actions and thus all actions in a <a>T</a> can be run
--   parallelly. Only the <a>IO</a> actions are parallelised but not the
--   combining function passed to <tt>liftA2</tt> et.al. That is, the main
--   work must be done in the <a>IO</a> actions in order to benefit from
--   parallelisation.
fork :: NFData a => IO a -> T a
instance GHC.Base.Functor Control.Concurrent.PooledIO.Final.T
instance GHC.Base.Applicative Control.Concurrent.PooledIO.Final.T


-- | Functions for sequencing actions requested from concurrent threads.
--   
--   Here is an example usage:
--   
--   <pre>
--   import qualified Control.Concurrent.PooledIO.Independent as Parallel
--   import qualified Control.Concurrent.PooledIO.Sequence as Sequence
--   
--   thread :: Sequence.In -&gt; FilePath -&gt; IO ()
--   thread seqIn name = do
--      txt &lt;- Sequence.sync seqIn $ readFile (name ++ ".in")
--      -- evaluate result with ($!!) before sending it to the sequencing thread
--      Sequence.async seqIn . writeFile (name ++ ".out") $!! processMyText txt
--      doFurtherStuff
--      -- block main program until completion
--      Sequence.sync seqIn $ return ()
--   
--   main :: IO ()
--   main = do
--      (seqIn, seqOut) &lt;- Sequence.new
--      void $ forkIO $ Sequence.run seqOut
--      Parallel.run $ map (thread seqIn) ["a", "b", "c"]
--   </pre>
module Control.Concurrent.PooledIO.Sequence
data In
data Out
new :: IO (In, Out)

-- | Run the sequencing thread. You will usually fork it.
run :: Out -> IO ()

-- | This is primarily intended for output functions. You should make sure
--   that the emitted data is evaluated before calling <a>async</a>.
--   Otherwise the sequencing thread will evaluate it and thus not much
--   parallelization will happen.
--   
--   Example:
--   
--   <pre>
--   async seqIn . writeFile "foobar.txt" $!! show result
--   </pre>
async :: In -> IO () -> IO ()

-- | This is primarily intended for input functions. You should also call
--   it at the end of a thread in order to make sure that all your
--   asynchronous actions are completed. It will actually also wait for the
--   actions that were requested by other threads. However, I think this
--   should not hurt since after completion of the current thread another
--   one will be started and it will certainly begin with an input action,
--   which has to be queued anyway.
sync :: In -> IO a -> IO a
