------------------------------------------------------------------------------- |-- Module : Control.Concurrent.Async-- Copyright : (c) Simon Marlow 2012-- License : BSD3 (see the file LICENSE)---- Maintainer : Simon Marlow <marlowsd@gmail.com>-- 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,-- but the interface also provides some additional safety and-- robustness over using 'forkIO' threads and @MVar@ directly.---- == High-level API---- @async@'s high-level API spawns /lexically scoped/ threads,-- ensuring the following key poperties that make it safer to use-- than using plain 'forkIO':---- 1. No exception is swallowed (waiting for results propagates exceptions).-- 2. No thread is leaked (left running unintentionally).---- (This is done using the 'Control.Exception.bracket' pattern to work in presence-- of synchronous and asynchronous exceptions.)---- __Most practical/production code should only use the high-level API__.---- 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' is a wrapper around a low-level 'forkIO' thread.---- The fundamental function to spawn threads with the high-level API is-- 'withAsync'.---- For example, to fetch two web pages at the same time, we could do-- this (assuming a suitable @getURL@ function):---- > withAsync (getURL url1) $ \a1 -> do-- > withAsync (getURL url2) $ \a2 -> do-- > page1 <- wait a1-- > page2 <- wait a2-- > ...---- where 'withAsync' starts the operation in a separate thread, and-- 'wait' waits for and returns the result.---- * If the operation throws an exception, then that exception is re-thrown-- by 'wait'. This ensures property (1): No exception is swallowed.-- * If an exception bubbles up through a 'withAsync', then the 'Async'-- it spawned is 'cancel'ed. This ensures property (2): No thread is leaked.---- Often we do not care to work manually with 'Async' handles like-- @a1@ and @a2@. Instead, we want to express high-level objectives like-- performing two or more tasks concurrently, and waiting for one or all-- of them to finish.---- For example, the pattern of performing two IO actions concurrently and-- waiting for both their results is packaged up in a combinator 'concurrently',-- so we can further shorten the above example to:---- > (page1, page2) <- concurrently (getURL url1) (getURL url2)-- > ...---- The section __/High-level utilities/__ covers the most-- common high-level objectives, including:---- * Waiting for 2 results ('concurrently').-- * Waiting for many results ('mapConcurrently' / 'forConcurrently').-- * Waiting for the first of 2 results ('race').-- * Waiting for arbitrary nestings of "all of /N/" and "the first of /N/"-- results with the 'Concurrently' newtype and its 'Applicative' and-- 'Alternative' instances.---- Click here to scroll to that section:-- "Control.Concurrent.Async#high-level-utilities".---- == Low-level API---- Some use cases require parallelism that is not lexically scoped.---- For those, the low-level function 'async' can be used as a direct-- equivalent of 'forkIO':---- > -- Do NOT use this code in production, it has a flaw (explained below).-- > do-- > a1 <- async (getURL url1)-- > a2 <- async (getURL url2)-- > page1 <- wait a1-- > page2 <- wait a2-- > ...---- In contrast to 'withAsync', this code has a problem.---- It still fulfills property (1) in that an exception arising from-- @getUrl@ will be re-thrown by 'wait', but it does not fulfill-- property (2).-- Consider the case when the first 'wait' throws an exception; then the-- second 'wait' will not happen, and the second 'async' may be left-- running in the background, possibly indefinitely.---- 'withAsync' is like 'async', except that the 'Async' is-- automatically killed (using 'uninterruptibleCancel') if the-- enclosing IO operation returns before it has completed.-- Furthermore, 'withAsync' allows a tree of threads to be built, such-- that children are automatically killed if their parents die for any-- reason.---- If you need to use the low-level API, ensure that you guarantee-- property (2) by other means, such as 'link'ing asyncs that need-- to die together, and protecting against asynchronous exceptions-- using 'Control.Exception.bracket', 'Control.Exception.mask',-- or other functions from "Control.Exception".---- == Miscellaneous---- The 'Functor' instance can be used to change the result of an-- 'Async'. For example:---- > ghci> withAsync (return 3) (\a -> wait (fmap (+1) a))-- > 4---- === Resource exhaustion---- As with all concurrent programming, keep in mind that while-- Haskell's cooperative ("green") multithreading carries low overhead,-- spawning too many of them at the same time may lead to resource exhaustion-- (of memory, file descriptors, or other limited resources), given that the-- actions running in the threads consume these resources.-----------------------------------------------------------------------------moduleControl.Concurrent.Async(-- * Asynchronous actionsAsync ,-- * High-level API-- ** Spawning with automatic 'cancel'ationwithAsync ,withAsyncBound ,withAsyncOn ,withAsyncWithUnmask ,withAsyncOnWithUnmask ,-- ** Querying 'Async'swait ,poll ,waitCatch ,asyncThreadId ,cancel ,cancelMany ,uninterruptibleCancel ,cancelWith ,AsyncCancelled (..),-- ** #high-level-utilities# High-level utilitiesrace ,race_ ,concurrently ,concurrently_ ,mapConcurrently ,forConcurrently ,mapConcurrently_ ,forConcurrently_ ,replicateConcurrently ,replicateConcurrently_ ,Concurrently (..),concurrentlyE ,ConcurrentlyE (..),compareAsyncs ,-- ** Specialised operations-- *** STM operationswaitSTM ,pollSTM ,waitCatchSTM ,-- *** Waiting for multiple 'Async'swaitAny ,waitAnyCatch ,waitAnyCancel ,waitAnyCatchCancel ,waitEither ,waitEitherCatch ,waitEitherCancel ,waitEitherCatchCancel ,waitEither_ ,waitBoth ,-- *** Waiting for multiple 'Async's in STMwaitAnySTM ,waitAnyCatchSTM ,waitEitherSTM ,waitEitherCatchSTM ,waitEitherSTM_ ,waitBothSTM ,-- * Low-level API-- ** Spawning (low-level API)async ,asyncBound ,asyncOn ,asyncWithUnmask ,asyncOnWithUnmask ,-- ** Linkinglink ,linkOnly ,link2 ,link2Only ,ExceptionInLinkedThread (..),)whereimportControl.Concurrent.Async.Internal