| ... | ... | @@ -102,7 +102,7 @@ expect. |
|
|
|
|
|
|
|
|
|
|
|
- Simpler from the programmer's point of view: no yield, no
|
|
|
|
worrying about latency. "write code as if the current
|
|
|
|
worrying about latency. "write a thread as if the current
|
|
|
|
thread is the only one.".
|
|
|
|
|
|
|
|
|
| ... | ... | @@ -140,7 +140,7 @@ expect. |
|
|
|
|
|
|
|
- Hard to implement, no implementations yet.
|
|
|
|
|
|
|
|
### 2. Syntax for foreign call annoatations.
|
|
|
|
### 2. nomenclature for foreign call annoatations.
|
|
|
|
|
|
|
|
|
|
|
|
|
| ... | ... | @@ -148,124 +148,128 @@ expect. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**2.1.a.** we annotate concurrent calls with
|
|
|
|
**2.1.a.** we annotate concurrent calls:
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **a.** concurrent
|
|
|
|
>
|
|
|
|
> **b.** mayblock
|
|
|
|
>
|
|
|
|
> **c.** mightblock
|
|
|
|
>
|
|
|
|
> **d.** blocks
|
|
|
|
>
|
|
|
|
> **e.** longrunning
|
|
|
|
>
|
|
|
|
>
|
|
|
|
1. concurrent
|
|
|
|
1. mayblock
|
|
|
|
1. mightblock
|
|
|
|
1. blocks
|
|
|
|
1. longrunning
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **Rationale** for using the term "block": blocking is the main
|
|
|
|
> reason for wanting concurrent calls. Concurrent calls allow the
|
|
|
|
> progress guarantee to be retained in the presence of a blocking
|
|
|
|
> foreign call. A foreign call that just takes a long time is still
|
|
|
|
> making progress.
|
|
|
|
>
|
|
|
|
>
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **Rationale** for not using the term "block": the fact that the
|
|
|
|
> call blocks is immaterial, the property we want to provide is that
|
|
|
|
> it doesn't impede progress of other Haskell threads. A long-running
|
|
|
|
> call is indistinguishable from a blocked call in terms of the
|
|
|
|
> progress of other threads.
|
|
|
|
>
|
|
|
|
>
|
|
|
|
**Rationale** for using the term "block": blocking is the main
|
|
|
|
reason for wanting concurrent calls. Concurrent calls allow
|
|
|
|
the progress guarantee to be retained in the presence of a
|
|
|
|
blocking foreign call. A foreign call that just takes a long
|
|
|
|
time is still making progress.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Rationale** for not using the term "block": the fact that the
|
|
|
|
call blocks is immaterial, the property we want to provide is
|
|
|
|
that it doesn't impede progress of other Haskell threads. A
|
|
|
|
long-running call is indistinguishable from a blocked call in
|
|
|
|
terms of the progress of other threads.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We often don't know whether a library call will block or not
|
|
|
|
(it isn't documented), whereas saying a call should run
|
|
|
|
concurrently with other threads is a choice the programmer can
|
|
|
|
reasonably make.
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> We often don't know whether a library call will block or not (it
|
|
|
|
> isn't documented), whereas saying a call should run concurrently
|
|
|
|
> with other threads is a choice the programmer can reasonably make.
|
|
|
|
>
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
**2.1.b.** we annotate non concurrent calls:
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **Rationale** for annotating the non-concurrent calls: this is a
|
|
|
|
> performance issue. It is always correct to make a concurrent call,
|
|
|
|
> but it might be more efficient to make a non-concurrent call if the
|
|
|
|
> call does not block. An implementation might implement *all*
|
|
|
|
> calls as concurrent, for simplicity.
|
|
|
|
>
|
|
|
|
>
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> Against: John Meacham says "The FFI is inherently unsafe. We do not
|
|
|
|
> need to coddle the programer who is writing raw FFI code."
|
|
|
|
>
|
|
|
|
>
|
|
|
|
**Rationale** for annotating the non-concurrent calls: this is a
|
|
|
|
performance issue. It is always correct to make a concurrent
|
|
|
|
call, but it might be more efficient to make a non-concurrent
|
|
|
|
call if the call does not block. An implementation might
|
|
|
|
implement \*all\* calls as concurrent, for simplicity.
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **a.** nonconcurrent
|
|
|
|
>
|
|
|
|
> **b.** noblock
|
|
|
|
>
|
|
|
|
> **c.** returnsquickly
|
|
|
|
>
|
|
|
|
> **d.** fast
|
|
|
|
>
|
|
|
|
> **e.** quick
|
|
|
|
>
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
Against: John Meacham says "The FFI is inherently unsafe. We
|
|
|
|
do not need to coddle the programer who is writing raw FFI
|
|
|
|
code."
|
|
|
|
|
|
|
|
**2.2.** choices for non-reentrant calls:
|
|
|
|
|
|
|
|
1. nonconcurrent
|
|
|
|
1. noblock
|
|
|
|
1. returnsquickly
|
|
|
|
1. fast
|
|
|
|
1. quick
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **a.** nonreentrant
|
|
|
|
>
|
|
|
|
> **b.** nocallback
|
|
|
|
>
|
|
|
|
>
|
|
|
|
|
|
|
|
>
|
|
|
|
>
|
|
|
|
> **Rationale** for annotating the non-reentrant calls, as opposed
|
|
|
|
> to the reentrant ones: we want the "safe" option to be the default
|
|
|
|
> (as in the FFI spec).
|
|
|
|
>
|
|
|
|
>
|
|
|
|
**2.2.** choices for non-reentrant calls:
|
|
|
|
|
|
|
|
|
|
|
|
1. nonreentrant
|
|
|
|
1. nocallback
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Rationale** for annotating the non-reentrant calls, as opposed
|
|
|
|
to the reentrant ones: we want the "safe" option to be the
|
|
|
|
default (as in the FFI spec).
|
|
|
|
|
|
|
|
**2.3.** should we annotate foreign calls according to whether they need
|
|
|
|
to access thread-local state (TLS) or not?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Pros**
|
|
|
|
In favour: a call that doesn't need access to thread-local state,
|
|
|
|
called from a bound thread, can be executed much more quickly on
|
|
|
|
an implementation that doesn't run the Haskell thread directly on
|
|
|
|
the bound OS thread, because it doesn't need to context switch.
|
|
|
|
|
|
|
|
|
|
|
|
- a call that doesn't need access to thread-local state, called from a bound thread, can be executed much more quickly on an implementation that doesn't run the Haskell thread directly on the bound OS thread, because it doesn't need to context switch.
|
|
|
|
|
|
|
|
Against: libraries that require TLS, eg. OpenGL, often have many
|
|
|
|
fast TLS-using functions. So implementations that need the no-TLS
|
|
|
|
annotation in order to get good performance, will probably still
|
|
|
|
get poor performance from libraries that need TLS anyway.
|
|
|
|
|
|
|
|
**Cons**
|
|
|
|
|
|
|
|
### 3. Semantics of IORefs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`MVar` operations must be strictly ordered; that is, a thread must never
|
|
|
|
observe `MVar` operations performed by another thread out of order.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
We have a choice when it comes to `IORef`s, however. (Note that
|
|
|
|
this only affects true multiprocessor implementations of concurrent
|
|
|
|
Haskell).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**3.a** Specify a weak memory model, in which `IORef` updates
|
|
|
|
may be observed out of order, but specify that certain operations
|
|
|
|
(eg. `MVar` operations) constitute sequence points around which no
|
|
|
|
re-ordering may happen.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**3.b** Specify a strong memory model in which no re-ordering is
|
|
|
|
observable.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**Pros**
|
|
|
|
|
|
|
|
|
|
|
|
- Some processors provide this anyway (current generations of x86, x86-64)
|
|
|
|
|
|
|
|
- The implementation will require some synchronisation in any case in order to prevent threads from observing partially-written closures. For example, if one thread builds a closure and writes its address into an `IORef`, there must be a write barrier (and possibly a read barrier depending on the CPU) to prevent other threads from following the pointer and not finding the closure at the end of it. This synchronisation may be enough to provide the strong memory model anyway.
|
|
|
|
|
|
|
|
- libraries that require TLS, eg. OpenGL, often have many fast TLS-using functions. So implementations that need the no-TLS annotation in order to get good performance, will probably still get poor performance from libraries that need TLS anyway.
|
|
|
|
- Strong memory models are easier to program with, and leave fewer possibilities for a program to behave unexpectedly on a different processor or Haskell implementation.
|
|
|
|
|
|
|
|
---
|
|
|
|
|
| ... | ... | |