| ... | ... | @@ -21,11 +21,11 @@ Operations performed by multiple threads may be interleaved arbitrarily by the i |
|
|
|
- A thread that is not *blocked* will not be indefinitely delayed by the implementation.
|
|
|
|
|
|
|
|
|
|
|
|
Where a thread is *blocked* if
|
|
|
|
where
|
|
|
|
|
|
|
|
- the thread is waiting for an external resource that is currently not available (for example input
|
|
|
|
- a thread is *blocked* if it is waiting for an external resource that is currently not available (for example input
|
|
|
|
from the console), or it is performing an operation that involves a shared resource and another thread
|
|
|
|
currently has ownership of the resource (for example, output to a `Handle`).
|
|
|
|
currently has ownership of the resource (for example, output to a shared `Handle`).
|
|
|
|
|
|
|
|
|
|
|
|
This is called the *fairness guarantee*. An implementation technique that is often used to provide this fairness guarnatee is *pre-emption*: running threads are periodically pre-empted in software in order to let other threads proceed. There are other implementation techniques that also work; for example, hardware concurrency. (**ToDo?**: move this text to a footnote or separate section?)
|
| ... | ... | @@ -81,10 +81,8 @@ Foreign calls may also invoke further Haskell functions by calling `foreign expo |
|
|
|
|
|
|
|
## Bound threads (optional)
|
|
|
|
|
|
|
|
**ToDo?**.
|
|
|
|
|
|
|
|
|
|
|
|
Bound threads allow a Haskell program more control over the mapping between Haskell threads and OS threads. Such control is required for interacting with foreign code that makes use of thread-local state in the native OS threading model. When foreign code uses OS thread-local state, the Haskell programmer needs to restrict calls to that foreign code to happen in a particular OS thread, which is what bound threads provide.
|
|
|
|
Bound threads allow a Haskell program more control over the mapping between Haskell threads and OS threads. Such control is required for interacting with foreign code that makes use of thread-local state in the native OS threading model: when foreign code uses OS thread-local state, the Haskell programmer needs to restrict calls to that foreign code to happen in a particular OS thread. Bound threads provide a lightweight way to allow the programmer enough control without imposing burdens on the implementation that would significantly reduce efficiency.
|
|
|
|
|
|
|
|
|
|
|
|
Bound threads are an optional feature in Haskell'; the documentation for an implementation should state whether bound threads are supported or not.
|
| ... | ... | @@ -92,11 +90,11 @@ Bound threads are an optional feature in Haskell'; the documentation for an impl |
|
|
|
|
|
|
|
A Haskell thread can be either *bound* or *unbound*, depending on how it was created:
|
|
|
|
|
|
|
|
- `forkIO` creates *unbound* threads
|
|
|
|
|
|
|
|
- Calls from foreign code to Haskell functions exposed by `foreign export` or `foreign import "wrapper"` create a
|
|
|
|
*bound* thread in which to run the computation.
|
|
|
|
|
|
|
|
- `forkIO` creates *unbound* threads
|
|
|
|
|
|
|
|
|
|
|
|
Whether a thread is bound or unbound affects how foreign calls are made:
|
|
|
|
|
| ... | ... | @@ -108,7 +106,10 @@ Whether a thread is bound or unbound affects how foreign calls are made: |
|
|
|
Note that a valid implementation of bound threads is one in which every Haskell thread is associated with a distinct OS thread, where in effect every thread is bound. However, the `isCurrentThreadBound` operation (see below) should always return `False` for threads created by `forkIO`, regardless of the implementation, to aid portabilty.
|
|
|
|
|
|
|
|
|
|
|
|
The following operations exported by `Control.Concurrent` are related to bound threads:
|
|
|
|
Also note that the above property of foreign calls made by a bound thread is the *only* requirement of the relationship between OS threads and Haskell threads. It is completely unspecified which OS thread runs the Haskell code itself: the implementation is free to choose among a number of strategies here.
|
|
|
|
|
|
|
|
|
|
|
|
The following operations exported by `Control.Concurrent` are related to bound threads (**ToDo?** just link to the appropriate section of the library docs here?):
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
supportsBoundThreads :: Bool
|
| ... | ... | @@ -122,11 +123,11 @@ This value is `True` if the implementation supports bound threads (**NB.** this |
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
This operation returns `False` if the current thread was created by `forkIO`, and `True` otherwise.
|
|
|
|
This operation returns `False` if the current thread was created by `forkIO`, and `True` otherwise. If `supportsBoundThreads` is `False`, this function raises an exception (**ToDo?** which one?).
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
forkOS :: IO () -> IO ThreadId
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Like `forkIO`, `forkOS` creates a new Haskell thread to run the supplied `IO` action. However, in the case of `forkOS`, the new Haskell thread is bound to a freshly created OS thread. This is achieved by making a foreign call to create the new OS thread, and having the new OS thread invoke the `IO` action, thus creating a bound thread. |
|
|
|
Like `forkIO`, `forkOS` creates a new Haskell thread to run the supplied `IO` action. However, in the case of `forkOS`, the new Haskell thread is bound to a freshly created OS thread. This is achieved by making a foreign call to create the new OS thread, and having the new OS thread invoke the `IO` action, thus creating a bound thread. If `supportsBoundThreads` is `False`, this function raises an exception (**ToDo?** which one?). |