-
Notifications
You must be signed in to change notification settings - Fork 13
Async and Future basics
When I started to write my Future implementation, I found that the official document is not clear about some basic rules. I created an issue in the official Rust repo https://github.com/rust-lang/rust/issues/73002. Although my problems are still not getting a clear answer. I hereby summarize some rules we should follow:
-
Waker is a token to register events to your event manager (timer, io poller, or synchronize counterpart), most likely a heap structure. What's inside and the relationship to RawWaker, the document is not clear enough, you can ignore the details if not trying to implement an async runtime.
-
Before your Future goes to sleep, you register a weaker. And your counterpart may set the condition. These two operations may happen at the same time. If you decide to go the lockless way, you should check the condition twice before and after registering the Waker; otherwise, you will get a deadlock. (The counterpart might not see the Waker).
-
If a Future's poll() returns Ready() before the Waker gets woken. It's an OK and common behavior.
-
Once Waker is woken by some event, the async runtime will guarantee that poll() will be triggered eventually.
-
If your Future is woken and the condition is ready, you miss it because of forgetting to check, your Future will not be woken again. This will incur a deadlock.
-
On Poll::Ready returns, Future will not be called again, and will be dropped.
-
On Future being aborted (things like futures abortable or tokio::time::timeout), the future will be dropped.
-
So that inside Drop, no matter after ready or aborted, you should clean up some resources.
-
When you use Timeout to wrap a Future, I think timeout or ready checking on the poller side is sequential. So it's possible to ensure your message is not lost due to a timeout occurring. Most async channel implementations do not specify this behavior.
-
Whether or not the same Waker can be registered and
wake()twice, the behavior is not specified by the async runtime, nor by the official document. I observe that the memory address of Wakers created by the same Future is the same. But you should not rely on this unspecified behavior.