Hi, I got question about below code. Maybe my understanding on how async works in Nim is wrong. Please feel free to point that out.
In the code if "poll()" is commented out, the callback is not triggered. I was expecting the dispatcher to kick in once sleep_async finishes. I was hoping I could just register a callback and forget it. However it seems I need to add poll/waitFor/runForever in order for the Future's status to be checked and callback get triggered. If I add poll, it has to be after the Future has finished, waitFor will make the thread block, and runForever should only be used for server program. So what am I supposed to do here?
import os, asyncdispatch
var f = sleep_async 1000
f.add_callback proc() =
echo "Sleep_async finished"
sleep 3000
# poll()
runForever will raise exception when no more pending timers, callbacks, file descriptors.
import asyncdispatch
var f = sleep_async 1000
f.add_callback proc() =
echo "Sleep_async finished"
try:
runForever()
except ValueError:
if getCurrentExceptionMsg() == "No handles or timers registered in dispatcher.":
echo "done"
else:
raise getCurrentException()
The problem here is that ValueError is rather general. The stdlib should provide a more specific exception for this.
I may misunderstood your problem. Your description of Future is correct. In your example code, you just need to waitFor f. But as Araq point out, you should also handle the future exception. If you prefer the callback style, it should be something like this.
import asyncdispatch
proc main() =
let f = sleepAsync 1000
f.addCallback:
if f.failed:
echo "sleep failed..."
else:
echo "sleep finished 1"
let f2 = sleepAsync 500
f2.addCallback:
if f2.failed:
echo "sleep failed..."
else:
echo "sleep finished 2"
waitFor all [f, f2]
main()
It is gcunsafe if closure capture global variables f, f2, so they must be declared in main(). If you need to wait for more than one future, all is a handy helper to combine multiple futures into one.