Executing actions

Never creates more or less unblocked threads than are specified to
live in the pool. NB: this count includes the thread executing parallel_.
This should minimize contention and hence pre-emption, while also preventing
starvation.

On return all actions have been performed.

The function returns in a timely manner as soon as all actions have
been performed.

The above properties are true even if parallel_ is used by an
action which is itself being executed by one of the parallel combinators.

If any of the IO actions throws an exception, undefined behaviour will result.
If you want safety, wrap your actions in Control.Exception.try.

Run the list of computations in parallel, returning the results in the
same order as the corresponding actions.

Has the following properties:

Never creates more or less unblocked threads than are specified to
live in the pool. NB: this count includes the thread executing parallel.
This should minimize contention and hence pre-emption, while also preventing
starvation.

On return all actions have been performed.

The function returns in a timely manner as soon as all actions have
been performed.

The above properties are true even if parallel is used by an
action which is itself being executed by one of the parallel combinators.

If any of the IO actions throws an exception, undefined behaviour will result.
If you want safety, wrap your actions in Control.Exception.try.

Run the list of computations in parallel, returning the results in the
approximate order of completion.

Has the following properties:

Never creates more or less unblocked threads than are specified to
live in the pool. NB: this count includes the thread executing parallelInterleaved.
This should minimize contention and hence pre-emption, while also preventing
starvation.

On return all actions have been performed.

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 parallelInterleaved is used by an
action which is itself being executed by one of the parallel combinators.

If any of the IO actions throws an exception, undefined behaviour will result.
If you want safety, wrap your actions in Control.Exception.try.

You should wrap any IO action used from your worker threads that may block with this method.
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't 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.

An example where something goes wrong if you don't use this to wrap blocking actions is the following example:

If we only have one thread, we will sometimes get a schedule where the readMVar action is run
before the putMVar. Unless we wrap the read with extraWorkerWhileBlocked, if the pool has a
single thread our program to deadlock, because the worker will become blocked and no other thread
will be available to execute the putMVar.

Advanced pool management

Internal method for adding extra unblocked threads to a pool if one of the current
worker threads is going to be temporarily blocked. Unrestricted use of this is unsafe,
so we reccomend that you use the extraWorkerWhileBlocked function instead if possible.

Internal 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 extraWorkerWhileBlocked function instead if possible.