Ah, that does make sense. But I'm curious what other way I might achieve what
I'm trying to do. In short, I'm planning on interfacing with a C library, a
JavaScript runtime. It requires that it be used on the same thread at all
times, so I'm using the channels and threads modules to enable that. My idea
was that I'd have an outgoing channel and an incoming channel and pass
references to a future through them. A very simplified version here:
import asyncdispatch
import threadpool
type ChannelMsg = object
future: ref Future[string]
var from_thread: Channel[ChannelMsg]
var to_thread: Channel[ChannelMsg]
from_thread.open()
to_thread.open()
proc run_on_thread() {.thread.} =
while true:
let incoming = to_thread.recv()
echo "Received on thread, sending back"
from_thread.send(ChannelMsg(future: incoming.future))
var thread: Thread[void]
createThread(thread, run_on_thread)
proc run_outside_thread() =
while true:
let outgoing = from_thread.recv()
echo "Received off thread"
outgoing.future[].complete("DONE")
spawn run_outside_thread()
var future: ref Future[string] = new(ref Future[string])
future[] = newFuture[string]()
echo "Sending to thread"
to_thread.send(ChannelMsg(future: future))
let result = waitFor future[]
echo result
Run
And it very nearly works! The output is:
Sending to thread
Received on thread, sending back
Received off thread
[...]
Error: unhandled exception: No handles or timers registered in dispatcher.
[ValueError]
Run
...which makes total sense given what you're saying about IO and timers. Is
there an entirely different approach I should be taking here?