I have the following simple example of an inter-thread communication problem: I want to run arbitrary "anytime" algorithms in a background thread. An anytime algorithm performs some computation of result type T
incrementally, i.e., it sporadically produces newer, more precise results. In Nim parlance, they are probably best represented by an iterator. In the main thread, I now want to wrap such iterators each in its own thread, with the possibility to query the threads for things like "is there a new value available" or "what is the current computation result".
Since I'm not familiar with Nim's concurrency concepts I have trouble to implement the required inter-thread communication. My idea was to use a TChannel
for the communication. According to this forum post, a TChannel
cannot be used in combination with spawn
but requires to use createThread
. I managed to get the following to compile and run:
import os, threadpool
proc spawnBackgroundJob[T](f: iterator (): T): TChannel[T] =
type Args = tuple[iter: iterator (): T, channel: ptr TChannel[T]]
# I think I have to wrap the iterator to pass it to createThread
proc threadFunc(args: Args) {.thread.} =
echo "Thread is starting"
let iter = args.iter
var channel = args.channel[]
for i in iter():
echo "Sending ", i
channel.send(i)
var thread: TThread[Args]
var channel: TChannel[T]
channel.open()
let args = (f, channel.addr)
createThread(thread, threadFunc, args)
result = channel
# example use in some main thread:
iterator test(): int {.closure.} =
sleep(500)
yield 1
sleep(500)
yield 2
var channel = spawnBackgroundJob[int](test)
for i in 0 .. 10:
sleep(200)
echo channel.peek()
echo "Finished"
Unfortunately, this does not have the expected behavior, i.e., I never receive anything in the main thread. I was told on IRC that the problem is that I do not use global variables. But even after a long time thinking I neither do see exactly why this fails, nor if there is a way to solve it. The problem is that I cannot simply make the variables thread
and channel
global, since they depend on the type T
. I also want to avoid restricting this to only run a single anytime algorithm (or some other fixed number N). I was also told that the approach does not really make sense overall, so maybe I'm just missing that this problem has an entirely different solution?