Challenges with asynchronous Rust 267 Tasks We've used the terms tasks and futures without making the difference explicitly clear, so let's clear that up here. We first covered tasks in Chapter 1, and they still retain the same general meaning, but when talking about runtimes in Rust, they have a more specific definition. A task is a top-level future, the one that we spawn onto our executor. The executor schedules between different tasks. Tasks in a runtime in many ways represent the same abstraction that threads do in an OS. Every task is a future in Rust, but every future is not a task by this definition. Y ou can think of thread::sleep as a timer, and we often need something like this in an asynchronous context, so our asynchronous runtime will therefore need to have a sleep equivalent that tells the executor to park this task for a specified duration. We could implement this as a reactor and have separate OS-thread sleep for a specified duration and then wake the correct Waker. That would be simple and executor agnostic since the executor is oblivious to what happens and only concern itself with scheduling the task when Waker::wake is called. However, it's also not optimally efficient for all workloads (even if we used the same thread for all timers). Another, and more common, way to solve this is to delegate this task to the executor. In our runtime, this could be done by having the executor store an ordered list of instants and a corresponding Waker, which is used to determine whether any timers have expired before it calls thread::park. If none have expired, we can calculate the duration until the next timer expires and use something such as thread::park_timeout to make sure that we at least wake up to handle that timer. The algorithms used to store the timers can be heavily optimized and you avoid the need for one extra thread just for timers with the additional overhead of synchronization between these threads just to signal that a timer has expired. In a multithreaded runtime, there might even be contention when multiple executors frequently add timers to the same reactor. Some timers are implemented reactor-style as separate libraries, and for many tasks, that will suffice. The important point here is that by using the defaults, you end up being tied to one specific runtime, and you have to make careful considerations if you want to avoid your library being tightly coupled to a specific runtime. Common traits that everyone agrees about The last topic that causes friction in async Rust is the lack of universally agreed-upon traits and interfaces for typical async operations. I want to preface this segment by pointing out that this is one area that's improving day by day, and there is a nursery for the traits and abstractions for asynchronous Rust in the futures-rs crate (https://github. com/rust-lang/futures-rs ). However, since it's still early days for async Rust, it's something worth mentioning in a book like this.