summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAntoine Delègue <delegue.antoine@gmail.com>2024-04-11 09:13:17 +0200
committerGitHub <noreply@github.com>2024-04-11 09:13:17 +0200
commit2bd2f2885873f5eb2c722b3647fd11ee480a2452 (patch)
tree51c1319e58a64260299f5573c05ce54f67390185
parent9b378296f65fff962225acc1bef2b3811fffda03 (diff)
downloadNim-2bd2f2885873f5eb2c722b3647fd11ee480a2452.tar.gz
Better documentation for typedthreads module (#23483)
Added a second example inside the `typedthreads` file.

Also, add a more detailed introduction. When Nim is one's first
programming language, a short explanation of what a thread is might not
hurt.

For reference, the thread documentation of other languages looks like
this:
- https://en.cppreference.com/w/cpp/thread/thread
- https://doc.rust-lang.org/std/thread/

The documentation of a module is the first place one will look when
using a standard library feature, so I think it is important to have a
few usable examples for the main modules.

This is the example added
```nim
import locks

var l: Lock

proc threadFunc(obj: ptr seq[int]) {.thread.} =
    withLock l:
        for i in 0..<100:
            obj[].add(obj[].len * obj[].len)

proc threadHandler() =
    var thr: array[0..4, Thread[ptr seq[int]]]
    var s = newSeq[int]()
    
    for i in 0..high(thr):
        createThread(thr[i], threadFunc, s.addr)
    joinThreads(thr)
    echo s

initLock(l)
threadHandler()
deinitLock(l)
```

Sharing memory between threads is very very common, so I think having an
example showcasing this is crucial.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
-rw-r--r--lib/std/typedthreads.nim94
1 files changed, 67 insertions, 27 deletions
diff --git a/lib/std/typedthreads.nim b/lib/std/typedthreads.nim
index 501a0d0fa..7b0b81968 100644
--- a/lib/std/typedthreads.nim
+++ b/lib/std/typedthreads.nim
@@ -7,33 +7,73 @@
 #    distribution, for details about the copyright.
 #
 
-## Thread support for Nim.
-##
-## Examples
-## ========
-##
-##   ```Nim
-##   import std/locks
-##
-##   var
-##     thr: array[0..4, Thread[tuple[a,b: int]]]
-##     L: Lock
-##
-##   proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
-##     for i in interval.a..interval.b:
-##       acquire(L) # lock stdout
-##       echo i
-##       release(L)
-##
-##   initLock(L)
-##
-##   for i in 0..high(thr):
-##     createThread(thr[i], threadFunc, (i*10, i*10+5))
-##   joinThreads(thr)
-##
-##   deinitLock(L)
-##   ```
-
+##[
+Thread support for Nim. Threads allow multiple functions to execute concurrently.
+ 
+In Nim, threads are a low-level construct and using a library like `malebolgia`, `taskpools` or `weave` is recommended.
+ 
+When creating a thread, you can pass arguments to it. As Nim's garbage collector does not use atomic references, sharing
+`ref` and other variables managed by the garbage collector between threads is not supported.
+Use global variables to do so, or pointers.
+ 
+Memory allocated using [`sharedAlloc`](./system.html#allocShared.t%2CNatural) can be used and shared between threads.
+
+To communicate between threads, consider using [channels](./system.html#Channel)
+
+Examples
+========
+
+```Nim
+import std/locks
+
+var
+  thr: array[0..4, Thread[tuple[a,b: int]]]
+  L: Lock
+
+proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
+  for i in interval.a..interval.b:
+    acquire(L) # lock stdout
+    echo i
+    release(L)
+
+initLock(L)
+
+for i in 0..high(thr):
+  createThread(thr[i], threadFunc, (i*10, i*10+5))
+joinThreads(thr)
+
+deinitLock(L)
+```
+ 
+When using a memory management strategy that supports shared heaps like `arc` or `boehm`,
+you can pass pointer to threads and share memory between them, but the memory must outlive the thread.
+The default memory management strategy, `orc`, supports this.
+The example below is **not valid** for memory management strategies that use local heaps like `refc`!
+
+```Nim
+import locks
+ 
+var l: Lock
+ 
+proc threadFunc(obj: ptr seq[int]) {.thread.} =
+  withLock l:
+    for i in 0..<100:
+      obj[].add(obj[].len * obj[].len)
+ 
+proc threadHandler() =
+  var thr: array[0..4, Thread[ptr seq[int]]]
+  var s = newSeq[int]()
+    
+  for i in 0..high(thr):
+    createThread(thr[i], threadFunc, s.addr)
+  joinThreads(thr)
+  echo s
+ 
+initLock(l)
+threadHandler()
+deinitLock(l)
+```
+]##
 
 
 import std/private/[threadtypes]