| ... | @@ -30,12 +30,12 @@ Operations performed by multiple threads may be interleaved arbitrarily by the i |
... | @@ -30,12 +30,12 @@ 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.
|
|
- 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
|
|
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?)
|
|
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?)
|
| ... | @@ -113,11 +113,7 @@ Foreign calls may also invoke further Haskell functions by calling `foreign expo |
... | @@ -113,11 +113,7 @@ Foreign calls may also invoke further Haskell functions by calling `foreign expo |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**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. 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 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| ... | @@ -128,11 +124,11 @@ Bound threads are an optional feature in Haskell'; the documentation for an impl |
... | @@ -128,11 +124,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:
|
|
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
|
|
- 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.
|
|
*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:
|
|
Whether a thread is bound or unbound affects how foreign calls are made:
|
|
|
|
|
|
| ... | @@ -146,7 +142,11 @@ Note that a valid implementation of bound threads is one in which every Haskell |
... | @@ -146,7 +142,11 @@ Note that a valid implementation of bound threads is one in which every Haskell |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
```wiki
|
| ... | @@ -162,7 +162,7 @@ This value is `True` if the implementation supports bound threads (**NB.** this |
... | @@ -162,7 +162,7 @@ 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
|
|
```wiki
|
| ... | @@ -170,6 +170,6 @@ This operation returns `False` if the current thread was created by `forkIO`, an |
... | @@ -170,6 +170,6 @@ This operation returns `False` if the current thread was created by `forkIO`, an |
|
|
```
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
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?).
|
|
|
|
|
|
|
|
|
|
|