diff options
author | Araq <rumpf_a@web.de> | 2014-04-19 22:24:43 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-04-19 22:24:43 +0200 |
commit | 3b69a8d27a6b87bcb3440b5dae4aa2f618204264 (patch) | |
tree | 99ca5259b57b7bdbc80363db0fa49ced2a019517 /doc/manual.txt | |
parent | 8e08ff559f4c03587c683b1bf2ef71f256af3824 (diff) | |
download | Nim-3b69a8d27a6b87bcb3440b5dae4aa2f618204264.tar.gz |
New concurrency model: next steps
Diffstat (limited to 'doc/manual.txt')
-rw-r--r-- | doc/manual.txt | 104 |
1 files changed, 26 insertions, 78 deletions
diff --git a/doc/manual.txt b/doc/manual.txt index c0d4f2627..d6b9f296e 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -5616,7 +5616,6 @@ Memory allocation requires no lock at all! This design easily scales to massive multicore processors that will become the norm in the future. - Thread pragma ------------- @@ -5626,12 +5625,32 @@ violations of the `no heap sharing restriction`:idx:\: This restriction implies that it is invalid to construct a data structure that consists of memory allocated from different (thread local) heaps. -Since the semantic checking of threads requires whole program analysis, -it is quite expensive and can be turned off with ``--threadanalysis:off`` to -improve compile times. +A thread proc is passed to ``createThread`` or ``spawn`` and invoked +indirectly; so the ``thread`` pragma implies ``procvar``. + + +GC safety +--------- + +We call a proc ``p`` `GC safe`:idx: when it doesn't access any global variable +that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either +directly or indirectly through a call to a GC unsafe proc. + +The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe +otherwise this property is inferred by the compiler. Note that ``noSideEfect`` +implies ``gcsafe``. The only way to create a thread is via ``spawn`` or +``createThead``. ``spawn`` is usually the preferable method. Either way +the invoked proc must not use ``var`` parameters nor must any of its parameters +contain a ``ref`` or ``closure`` type. This enforces +the *no heap sharing restriction*. + +Routines that are imported from C are always assumed to be ``gcsafe``. + +Future directions: -A thread proc is passed to ``createThread`` and invoked indirectly; so the -``thread`` pragma implies ``procvar``. +- For structured fork&join parallelism more efficient parameter passing can + be performed and much more can be proven safe. +- A shared GC'ed heap is planned. Threadvar pragma @@ -5648,78 +5667,6 @@ initialized within the ``var`` section. (Every thread local variable needs to be replicated at thread creation.) -Actor model ------------ - -**Caution**: This section is already outdated! XXX - -Nimrod supports the `actor model`:idx: of concurrency natively: - -.. code-block:: nimrod - type - TMsgKind = enum - mLine, mEof - TMsg = object - case k: TMsgKind - of mEof: nil - of mLine: data: string - - var - thr: TThread[TMsg] - printedLines = 0 - m: TMsg - - proc print() {.thread.} = - while true: - var x = recv[TMsg]() - if x.k == mEof: break - echo x.data - discard atomicInc(printedLines) - - createThread(thr, print) - - var input = open("readme.txt") - while not endOfFile(input): - m.data = input.readLine() - thr.send(m) - close(input) - m.k = mEof - thr.send(m) - joinThread(thr) - - echo printedLines - -In the actor model threads communicate only over sending messages (`send`:idx: -and `recv`:idx: built-ins), not by sharing memory. Every thread has -an `inbox`:idx: that keeps incoming messages until the thread requests a new -message via the ``recv`` operation. The inbox is an unlimited FIFO queue. - -In the above example the ``print`` thread also communicates with its -parent thread over the ``printedLines`` global variable. In general, it is -highly advisable to only read from globals, but not to write to them. In fact -a write to a global that contains GC'ed memory is always wrong, because it -violates the *no heap sharing restriction*: - -.. code-block:: nimrod - var - global: string - t: TThread[string] - - proc horrible() {.thread.} = - global = "string in thread local heap!" - - createThread(t, horrible) - joinThread(t) - -For the above code the compiler produces "Warning: write to foreign heap". This -warning might become an error message in future versions of the compiler. - -Creating a thread is an expensive operation, because a new stack and heap needs -to be created for the thread. It is therefore highly advisable that a thread -handles a large amount of work. Nimrod prefers *coarse grained* -over *fine grained* concurrency. - - Threads and exceptions ---------------------- @@ -5727,6 +5674,7 @@ The interaction between threads and exceptions is simple: A *handled* exception in one thread cannot affect any other thread. However, an *unhandled* exception in one thread terminates the whole *process*! + Taint mode ========== |