How does downstream code know which kind of asynchrony is requested / allowed?
Assume some code is trying to blink an LED, which can only be done with the led_on and led_off system calls. Those system calls block until they get an ack from the LED controller, which, in the worst case, will timeout after 10s if the controller is broken.
In e.g. Python, my function is either sync or async, if it's async, I know I have to go through the rigamarole of accessing the event loop and scheduling the blocking syscall on a background thread. If it's sync, I know I'm allowed to block, but I can't assume an event loop exists.
In Zig, how would something like this be accomplished (assuming led_on and led_off aren't operations natively supported by the IO interface?)
> How does downstream code know which kind of asynchrony is requested / allowed?
Certainly not from the function signatures, so documentation is the only way.
Seems like properly-written downstream code would deadlock if given an IO implementation that does not support concurrency. If that's true, to me this looks like a bad IO abstraction.
> Seems like properly written downstream code would deadlock if given an IO implementation that does not support concurrency.
No, it would fail with error.ConcurrencyUnavailable. See example 10 from TFA.
More to the point, this implementation decouples asynchrony from concurrency. In GP's example of a microcontroller blinking an LED, there's no explicit requirement for concurrency, only asynchrony. That is, it would be nice to be able to do other things while we wait for the LED controller to potentially time out, but it does not fundamentally change the application logic if the program blocks until the function completes. If you use io.async to run the call, then it will do exactly that: run other code while waiting for the controller if a concurrent Io implementation is passed, and block until the controller returns if a synchronous Io implementation is passed.
Functions that require concurrency would, however, need to be documented. Several people have proposed adding a feature like Rust traits or C++ concepts to Zig that would enable you to annotate type signatures to indicate which features need to be available for a generic substitution to succeed, but until such a thing exists, you're pretty much best off reading the source itself. In practice, most code probably doesn't require concurrency, and library authors are free to sprinkle asynchrony everywhere without worrying about whether or not their users' Io implementation will actually support concurrency.