Runtimes, Wakers, and the Reactor-Executor Pattern 170 An example of yielding to the OS scheduler is making a blocking call using the default std::net ::Tcp Stream or std::thread::sleep methods. Even potentially blocking calls using primitives such as Mutex provided by the standard library might yield to the OS scheduler. That's why you'll often find that asynchronous programming tends to color everything it touches, and it's tough to only run a part of your program using async/await. The consequence is that runtimes must use a non-blocking version of the standard library. In theory, you could make one non-blocking version of the standard library that all runtimes use, and that was one of the goals of the async_std initiative (https://book. async. rs/introduction ). However, having the community agree upon one way to solve this task was a tall order and one that hasn't really come to fruition yet. Before we start implementing our examples, we'll discuss the overall design of a typical async runtime in Rust. Most runtimes such as Tokio, Smol, or async-std will divide their runtime into two parts. The part that tracks events we're waiting on and makes sure to wait on notifications from the OS in an efficient manner is often called the reactor or driver. The part that schedules tasks and polls them to completion is called the executor. Let's take a high-level look at this design so that we know what we'll be implementing in our example. Reactors and executors Dividing the runtime into two distinct parts makes a lot of sense when we take a look at how Rust models asynchronous tasks. If you read the documentation for Future (https://doc. rust-lang. org/std/future/trait. Future. html ) and Waker (https://doc. rust-lang. org/std/task/struct. Waker. html ), you'll see that Rust doesn't only define a Future trait and a Waker type but also comes with important information on how they're supposed to be used. One example of this is that Future traits are inert, as we covered in Chapter 6. Another example is that a call to Waker::wake will guarantee at least one call to Future::poll on the corresponding task. So, already by reading the documentation, you will see that there is at least some thought put into how runtimes should behave. The reason for learning this pattern is that it's almost a glove-to-hand fit for Rust's asynchronous model. Since many readers, including me, will not have English as a first language, I'll explain the names here at the start since, well, they seem to be easy to misunderstand. If the name reactor gives you associations with nuclear reactors, and you start thinking of reactors as something that powers, or drives, a runtime, drop that thought right now. A reactor is simply something that reacts to a whole set of incoming events and dispatches them one by one to a handler. It's an event loop, and in our case, it dispatches events to an executor. Events that are handled by a reactor could 