Implementing Rust Async and Futures from Scratch

As is tradition for many developers stuck at the family home over xmas. I decided to go hack something.

Asynchronous programming is becoming more popular in all major languages. C++20 is going to get co_await and friends, python 3.7 now has async, and Rust has async / .await. Rust’s implementation of Future<T> is quite unique. It uses a “polling”-based interface, where the listener “polls” for updates but–and this is why I am making judicious use of quotation marks–polling only occurs when the asynchronous event source “wakes” the poller, so polling only actually happens when a state change occurs, rather than continuously.

This pattern can be used to decouple the waiter from the event source (if necessary) which is important for a high-perf language with strict threading logic like Rust. By contrast, almost all other implementations I’ve seen in the wild tend to use callbacks (e.g. .then() in javascript), which is easier to implement but can make it difficult to figure out which thread executes the callback and how backpressure should be handled.

This polling design can make implementing async Rust from scratch (as in, without using something like tokio to do it for you) quite complicated. There’s Future<T>s, Wakers, RawWakerVTables, etc. etc. to have to implement, and these would be fairly easy to implement in a GCed language, but Rust also requires that the implementations are suitably safe, which typically requires a little unsafe code. I implemented an async system with the help of this book (high-level overview) and the source code for futures and tokio. The experience was eye-opening, but much more complicated than expected.

github link