Maintainer | Bas van Dijk <v.dijk.bas@gmail.com> , Roel van Dijk <vandijk.roel@gmail.com> |
---|
Standard threads extended with the ability to wait for their termination.
Inspired by: http://hackage.haskell.org/package/threadmanager
This module re-implements several functions from Control.Concurrent
. Avoid
ambiguities by importing one or both qualified. We suggest importing this
module like:
import qualified Control.Concurrent.Thread as Thread ( ... )
- data ThreadId α
- threadId :: ThreadId α -> ThreadId
- forkIO :: IO α -> IO (ThreadId α)
- forkOS :: IO α -> IO (ThreadId α)
- wait :: ThreadId α -> IO (Either SomeException α)
- wait_ :: ThreadId α -> IO ()
- unsafeWait :: ThreadId α -> IO α
- unsafeWait_ :: ThreadId α -> IO ()
- waitTimeout :: ThreadId α -> Integer -> IO (Maybe (Either SomeException α))
- waitTimeout_ :: ThreadId α -> Integer -> IO Bool
- unsafeWaitTimeout :: ThreadId α -> Integer -> IO (Maybe α)
- unsafeWaitTimeout_ :: ThreadId α -> Integer -> IO Bool
- isRunning :: ThreadId α -> IO Bool
- throwTo :: Exception e => ThreadId α -> e -> IO ()
- killThread :: ThreadId α -> IO ()
- killThreadTimeout :: ThreadId α -> Integer -> IO Bool
Documentation
A
is an abstract type representing a handle to a thread
that is executing or has executed a computation of type ThreadId
α
.
IO
α
is an instance of ThreadId
αEq
, Ord
and Show
, where the Ord
instance implements an arbitrary total ordering over ThreadId
s. The Show
instance lets you convert an arbitrary-valued ThreadId
to string form; showing
a ThreadId
value is occasionally useful when debugging or diagnosing the
behaviour of a concurrent program.
threadId :: ThreadId α -> ThreadIdSource
Extract the underlying ThreadId
(Conctrol.Concurrent.ThreadId
).
Forking threads
forkIO :: IO α -> IO (ThreadId α)Source
Sparks off a new thread to run the given IO
computation 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 blocked state of the parent (see
block
).
The newly created thread has an exception handler that discards the exceptions
BlockedIndefinitelyOnMVar
, BlockedIndefinitelyOnSTM
, and ThreadKilled
. All
other exceptions are recorded in the ThreadId
and can be retrieved using
wait
.
forkOS :: IO α -> IO (ThreadId α)Source
Like forkIO
, this sparks off a new thread to run the given IO
computation
and returns the ThreadId
of the newly created thread.
Unlike forkIO
, 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
.
Waiting on threads
unsafeWait :: ThreadId α -> IO αSource
Like wait
but will either rethrow the exception that was thrown in the
thread or return the value that was returned by the thread.
unsafeWait_ :: ThreadId α -> IO ()Source
Like unsafeWait
in that it will rethrow the exception that was thrown in
the thread but it will ignore the value returned by the thread.
Waiting with a timeout
waitTimeout :: ThreadId α -> Integer -> IO (Maybe (Either SomeException α))Source
waitTimeout_ :: ThreadId α -> Integer -> IO BoolSource
Like waitTimeout
but will ignore the value returned by the thread.
Returns False
when a timeout occurred and True
otherwise.
unsafeWaitTimeout :: ThreadId α -> Integer -> IO (Maybe α)Source
Like waitTimeout
but will rethrow the exception that was thrown in the
thread. Returns Nothing
if a timeout occured or Just
the value returned from
the target thread.
unsafeWaitTimeout_ :: ThreadId α -> Integer -> IO BoolSource
Like unsafeWaitTimeout
in that it will rethrow the exception that was
thrown in the thread but it will ignore the value returned by the thread.
Returns False
when a timeout occurred and True
otherwise.
Quering thread status
isRunning :: ThreadId α -> IO BoolSource
Returns True
if the given thread is currently running.
Notice that this observation is only a snapshot of a thread's state. By the time a program reacts on its result it may already be out of date.
Convenience functions
throwTo :: Exception e => ThreadId α -> e -> IO ()Source
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.
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 block
or not.
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).
There is currently no guarantee that the exception delivered by throwTo
will
be delivered at the first possible opportunity. In particular, a thread may
unblock
and then re-block
exceptions without receiving a pending
throwTo
. This is arguably undesirable behaviour.
killThread :: ThreadId α -> IO ()Source
killThread
terminates the given thread (GHC only). Any work already done by
the thread isn't lost: the computation is suspended until required by another
thread. The memory used by the thread will be garbage collected if it isn't
referenced from anywhere. The killThread
function is defined in terms of
throwTo
.
This function blocks until the target thread is terminated. It is a no-op if the target thread has already completed.
killThreadTimeout :: ThreadId α -> Integer -> IO BoolSource
Like killThread
but with a timeout. Returns True
if the target thread was
terminated within the given amount of time, False
otherwise.
The timeout is specified in microseconds.
Note that even when a timeout occurs, the target thread can still terminate at a later time as a direct result of calling this function.