Channel Synchronization in Nim
We can use channels to synchronize execution across threads. Here’s an example of using a blocking receive to wait for a thread to finish. When waiting for multiple threads to finish, you may prefer to use a CountdownLatch
or ThreadPool
.
import std/[threadpool, os]
# This is the procedure we'll run in a thread. The
# `done` channel will be used to notify another
# thread that this procedure's work is done.
proc worker(done: Channel[bool]) =
stdout.write("working...")
stdout.flushFile()
sleep(1000) # Sleep for 1 second
echo "done"
# Send a value to notify that we're done.
done.send(true)
# Start a worker thread, giving it the channel to
# notify on.
let done = newChannel[bool]()
spawn worker(done)
# Block until we receive a notification from the
# worker on the channel.
discard done.recv()
To run the program:
$ nim c -r channel_synchronization.nim
working...done
If you removed the discard done.recv()
line from this program, the program would exit before the worker
even started.
In Nim, we use spawn
to create a new thread, which is similar to goroutines in concept. The Channel
type is used for communication between threads, analogous to channels in Go. The newChannel[bool]()
creates a new channel that can send and receive boolean values.
The worker
procedure simulates work by sleeping for a second, and then sends a value on the channel to signal completion. The main thread waits for this signal by calling done.recv()
, which blocks until a value is received.
Note that Nim’s concurrency model is based on OS threads, which are more heavyweight than Go’s goroutines, but the synchronization concept remains similar.