I'm looking into some more complex Rust projects and I noticed that a lot of them instead of using only async functions implement Future
manually to get greater control of what happens.
The problem is that in the entire project, there is no call to waker.wake()
whatsoever, so I have no idea how they make sure the future is polled again.
Let's say I want to poll an endless Future
that always returns Poll::Pending
but without calling waker.wake()
. What are the other options?
Also, any resources on this topic and async rust are appreciated.
Thanks!
Using the Waker
provided by the Context
is the only way (in general) for a Future
implementation to communicate to its executor - which is to indicate that the task associated with that waker should be polled again such that progress can be made.
Making use of the Waker
yourself is not very common since it can only be used effectively by Future
s that have a out-of-band method to know that a value or signal being waited on is ready. This is usually restricted to low-level I/O operations, timers, other triggers from the OS, and notifications from other tasks or threads. If you are making your own Future
that relies on other Future
s, you won't use the waker yourself and simply pass the context when polling the inner Future
.
When you use an async
block or function, the state-machine type that is built by the compiler will implement Future
with a poll
function that defers to the current Future
being .await
-ed by simply passing the context. So its only the lowest, deepest Future
that would actually use the waker.
That all being said, there are no guarantees. Your Future
may be poll
-ed without calling the waker; this can happen if your task is using something like select!
elsewhere which is managing multiple Future
s in the same task. You may also call .wake()
on your waker but the executor is totally free to ignore it, or it may be stuck, or shutting down, or whatever else. In the most likely case, things will work as you'd expect but edge cases always exist.
This section of the Asynchronous Programming in Rust looks relevant: Under the Hood: Executing Futures and Tasks. If you are looking for a non-runtime specific implementation that uses the waker (since those may be very complicated underneath), you can look at futures::channel::oneshot::Sender
.
As a side note, a Future
that always returns Poll::Pending
is already in the standard library - std::future::pending
- but of course, it doesn't call the waker (since why would it if it is only always going to be pending?).