rust-embedded / nb

Minimal and reusable non-blocking I/O layer
Apache License 2.0
88 stars 15 forks source link

Documentation: Point to non-blocking executors #37

Open chrysn opened 3 years ago

chrysn commented 3 years ago

While the documentation lists that blocking (busy wait, block!) and in asynchronous operation, there are no examples for the latter, and the link into the futures documentation is semantically broken (the link works, but it mentions NotReady which is not to be found there any more).

If there still is a roadmap towards how nb can be used in an asynchronous fashion that does not contain an always-spinning busy main loop, it would be helpful to have a pointer there in the documentation -- especially now that libraries like embedded-nal (where, unlike in embedded-hal where busy-looping-until-ADC-is-done is kind of OK, busy-looping is a no-go in many applications) start building on this, and have all their examples with block! as well.

If there is no way forward towards having a real executor underlying nb (which I'm leaning towards suspecting is the case, for even on an interrupt based system, how would the executor tell whether tasks are still making progress or everyone is waiting for an interrupt?), it would be good to document that (and possibly to document how nb users can migrate to full futures, or outline when which of them is preferable).

chrysn commented 3 years ago

It may be worth pointing out here that embedded-hal (which is probably the most prominent user of nb) is contemplating a move towards Rust's now-native async mechanisms at https://github.com/rust-embedded/embedded-hal/issues/172 -- if that is acted on, the issue at hand might become more of deprecation note of nb as a whole, provided I'm reading the situation correctly.

chrysn commented 3 years ago

The possibilities for such executors has also been part of a discussion at https://github.com/rust-embedded-community/embedded-nal/issues/47; my takeaway from there as far as this issue is concerned is that in std environments the non-blocking executor is usually something like loop { step(); sleep 50ms; }, and in embedded systems a loop { step(); asm::WFI(); } in the expectation that everything that returns WouldBlock sets up some interrupt to get the program running again, or is using block!() where it is known that an interrupt is not done or makes no sense timing-wise.