bbqueue
bbqueue copied to clipboard
Feat/async support
Initial draft for async support. Just want your input before continuing/cleaning up. My experience with async is pretty limited so feedback and comments are more than welcomed!
I diverted a bit from the previous work API since I wanted to keep the flexibility. This async api is as close as possible to the sync one.
Status:
- [x] Basic implementation
- [x] Basic tests
- [x] Add Frame flavor implementation
- [x] Cancellation tests
- [x] Test on MSRV, gate behind feature if necessary
- [x] Complete API documentation
This looks really useful, thanks! I'm going to try it in some network code and see how it works out.
Thanks @jeff-hiner! I continued developing the fork a bit since the PR, there are probably some fixes missing in this PR versus the fork. You can check it out here. Also note that the fork abstracted on the source of the storage since I wanted to provide the buffer myself.
I spoke to James some time ago and he won't merge the PR for now but we left it as reference for other users.
Since I am using it for internal project, I did not take the time to publish as a separate crate, but if there is some traction, I could publish a crate of the fork until the upstream gets async support if I have the time to update the doc.
Just curious, could you elaborate on why you choose to leverage the waker? To my understanding, the executor will eventually poll the task anyway, so it shouldn't be a big issue. Specially given that the comparison of some atomic values is so fast. Using the waker leads to increased complexity on the codebase. Do you fear task starvation from the scheduler?
Just curious, could you elaborate on why you choose to leverage the waker? To my understanding, the executor will eventually poll the task anyway, so it shouldn't be a big issue. Specially given that the comparison of some atomic values is so fast. Using the waker leads to increased complexity on the codebase. Do you fear task starvation from the scheduler?
Sure! The thing is that most executor won't poll again unless the task is awoken, thus you need the waker. Without a waker, the executor would need to poll every task. So unless you use an executor that does a busy polling loop, the executor will not poll the task again like you mentionned.
For example, embassy puts the MCU in a low power state when all tasks are pending and wait for an interrupt. Needing to loop while polling would make this impossible.
You can learn more about the inner workings of async here
Just FYI, I've been using a fork of some of @xgroleau 's work for implementing a completion-based i/o model with async. I did run into some deadlock issues with the custom waker, so I patched in futures::task::AtomicWaker
and replaced a bunch of NonNull and raw pointers with normal refs (which removed a bunch of unsafe). I don't know exactly what fixed the issue, and I need to break the fixes out into smaller PRs, but it's been running a while in production with no issues. Here's the branch if you want to experiment with it or incorporate any of the changes into your own fork.
https://github.com/jeff-hiner/bbqueue/tree/xgroleau-async
The thing is that most executor won't poll again unless the task is awoken,
Hm i didn't knew that! Thanks.
And thanks Jeff too! I definitely will give it a try.