layers-0.1: Modular type class machinery for monad transformer stacks.

Safe HaskellNone



This module exports:

  1. The MonadFork type class and its operations fork and forkOn.
  2. An instance of MonadFork for the IO monad.
  3. A universal pass-through instance of MonadFork for any existing MonadFork wrapped by a MonadLayerControl.
  4. The utility operations forkWithUnmask and forkOnWithUnmask.



class MonadMask m => MonadFork m whereSource

The MonadFork type class, for monads which support a fork operation.

An example of a monad which has a MonadFork instance that is not simply a lifted form of forkIO is the ResourceT monad from the resourcet package, which defines an operation resourceForkIO.


fork :: m () -> m ThreadIdSource

Sparks off a new thread to run the computation passed as the first argument, and returns the ThreadId of the newly created thread.

The new thread will be a lightweight thread; if you want to use a foreign library that uses thread-local storage, use forkOS instead. (Note that forkOS is not included in the MonadFork interface, so your monad m must be an instance of LiftControl 'IO m to be able to use forkOS.

GHC note: the new thread inherits the masked state of the parent (see mask).

The newly created thread has an exception handler that discards the exceptions BlockedIndefinitelyOnMVar, BlockedIndefinitelyOnSTM, and ThreadKilled, and passes all other exceptions to the uncaught exception handler.

forkOn :: Int -> m () -> m ThreadIdSource

Like fork, but lets you specify on which processor the thread should run. Unlike a fork thread, a thread created by forkOn will stay on the same processor for its entire lifetime (fork threads can migrate between processors according to the scheduling policy). forkOn is useful for overriding the scheduling policy when you know in advance how best to distribute the threads.

The Int argument specifies a capability number (see getNumCapabilities). Typically capabilities correspond to physical processors, but the exact behaviour is implementation-dependent. The value passed to forkOn is interpreted modulo the total number of capabilities as returned by getNumCapabilities.

GHC note: the number of capabilities is specified by the +RTS -N option when the program is started. Capabilities can be fixed to actual processor cores with +RTS -qa if the underlying operating system supports that, although in practice this is usually unnecessary (and may actually degrade perforamnce in some cases - experimentation is recommended).

forkWithUnmask :: MonadFork m => ((forall a n. MonadMask n => n a -> n a) -> m ()) -> m ThreadIdSource

Like fork, but the child thread is passed a function that can be used to unmask asynchronous exceptions. This function is typically used in the following way

  ... mask_ $ forkIOWithUnmask $ \unmask ->
                 catch (unmask ...) handler

so that the exception handler in the child thread is established with asynchronous exceptions masked, meanwhile the main body of the child thread is executed in the unmasked state.

Note that the unmask function passed to the child thread should only be used in that thread; the behaviour is undefined if it is invoked in a different thread.

forkOnWithUnmask :: MonadFork m => Int -> ((forall a n. MonadMask n => n a -> n a) -> m ()) -> m ThreadIdSource

Like forkWithUnmask, but the child thread is pinned to the given CPU, as with forkOn.