| ... | ... | @@ -66,11 +66,56 @@ The `ThreadId` type is abstract, and supports `Eq`, `Ord`, and `Show`, with the |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**ToDo?**: MVars or STM.
|
|
|
|
The basic facility for communication between threads is the `MVar` type.
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
data MVar -- instance of Eq, Typeable, Typeable1
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
An MVar (pronounced "em-var") is a synchronising variable. It can be thought of as a a box, which may be empty or full. An `MVar` may be created using one of the following two operations:
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
newEmptyMVar :: IO (MVar a)
|
|
|
|
newMVar :: a -> IO (MVar a)
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
`newEmptyMVar` create an MVar which is initially empty; `newMVar` create an MVar which contains the supplied value.
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
takeMVar :: MVar a -> IO a
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
The `takeMVar` operation return the contents of the `MVar`. If the `MVar` is currently empty, `takeMVar` will block until it is full. After a `takeMVar`, the `MVar` is left empty.
|
|
|
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
|
putMVar :: MVar a -> a -> IO ()
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Put a value into an `MVar`. If the `MVar` is currently full, `putMVar` will wait until it becomes empty.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
There is an extension to the fairness guarantee as it applies to `MVar`s:
|
|
|
|
|
|
|
|
|
|
|
|
- A thread blocked on an `MVar` will eventually proceed, as long as the `MVar` is being filled infinitely often.
|
|
|
|
|
|
|
|
|
|
|
|
It is recommended that the implementation provide "single-wakeup" semantics for `takeMVar`. That is, if there are multiple threads
|
|
|
|
blocked in `takeMVar` on a particular `MVar`, and the `MVar` becomes full, only one thread will be woken up. The implementation
|
|
|
|
guarantees that the woken thread completes its `takeMVar` operation. In fact, a single-wakeup implementation is usually a consequence of providing the fairness extension for `MVar`s above: if multiple threads blocked on an `MVar` were woken up simultaneously, it would be hard to guarantee that any particular thread would eventually gain access to the `MVar`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MVars have important properties that can't be simulated in STM: fairness and single-wakeup. (only the first is important from a semantics perspective, the second has significant practical importance though).
|
|
|
|
**ToDo?** STM?
|
|
|
|
|
|
|
|
|
|
|
|
## Concurrency and the FFI
|
| ... | ... | @@ -142,7 +187,7 @@ Note that a valid implementation of bound threads is one in which every Haskell |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
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 Haskell programmer has no way to observe the current OS thread aside from making a foreign call, so the implementation is free to choose among a number of strategies here.
|
|
|
|
|
|
|
|
|
|
|
|
|
| ... | ... | |