úÎåâ      Safe-Inferred Safe-InferredGA thread pool, containing a maximum number of threads. The best way to ! construct one of these is using . HA slightly unsafe way to construct a pool. Make a pool from the maximum E number of threads you wish it to execute (including the main thread  in the count). >If you use this variant then ensure that you insert a call to  G somewhere in your program after all users of that pool have finished. 2A better alternative is to see if you can use the  variant. "Clean up a thread pool. If you don'>t call this from the main thread then no one holds the queue,  the queue gets GC'Md, the threads find themselves blocked indefinitely, and you get exceptions. 4This cleanly shuts down the threads so the queue isn't important and you don't get  exceptions. Only call this after; all users of the pool have completed, or your program may  block indefinitely. A safe wrapper around  and . Executes an  action using a newly-created H pool with the specified number of threads and cleans it up at the end. ]You should wrap any IO action used from your worker threads that may block with this method. X It temporarily spawns another worker thread to make up for the loss of the old blocked  worker. _This is particularly important if the unblocking is dependent on worker threads actually doing . work. If you have this situation, and you don'1t use this method to wrap blocking actions, then ` you may get a deadlock if all your worker threads get blocked on work that they assume will be  done by other worker threads. 0An example where something goes wrong if you don'>t use this to wrap blocking actions is the following example:  K newEmptyMVar >>= \mvar -> parallel_ pool [readMVar mvar, putMVar mvar ()] GIf we only have one thread, we will sometimes get a schedule where the  action is run  before the  . Unless we wrap the read with , if the pool has a c single thread our program to deadlock, because the worker will become blocked and no other thread " will be available to execute the  . The correct code is: j newEmptyMVar >>= \mvar -> parallel_ pool [extraWorkerWhileBlocked pool (readMVar mvar), putMVar mvar ()] SInternal method for adding extra unblocked threads to a pool if one of the current X worker threads is going to be temporarily blocked. Unrestricted use of this is unsafe, " so we recommend that you use the  function instead if possible. VInternal method for removing threads from a pool after one of the threads on the pool [ becomes newly unblocked. Unrestricted use of this is unsafe, so we reccomend that you use  the  function instead if possible. *Run the list of computations in parallel. Has the following properties:  D Never creates more or less unblocked threads than are specified to D live in the pool. NB: this count includes the thread executing . R This should minimize contention and hence pre-emption, while also preventing  starvation. , On return all actions have been performed. E The function returns in a timely manner as soon as all actions have  been performed. ' The above properties are true even if  is used by an O action which is itself being executed by one of the parallel combinators. O If any of the IO actions throws an exception this does not prevent any of the ) other actions from being performed. Q If any of the IO actions throws an exception, the exception thrown by the first 8 failing action in the input list will be thrown by . Importantly, at the X time the exception is thrown there is no guarantee that the other parallel actions  have completed. TThe motivation for this choice is that waiting for the all threads to either return [ or throw before throwing the first exception will almost always cause GHC to show the  &Blocked indefinitely in MVar operation5 exception rather than the exception you care about. MThe reason for this behaviour can be seen by considering this machine state:  ` The main thread has used the parallel combinators to spawn two threads, thread 1 and thread 2. p It is blocked on both of them waiting for them to return either a result or an exception via an MVar. 7 Thread 1 and thread 2 share another (empty) MVar, the  wait handle%. Thread 2 is waiting on the handle, > while thread 2 will eventually put into the handle. iConsider what happens when thread 1 is buggy and throws an exception before putting into the handle. Now q thread 2 is blocked indefinitely, and so the main thread is also blocked indefinetly waiting for the result p of thread 2. GHC has no choice but to throw the uninformative exception. However, what we really wanted to 8 see was the original exception thrown in thread 1! qBy having the main thread abandon its wait for the results of the spawned threads as soon as the first exception I comes in, we give this exception a chance to actually be displayed. As I, but instead of throwing exceptions that are thrown by subcomputations, ( they are returned in a data structure. As a result, property 6 of M is not preserved, and therefore if your IO actions can depend on each other 4 and may throw exceptions your program may die with blocked indefinitely. exceptions rather than informative messages. GRun the list of computations in parallel, returning the results in the * same order as the corresponding actions. Has the following properties:  D Never creates more or less unblocked threads than are specified to D live in the pool. NB: this count includes the thread executing  . R This should minimize contention and hence pre-emption, while also preventing  starvation. , On return all actions have been performed. E The function returns in a timely manner as soon as all actions have  been performed. ' The above properties are true even if   is used by an O action which is itself being executed by one of the parallel combinators. O If any of the IO actions throws an exception this does not prevent any of the ) other actions from being performed. Q If any of the IO actions throws an exception, the exception thrown by the first 8 failing action in the input list will be thrown by  . Importantly, at the X time the exception is thrown there is no guarantee that the other parallel actions  have completed. TThe motivation for this choice is that waiting for the all threads to either return [ or throw before throwing the first exception will almost always cause GHC to show the  &Blocked indefinitely in MVar operation5 exception rather than the exception you care about. MThe reason for this behaviour can be seen by considering this machine state:  ` The main thread has used the parallel combinators to spawn two threads, thread 1 and thread 2. p It is blocked on both of them waiting for them to return either a result or an exception via an MVar. 7 Thread 1 and thread 2 share another (empty) MVar, the  wait handle%. Thread 2 is waiting on the handle, > while thread 2 will eventually put into the handle. iConsider what happens when thread 1 is buggy and throws an exception before putting into the handle. Now q thread 2 is blocked indefinitely, and so the main thread is also blocked indefinetly waiting for the result p of thread 2. GHC has no choice but to throw the uninformative exception. However, what we really wanted to 8 see was the original exception thrown in thread 1! qBy having the main thread abandon its wait for the results of the spawned threads as soon as the first exception I comes in, we give this exception a chance to actually be displayed. As  I, but instead of throwing exceptions that are thrown by subcomputations, ( they are returned in a data structure. As a result, property 6 of  M is not preserved, and therefore if your IO actions can depend on each other 4 and may throw exceptions your program may die with blocked indefinitely. exceptions rather than informative messages. GRun the list of computations in parallel, returning the results in the " approximate order of completion. Has the following properties:  D Never creates more or less unblocked threads than are specified to D live in the pool. NB: this count includes the thread executing  . R This should minimize contention and hence pre-emption, while also preventing  starvation. , On return all actions have been performed. P The result of running actions appear in the list in undefined order, but which > is likely to be very similar to the order of completion. ' The above properties are true even if   is used by an O action which is itself being executed by one of the parallel combinators. O If any of the IO actions throws an exception this does not prevent any of the ) other actions from being performed. Q If any of the IO actions throws an exception, the exception thrown by the first 8 failing action in the input list will be thrown by  . Importantly, at the X time the exception is thrown there is no guarantee that the other parallel actions  have completed. TThe motivation for this choice is that waiting for the all threads to either return [ or throw before throwing the first exception will almost always cause GHC to show the  &Blocked indefinitely in MVar operation5 exception rather than the exception you care about. MThe reason for this behaviour can be seen by considering this machine state:  ` The main thread has used the parallel combinators to spawn two threads, thread 1 and thread 2. p It is blocked on both of them waiting for them to return either a result or an exception via an MVar. 7 Thread 1 and thread 2 share another (empty) MVar, the  wait handle%. Thread 2 is waiting on the handle, > while thread 1 will eventually put into the handle. iConsider what happens when thread 1 is buggy and throws an exception before putting into the handle. Now q thread 2 is blocked indefinitely, and so the main thread is also blocked indefinetly waiting for the result p of thread 2. GHC has no choice but to throw the uninformative exception. However, what we really wanted to 8 see was the original exception thrown in thread 1! qBy having the main thread abandon its wait for the results of the spawned threads as soon as the first exception I comes in, we give this exception a chance to actually be displayed. As  I, but instead of throwing exceptions that are thrown by subcomputations, ( they are returned in a data structure. As a result, property 6 of  M is not preserved, and therefore if your IO actions can depend on each other 4 and may throw exceptions your program may die with blocked indefinitely. exceptions rather than informative messages. LRun the list of computations in parallel, returning the result of the first - thread that completes with (Just x), if any Has the following properties:  D Never creates more or less unblocked threads than are specified to D live in the pool. NB: this count includes the thread executing  . R This should minimize contention and hence pre-emption, while also preventing  starvation. _ On return all actions have either been performed or cancelled (with ThreadKilled exceptions). ' The above properties are true even if   is used by an O action which is itself being executed by one of the parallel combinators. Q If any of the IO actions throws an exception, the exception thrown by the first 9 throwing action in the input list will be thrown by  . Importantly, at the X time the exception is thrown there is no guarantee that the other parallel actions ' have been completed or cancelled. TThe motivation for this choice is that waiting for the all threads to either return [ or throw before throwing the first exception will almost always cause GHC to show the  &Blocked indefinitely in MVar operation5 exception rather than the exception you care about. MThe reason for this behaviour can be seen by considering this machine state:  ` The main thread has used the parallel combinators to spawn two threads, thread 1 and thread 2. p It is blocked on both of them waiting for them to return either a result or an exception via an MVar. 7 Thread 1 and thread 2 share another (empty) MVar, the  wait handle%. Thread 2 is waiting on the handle, > while thread 1 will eventually put into the handle. iConsider what happens when thread 1 is buggy and throws an exception before putting into the handle. Now q thread 2 is blocked indefinitely, and so the main thread is also blocked indefinetly waiting for the result p of thread 2. GHC has no choice but to throw the uninformative exception. However, what we really wanted to 8 see was the original exception thrown in thread 1! qBy having the main thread abandon its wait for the results of the spawned threads as soon as the first exception I comes in, we give this exception a chance to actually be displayed. As  I, but instead of throwing exceptions that are thrown by subcomputations, ( they are returned in a data structure. As a result, property 4 of  M is not preserved, and therefore if your IO actions can depend on each other 4 and may throw exceptions your program may die with blocked indefinitely. exceptions rather than informative messages. !"#$%&   !"#$%& None LThe global thread pool. Contains as many threads as there are capabilities. #Users of the global pool must call 3 from the main thread at the end of their program. EIn order to reliably make use of the global parallelism combinators, I you must invoke this function after all calls to those combinators have 0 finished. A good choice might be at the end of main.  See also . RWrap any IO action used from your worker threads that may block with this method: X it temporarily spawns another worker thread to make up for the loss of the old blocked  worker.  See also . SInternal method for adding extra unblocked threads to a pool if one of the current X worker threads is going to be temporarily blocked. Unrestricted use of this is unsafe, " so we reccomend that you use the  function instead if possible.  See also . VInternal method for removing threads from a pool after one of the threads on the pool [ becomes newly unblocked. Unrestricted use of this is unsafe, so we reccomend that you use  the  function instead if possible.  See also . AExecute the given actions in parallel on the global thread pool. #Users of the global pool must call 3 from the main thread at the end of their program.  See also . bExecute the given actions in parallel on the global thread pool, reporting exceptions explicitly. #Users of the global pool must call 3 from the main thread at the end of their program.  See also . AExecute the given actions in parallel on the global thread pool, G returning the results in the same order as the corresponding actions. #Users of the global pool must call 3 from the main thread at the end of their program.  See also  . AExecute the given actions in parallel on the global thread pool, k returning the results in the same order as the corresponding actions and reporting exceptions explicitly. #Users of the global pool must call 3 from the main thread at the end of their program.  See also  . AExecute the given actions in parallel on the global thread pool, ? returning the results in the approximate order of completion. #Users of the global pool must call 3 from the main thread at the end of their program.  See also  . AExecute the given actions in parallel on the global thread pool, c returning the results in the approximate order of completion and reporting exceptions explicitly. #Users of the global pool must call 3 from the main thread at the end of their program.  See also  . LRun the list of computations in parallel, returning the result of the first . thread that completes with (Just x), if any. #Users of the global pool must call 3 from the main thread at the end of their program.  See also  . LRun the list of computations in parallel, returning the result of the first V thread that completes with (Just x), if any, and reporting any exception explicitly. #Users of the global pool must call 3 from the main thread at the end of their program.  See also .    None '         !"#$%&'(parallel-io-0.3.3#Control.Concurrent.ParallelIO.Local$Control.Concurrent.ParallelIO.Global$Control.Concurrent.ParallelIO.CompatControl.Concurrent.ParallelIOPool startPoolstopPoolwithPoolextraWorkerWhileBlockedspawnPoolWorkerForkillPoolWorkerFor parallel_ parallelE_parallel parallelEparallelInterleavedparallelInterleavedE parallelFirstparallelFirstE globalPoolstopGlobalPoolspawnPoolWorkerkillPoolWorkerbaseGHC.IOmaskmask_ghc-prim GHC.TypesIOControl.Concurrent.MVarreadMVarGHC.MVarputMVarpool_threadcountpool_semcatchNonThreadKilledonNonThreadKilledExceptionreflectExceptionsTo