----------------------------------------------------------------------------- -- | -- Module : Control.Concurrent.Async.Pool -- Copyright : (c) Simon Marlow 2012, John Wiegley 2014 -- License : BSD3 (see the file LICENSE) -- -- Maintainer : John Wiegley -- Stability : provisional -- Portability : non-portable (requires concurrency) -- -- This module provides a set of operations for running IO operations -- asynchronously and waiting for their results. It is a thin layer over the -- basic concurrency operations provided by "Control.Concurrent". The main -- additional functionality it provides is the ability to wait for the return -- value of a thread, plus functions for managing task pools, work groups, and -- many-to-many dependencies between tasks. The interface also provides some -- additional safety and robustness over using threads and @MVar@ directly. -- -- The basic type is @'Async' a@, which represents an asynchronous @IO@ action -- that will return a value of type @a@, or die with an exception. An @Async@ -- corresponds to either a thread, or a @Handle@ to an action waiting to be -- spawned. This makes it possible to submit very large numbers of tasks, -- with only N threads active at one time. -- -- For example, to fetch two web pages at the same time, we could do -- this (assuming a suitable @getURL@ function): -- -- > withTaskGroup 4 $ \g -> do -- > a1 <- async g (getURL url1) -- > a2 <- async g (getURL url2) -- > page1 <- wait a1 -- > page2 <- wait a2 -- > ... -- -- where 'async' submits the operation to the worker group (and from which it -- is spawned in a separate thread), and 'wait' waits for and returns the -- result. The number 4 indicates the maximum number of threads which may be -- spawned at one time. If the operation throws an exception, then that -- exception is re-thrown by 'wait'. This is one of the ways in which this -- library provides some additional safety: it is harder to accidentally -- forget about exceptions thrown in child threads. -- -- A slight improvement over the previous example is this: -- -- > withTaskGroup 4 $ \g -> do -- > withAsync g (getURL url1) $ \a1 -> do -- > withAsync g (getURL url2) $ \a2 -> do -- > page1 <- wait a1 -- > page2 <- wait a2 -- > ... -- -- 'withAsync' is like 'async', except that the 'Async' is automatically -- killed (or unscheduled, using 'cancel') if the enclosing IO operation -- returns before it has completed. Consider the case when the first 'wait' -- throws an exception; then the second 'Async' will be automatically killed -- rather than being left to run in the background, possibly indefinitely. -- This is the second way that the library provides additional safety: using -- 'withAsync' means we can avoid accidentally leaving threads running. -- Furthermore, 'withAsync' allows a tree of threads to be built, such that -- children are automatically killed if their parents die for any reason. -- -- The pattern of performing two IO actions concurrently and waiting for their -- results is packaged up in a combinator 'concurrently', so we can further -- shorten the above example to: -- -- > withTaskGroup 4 $ \g -> do -- > (page1, page2) <- concurrently g (getURL url1) (getURL url2) -- > ... -- -- The 'Functor' instance can be used to change the result of an 'Async'. For -- example: -- -- > ghci> a <- async g (return 3) -- > ghci> wait a -- > 3 -- > ghci> wait (fmap (+1) a) -- > 4 module Control.Concurrent.Async.Pool ( -- * Asynchronous actions Async, -- * Task pools and groups withTaskGroup, withTaskGroupIn, Pool, createPool, TaskGroup, createTaskGroup, runTaskGroup, -- ** Spawning tasks async, asyncBound, asyncOn, asyncWithUnmask, asyncOnWithUnmask, asyncSTM, -- ** Dependent tasks taskHandle, asyncAfter, asyncAfterAll, makeDependent, unsafeMakeDependent, -- ** Spawning with automatic 'cancel'ation withAsync, withAsyncBound, withAsyncOn, withAsyncWithUnmask, withAsyncOnWithUnmask, -- ** Quering 'Async's wait, poll, waitCatch, cancel, cancelWith, -- ** STM operations waitSTM, pollSTM, waitCatchSTM, -- ** Waiting for multiple 'Async's waitAny, waitAnyCatch, waitAnyCancel, waitAnyCatchCancel, waitEither, waitEitherCatch, waitEitherCancel, waitEitherCatchCancel, waitEither_, waitBoth, -- ** Linking link, link2, -- ** Lists of actions mapTasks, mapTasks_, mapTasksE, mapTasksE_, mapRace, mapReduce, scatterFoldMapM, -- ** The Task Monad and Applicative Task, runTask, task, -- * Other utilities race, race_, concurrently, mapConcurrently, Concurrently(..) ) where import Control.Concurrent.Async.Pool.Async import Control.Concurrent.Async.Pool.Internal