Improving our base example 171 be anything from a timer that expires, an interrupt if you write programs for embedded systems, or an I/O event such as a READABLE event on Tcp Stream. Y ou could have several kinds of reactors running in the same runtime. If the name executor gives you associations to executioners (the medieval times kind) or executables, drop that thought as well. If you look up what an executor is, it's a person, often a lawyer, who administers a person's will. Most often, since that person is dead. Which is also the point where whatever mental model the naming suggests to you falls apart since nothing, and no one, needs to come in harm's way for the executor to have work to do in an asynchronous runtime, but I digress. The important point is that an executor simply decides who gets time on the CPU to progress and when they get it. The executor must also call Future::poll and advance the state machines to their next state. It's a type of scheduler. It can be frustrating to get the wrong idea from the start since the subject matter is already complex enough without thinking about how on earth nuclear reactors and executioners fit in the whole picture. Since reactors will respond to events, they need some integration with the source of the event. If we continue using Tcp Stream as an example, something will call read or write on it, and at that point, the reactor needs to know that it should track certain events on that source. For this reason, non-blocking I/O primitives and reactors need tight integration, and depending on how you look at it, the I/O primitives will either have to bring their own reactor or you'll have a reactor that provides I/O primitives such as sockets, ports, and streams. Now that we've covered some of the overarching design, we can start writing some code. Runtimes tend to get complex pretty quickly, so to keep this as simple as possible, we'll avoid any error handling in our code and use unwrap or expect for everything. We'll also choose simplicity over cleverness and readability over efficiency to the best of our abilities. Our first task will be to take the first example we wrote in Chapter 7 and improve it by avoiding having to actively poll it to make progress. Instead, we lean on what we learned about non-blocking I/O and epoll in the earlier chapters. Improving our base example We'll create a version of the first example in Chapter 7 since it's the simplest one to start with. Our only focus is showing how to schedule and drive the runtimes more efficiently. We start with the following steps: 1. Create a new project and name it a-runtime (alternatively, navigate to ch08/a-runtime in the book's repository).