Threads ======= To enable thread support the ``--threads:on`` command line switch needs to be used. The ``system`` module then contains several threading primitives. See the `threads `_ and `channels `_ modules for the low level thread API. There are also high level parallelism constructs available. See `spawn`_ for further details. Nim's memory model for threads is quite different than that of other common programming languages (C, Pascal, Java): Each thread has its own (garbage collected) heap and sharing of memory is restricted to global variables. This helps to prevent race conditions. GC efficiency is improved quite a lot, because the GC never has to stop other threads and see what they reference. Memory allocation requires no lock at all! This design easily scales to massive multicore processors that are becoming the norm. Thread pragma ------------- A proc that is executed as a new thread of execution should be marked by the ``thread`` pragma for reasons of readability. The compiler checks for 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. 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 ``noSideEffect`` 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``. To disable the GC-safety checking the ``--threadAnalysis:off`` command line switch can be used. This is a temporary workaround to ease the porting effort from old code to the new threading model. Future directions: - A shared GC'ed heap might be provided. Threadvar pragma ---------------- A global variable can be marked with the ``threadvar`` pragma; it is a `thread-local`:idx: variable then: .. code-block:: nim var checkpoints* {.threadvar.}: seq[string] Due to implementation restrictions thread local variables cannot be initialized within the ``var`` section. (Every thread local variable needs to be replicated at thread creation.) Threads and exceptions ---------------------- 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*! Parallel & Spawn ================ Nim has two flavors of parallelism: 1) `Structured`:idx: parallelism via the ``parallel`` statement. 2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement. Nim has a builtin thread pool that can be used for CPU intensive tasks. For IO intensive tasks the ``async`` and ``await`` features should be used instead. Both parallel and spawn need the `threadpool `_ module to work. Somewhat confusingly, ``spawn`` is also used in the ``parallel`` statement with slightly different semantics. ``spawn`` always takes a call expression of the form ``f(a, ...)``. Let ``