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, Waker
s, RawWakerVTable
s,
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.