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?

Reply via email to