Threads
While the cooperative async
model offers an efficient model
for dealing with many tasks that often are blocked on I/O, it is not suitable
for long-running computations that would prevent concurrent tasks from progressing.
Multithreading offers a way to offload heavy computations to be executed in parallel with the async work, or, in cases where a single event loop gets overloaded, to manage multiple event loops in parallel.
For interaction between threads, the ThreadSignalPtr
type (found in the
(chronos/threadsync
)(https://github.com/status-im/nim-chronos/blob/master/chronos/threadsync.nim)
module) is used - both to wait for notifications coming from other threads and
to notify other threads of progress from within an async procedure.
import chronos, chronos/threadsync
import os
type
Context = object
# Context allocated by `createShared` should contain no garbage-collected
# types!
signal: ThreadSignalPtr
value: int
proc myThread(ctx: ptr Context) {.thread.} =
echo "Doing some work in a thread"
sleep(3000)
ctx.value = 42
echo "Done, firing the signal"
discard ctx.signal.fireSync().expect("correctly initialized signal should not fail")
proc main() {.async.} =
let
signal = ThreadSignalPtr.new().expect("free file descriptor for signal")
context = createShared(Context)
context.signal = signal
var thread: Thread[ptr Context]
echo "Starting thread"
createThread(thread, myThread, context)
await signal.wait()
echo "Work done: ", context.value
joinThread(thread)
signal.close().expect("closing once works")
deallocShared(context)
waitFor main()