Hey everyone, just wanted to boast with three major features landed into yasync
1. Cancellation! It is now possible to cancel running tasks, and to handle cancellation in asyncRaw terminal procs, like this:
proc onCancelSleep(env: ptr Cont[void]) =
log "sleep cancelled: "
proc sleepRaw*(ms: int, env: ptr Cont[void]) {.asyncRaw.} =
echo "sleeping"
asyncdispatch.addCallback(asyncdispatch.sleepAsync(ms)) do():
env.complete()
setCancelCb(env, onCancelSleep)
let f = sleepRaw(1000) # Start async task
f.cancel() # Cancel!
assert(f.error of CancelError) # CancelError is "raised" in terminal future, and propagated along async stack like any other.
That's all for today. Note that yasync is designed with maximum performance and memory efficiency in mind (like, to stupid extents), and these new features do not make any compromises in that regards. Would be happy to hear your feedback! And bugs, if any, yes...
- Optimizable calls optimization
ooh, nice - can you think of any blockers why this couldn't be done in chronos proper?
re @PMunch
This is great stuff! How simple is it to switch an existing async program over to yasync?
It's not a drop-in replacement, but pretty straightforward most of the time. The good thing is you can mix yasync with asyncdispatch/chronos futures, it's not all-or-nothing, so the migration can be chopped to multiple independent steps, if your async project is big.
re @darkestpigeon
How hard would it be to make it possible to move tasks between threads (assuming atomicArc for simplicity)? Or at least to have some constrained version of this, e.g. assigning an opened TCP connection to a different loop?
I take it as it's a dispatcher's responsibility. And yasync should give you all the means to make it possible. The cornerstone feature is that you can get the type of env for an async task, allocate this env however you want, and launch the task on this env. Since this is an object type you can compile-time introspect it for GC-unsafe data, and stuff like that. Scheduling itself is not something that yasync is concerned about, but if you implement a multithreaded scheduler and find some complexities in yasync in that regards, please let me know.
re @arnetheduck
ooh, nice - can you think of any blockers why this couldn't be done in chronos proper?
Hard to say, it might be possible, dunno. The whole idea that yasync is based on, is that there are no futures (as in "there's no spoon"), they're only in our head, for semantic reasoning. yasync keeps track of proc types, and env types in compile time, and can collapse subenvs. This is fundamentally different from what asyncdispatch and chronos do. As it turned out this approach also allowed for relatively bloodless optimizable calls optimization, because most of the infrastructure was there already.