Closing Channels in Nim
import std/[asyncdispatch, asyncfutures]
proc main() {.async.} =
var jobs = newAsyncChannel[int](5)
var done = newAsyncFuture[bool]()
# Here's the worker procedure. It repeatedly receives
# from `jobs` with `let (j, more) = await jobs.recv()`. In this
# special 2-value form of receive, the `more` value
# will be `false` if `jobs` has been `close`d and all
# values in the channel have already been received.
# We use this to notify on `done` when we've worked
# all our jobs.
asyncSpawn(async proc() =
while true:
let (j, more) = await jobs.recv()
if more:
echo "received job ", j
else:
echo "received all jobs"
done.complete(true)
return
)
# This sends 3 jobs to the worker over the `jobs`
# channel, then closes it.
for j in 1..3:
await jobs.send(j)
echo "sent job ", j
jobs.close()
echo "sent all jobs"
# We await the worker using the synchronization approach
# we saw earlier.
discard await done
# Reading from a closed channel succeeds immediately,
# returning the zero value of the underlying type.
# The optional second return value is `true` if the
# value received was delivered by a successful send
# operation to the channel, or `false` if it was a
# zero value generated because the channel is closed
# and empty.
let (_, ok) = await jobs.recv()
echo "received more jobs: ", ok
waitFor main()
In this example, we demonstrate how to use asynchronous channels in Nim to communicate work between different asynchronous procedures. This is similar to using goroutines and channels in other languages.
We use the asyncdispatch
and asyncfutures
modules to work with asynchronous programming in Nim. The AsyncChannel
type is used to create a buffered channel for communication between asynchronous procedures.
The main
procedure is marked as async
and contains the main logic of our program. We create an AsyncChannel
for jobs and an AsyncFuture
for synchronization.
We define a worker procedure using asyncSpawn
which continuously receives jobs from the channel. It uses pattern matching to check if more jobs are available or if the channel has been closed.
In the main procedure, we send three jobs to the worker, close the channel, and then wait for the worker to complete processing all jobs.
Finally, we demonstrate how to check if a channel is closed by attempting to receive from it after it has been closed.
To run this program, save it as closing_channels.nim
and use the following command:
$ nim c -r closing_channels.nim
This will compile and run the Nim program, producing output similar to:
sent job 1
received job 1
sent job 2
received job 2
sent job 3
received job 3
sent all jobs
received all jobs
received more jobs: false
This example showcases Nim’s approach to concurrent programming using asynchronous procedures and channels, which provides similar functionality to goroutines and channels in other languages.