Copyright | (c) Aaron Stevens, 2014 |
---|---|
License | GPL2 |
Maintainer | bheklilr2@gmail.com |
Safe Haskell | None |
Language | Haskell2010 |
- module Control.Concurrent
- module Access.Control.Concurrent.MVar
- module Access.Control.Concurrent.Chan
- module Access.Control.Concurrent.QSem
- module Access.Control.Concurrent.QSemN
- class ExceptionAccess io => ThreadAccess io where
- myThreadId' :: io ThreadId
- forkIO' :: io () -> io ThreadId
- forkFinally' :: io a -> (Either SomeException a -> io ()) -> io ThreadId
- forkIOWithUnmask' :: ((forall a. io a -> io a) -> io ()) -> io ThreadId
- killThread' :: ThreadId -> io ()
- throwTo' :: Exception e => ThreadId -> e -> io ()
- forkOn' :: Int -> io () -> io ThreadId
- forkOnWithUnmask' :: Int -> ((forall a. io a -> io a) -> io ()) -> io ThreadId
- getNumCapabilities' :: io Int
- setNumCapabilities' :: Int -> io ()
- threadCapability' :: ThreadId -> io (Int, Bool)
- yield' :: io ()
- threadDelay' :: Int -> io ()
- threadWaitRead' :: Fd -> io ()
- threadWaitWrite' :: Fd -> io ()
- threadWaitReadSTM' :: Fd -> io (STM (), io ())
- threadWaitWriteSTM' :: Fd -> io (STM (), io ())
- class ThreadAccess io => BoundThreadAccess io where
- forkOS' :: io () -> io ThreadId
- isCurrentThreadBound' :: io Bool
- runInBoundThread' :: io a -> io a
- runInUnboundThread' :: io a -> io a
- class WeakMemAccess io => WeakThreadAccess io where
- mkWeakThreadId' :: ThreadId -> io (Weak ThreadId)
Documentation
module Control.Concurrent
class ExceptionAccess io => ThreadAccess io where Source
Inherits from ExceptionAccess
, and gives access to Thread related functions
myThreadId', forkIO', forkFinally', forkIOWithUnmask', killThread', forkOn', forkOnWithUnmask', getNumCapabilities', setNumCapabilities', threadCapability', yield', threadDelay', threadWaitRead', threadWaitWrite', threadWaitReadSTM', threadWaitWriteSTM'
myThreadId' :: io ThreadId Source
Wraps myThreadId
Returns the ThreadId
of the calling thread (GHC only)
forkIO' :: io () -> io ThreadId Source
Wraps forkIO
Sparks off a new thread to run the IO
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.
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.
forkFinally' :: io a -> (Either SomeException a -> io ()) -> io ThreadId Source
Wraps forkFinally
Fork a thread and call the supplied function when the thread is about to terminate, with an exception or a returned value. The function is called with asynchronous exceptions masked.
forkFinally' action and_then = mask $ \restore -> forkIO' $ try (restore action) >>= and_then
This function is useful for informing the parent when a child terminates, for example.
forkIOWithUnmask' :: ((forall a. io a -> io a) -> io ()) -> io ThreadId Source
Wraps forkIOWithUnmask
Like forkIO'
, 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.
killThread' :: ThreadId -> io () Source
Wraps killThread
killThread'
raises the ThreadKilled
exception in the given
thread (GHC only).
killThread' tid = throwTo' tid ThreadKilled
throwTo' :: Exception e => ThreadId -> e -> io () Source
Wraps throwTo
throwTo'
raises an arbitrary exception in the target thread (GHC only).
throwTo'
does not return until the exception has been raised in the
target thread.
The calling thread can thus be certain that the target
thread has received the exception. This is a useful property to know
when dealing with race conditions: eg. if there are two threads that
can kill each other, it is guaranteed that only one of the threads
will get to kill the other.
Whatever work the target thread was doing when the exception was raised is not lost: the computation is suspended until required by another thread.
If the target thread is currently making a foreign call, then the
exception will not be raised (and hence throwTo'
will not return)
until the call has completed. This is the case regardless of whether
the call is inside a mask'
or not. However, in GHC a foreign call
can be annotated as interruptible
, in which case a throwTo'
will
cause the RTS to attempt to cause the call to return; see the GHC
documentation for more details.
Important note: the behaviour of throwTo'
differs from that described in
the paper "Asynchronous exceptions in Haskell"
(http://research.microsoft.com/~simonpj/Papers/asynch-exns.htm).
In the paper, throwTo'
is non-blocking; but the library implementation
adopts a more synchronous design in which throwTo'
does not return
until the exception is received by the target thread. The trade-off is
discussed in Section 9 of the paper. Like any blocking operation,
throwTo'
is therefore interruptible (see Section 5.3 of the paper).
Unlike other interruptible operations, however, throwTo'
is always
interruptible, even if it does not actually block.
There is no guarantee that the exception will be delivered promptly,
although the runtime will endeavour to ensure that arbitrary
delays don't occur. In GHC, an exception can only be raised when a
thread reaches a safe point, where a safe point is where memory
allocation occurs. Some loops do not perform any memory allocation
inside the loop and therefore cannot be interrupted by a throwTo'
.
If the target of throwTo'
is the calling thread, then the behaviour
is the same as throwIO'
, except that the
exception is thrown as an asynchronous exception. This means that if
there is an enclosing pure computation, which would be the case if the
current IO operation is inside unsafePerformIO
or unsafeInterleaveIO
,
that computation is not permanently replaced by the exception, but is
suspended as if it had received an asynchronous exception.
Note that if throwTo'
is called with the current thread as the
target, the exception will be thrown even if the thread is currently
inside mask'
or uninterruptibleMask'
.
forkOn' :: Int -> io () -> io ThreadId Source
Wraps forkOn
Like ''forkIO'', but lets you specify on which processor the thread
should run. Unlike a `'forkIO'` thread, a thread created by forkOn'
will stay on the same processor for its entire lifetime (`'forkIO'`
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).
forkOnWithUnmask' :: Int -> ((forall a. io a -> io a) -> io ()) -> io ThreadId Source
Wraps forkOnWithUnmask
Like forkIOWithUnmask'
, but the child thread is pinned to the
given CPU, as with forkOn'
.
getNumCapabilities' :: io Int Source
Wraps getNumCapabilities
Returns the number of Haskell threads that can run truly
simultaneously (on separate physical processors) at any given time. To
change this value, use setNumCapabilities'
.
setNumCapabilities' :: Int -> io () Source
Wraps setNumCapabilities
Set the number of Haskell threads that can run truly simultaneously
(on separate physical processors) at any given time. The number
passed to forkOn'
is interpreted modulo this value. The initial
value is given by the +RTS -N
runtime flag.
This is also the number of threads that will participate in parallel garbage collection. It is strongly recommended that the number of capabilities is not set larger than the number of physical processor cores, and it may often be beneficial to leave one or more cores free to avoid contention with other processes in the machine.
threadCapability' :: ThreadId -> io (Int, Bool) Source
Wraps threadCapability
Returns the number of the capability on which the thread is currently
running, and a boolean indicating whether the thread is locked to
that capability or not. A thread is locked to a capability if it
was created with forkOn'
.
Wraps yield
The yield'
action allows (forces, in a co-operative multitasking
implementation) a context-switch to any other currently runnable
threads (if any), and is occasionally useful when implementing
concurrency abstractions.
threadDelay' :: Int -> io () Source
Wraps threadDelay
Suspends the current thread for a given number of microseconds (GHC only).
There is no guarantee that the thread will be rescheduled promptly when the delay has expired, but the thread will never continue to run earlier than specified.
threadWaitRead' :: Fd -> io () Source
Wraps threadWaitRead
Block the current thread until data is available to read on the given file descriptor (GHC only).
This will throw an IOError
if the file descriptor was closed
while this thread was blocked. To safely close a file descriptor
that has been used with threadWaitRead
, use
closeFdWith
.
threadWaitWrite' :: Fd -> io () Source
Wraps threadWaitWrite
Block the current thread until data can be written to the given file descriptor (GHC only).
This will throw an IOError
if the file descriptor was closed
while this thread was blocked. To safely close a file descriptor
that has been used with threadWaitWrite
, use
closeFdWith
.
threadWaitReadSTM' :: Fd -> io (STM (), io ()) Source
Returns an STM action that can be used to wait for data to read from a file descriptor. The second returned value is an IO action that can be used to deregister interest in the file descriptor.
Since: 4.7.0.0
threadWaitWriteSTM' :: Fd -> io (STM (), io ()) Source
Returns an STM action that can be used to wait until data can be written to a file descriptor. The second returned value is an IO action that can be used to deregister interest in the file descriptor.
Since: 4.7.0.0
class ThreadAccess io => BoundThreadAccess io where Source
Provides access to bounded thread functions
forkOS' :: io () -> io ThreadId Source
Wraps forkOS
Like forkIO'
, this sparks off a new thread to run the IO
computation passed as the first argument, and returns the ThreadId
of the newly created thread.
However, forkOS'
creates a bound thread, which is necessary if you
need to call foreign (non-Haskell) libraries that make use of
thread-local state, such as OpenGL (see Control.Concurrent).
Using forkOS'
instead of forkIO'
makes no difference at all to the
scheduling behaviour of the Haskell runtime system. It is a common
misconception that you need to use forkOS'
instead of forkIO'
to
avoid blocking all the Haskell threads when making a foreign call;
this isn't the case. To allow foreign calls to be made without
blocking all the Haskell threads (with GHC), it is only necessary to
use the -threaded
option when linking your program, and to make sure
the foreign import is not marked unsafe
.
isCurrentThreadBound' :: io Bool Source
Wraps isCurrentThreadBound
Returns True
if the calling thread is bound, that is, if it is
safe to use foreign libraries that rely on thread-local state from the
calling thread.
runInBoundThread' :: io a -> io a Source
Wraps runInBoundThread
Run the IO
computation passed as the first argument. If the calling
thread is not bound, a bound thread is created temporarily.
runInBoundThread'
doesn't finish until the IO
computation finishes.
You can wrap a series of foreign function calls that rely on thread-local
state with runInBoundThread'
so that you can use them without knowing
whether the current thread is bound.
runInUnboundThread' :: io a -> io a Source
Wraps runInUnboundThread
Run the IO
computation passed as the first argument. If the calling
thread is bound, an unbound thread is created temporarily using
forkIO'
. runInBoundThread'
doesn't finish until the IO
computation
finishes.
Use this function only in the rare case that you have actually observed
a performance loss due to the use of bound threads. A program that
doesn't need it's main thread to be bound and makes heavy use of
concurrency (e.g. a web server), might want to wrap it's main
action in
runInUnboundThread'
.
Note that exceptions which are thrown to the current thread are thrown in turn to the thread that is executing the given computation. This ensures there's always a way of killing the forked thread.
class WeakMemAccess io => WeakThreadAccess io where Source
Provides access to the mkWeakThreadId
function, inherits from WeakMemAccess
mkWeakThreadId' :: ThreadId -> io (Weak ThreadId) Source
Wraps mkWeakThreadId
Make a weak pointer to a ThreadId
. It can be important to do
this if you want to hold a reference to a ThreadId
while still
allowing the thread to receive the BlockedIndefinitely
family of
exceptions (e.g. BlockedIndefinitelyOnMVar
). Holding a normal
ThreadId
reference will prevent the delivery of
BlockedIndefinitely
exceptions because the reference could be
used as the target of throwTo'
at any time, which would unblock
the thread.
Holding a Weak ThreadId
, on the other hand, will not prevent the
thread from receiving BlockedIndefinitely
exceptions. It is
still possible to throw an exception to a Weak ThreadId
, but the
caller must use deRefWeak'
first to determine whether the thread
still exists.