Hello guys, I made a practical guide to Async IO in Zig.
It goes through small runnable examples for Futures, Io.Group , Io.Select , cancellations, Io.Queue , sleep/timers, and Io.Batch . I tried to keep it minimal and practical
It is not accurate to say io.async may not be truly async.
Asynchrony is the possibility that tasks may run in any order, and that if that happens they will still be correct.
io.async running tasks synchronously is well within the technical definition of asynchrony.
Some important things you should have mentioned:
Futures/Groups must eventually be awaited or canceled, not only because they have associated resources that the Io implementation cannot release until it knows you have the result.
But also because an Io implementation is allowed to only start async tasks when you await (cancel obviously lets it skip running it)
A common misconception is that the above deleyed start also applies to concurrent tasks, that is not the case, concurrent tasks will start ASAP. Otherwise they would not be that useful.
Lastly, you should avoid overusing async/concurrent, they have overhead, you would not start a thread just for some trivial math.
Asynchrony did not have a proper definition, even in languages that have async, everyone just had their own interpretation, often created after the fact to describe the languages’ implementation of async.
Zig has clearly stated the terms and definitions it is working with, we ought to use them when talking about zig, and ofc explain these definitions when (commonly) necessary.
I like to think of async as “order independent”, meaning task B and A can run without worrying which comes first. Whether or not your particular runtime and scheduler can run them concurrently that is a separate concern.
I find it pleasant to model tasks as “always async” first, then to use a list for expressing order of operations. That way, you maintain the concurrency availability and the list enforces before and after.
Semantics. async has to return because otherwise it cant be implemented as synchronous call. Concurrent has to able to yield so it doesnt deadlock / can return control back to program without returning.
Consider calling a function that calls io function in a while true loop.