The Rust Programming Language › Our First Async Program › Defining the page_title Function

Let’s start by writing a function that takes one page URL as a parameter, makes
a request to it, and returns the text of the `<title>` element (see Listing
17-1).
Listing 17-1: Defining an async function to get the title element from an HTML page (src/main.rs)
```rust
use trpl::Html;

async fn page_title(url: &str) -> Option<String> {
    let response = trpl::get(url).await;
    let response_text = response.text().await;
    Html::parse(&response_text)
        .select_first("title")
        .map(|title| title.inner_html())
}
```
First, we define a function named `page_title` and mark it with the `async`
keyword. Then we use the `trpl::get` function to fetch whatever URL is passed
in and add the `await` keyword to await the response. To get the text of the
`response`, we call its `text` method and once again await it with the `await`
keyword. Both of these steps are asynchronous. For the `get` function, we have
to wait for the server to send back the first part of its response, which will
include HTTP headers, cookies, and so on and can be delivered separately from
the response body. Especially if the body is very large, it can take some time
for it all to arrive. Because we have to wait for the _entirety_ of the
response to arrive, the `text` method is also async.

Our First Async Program
Defining the page_title Function


The Rust Programming Language › Our First Async Program › Defining the page_title Function

We have to explicitly await both of these futures, because futures in Rust are
_lazy_: they don’t do anything until you ask them to with the `await` keyword.
(In fact, Rust will show a compiler warning if you don’t use a future.) This
might remind you of the discussion of iterators in the “Processing a Series of
Items with Iterators” section in Chapter 13.
Iterators do nothing unless you call their `next` method—whether directly or by
using `for` loops or methods such as `map` that use `next` under the hood.
Likewise, futures do nothing unless you explicitly ask them to. This laziness
allows Rust to avoid running async code until it’s actually needed.
Note: This is different from the behavior we saw when using `thread::spawn`
in the “Creating a New Thread with spawn”
section in Chapter 16, where the closure we passed to another thread started
running immediately. It’s also different from how many other languages
approach async. But it’s important for Rust to be able to provide its
performance guarantees, just as it is with iterators.


The Rust Programming Language › Our First Async Program › Defining the page_title Function

Once we have `response_text`, we can parse it into an instance of the `Html`
type using `Html::parse`. Instead of a raw string, we now have a data type we
can use to work with the HTML as a richer data structure. In particular, we can
use the `select_first` method to find the first instance of a given CSS
selector. By passing the string `"title"`, we’ll get the first `<title>`
element in the document, if there is one. Because there may not be any matching
element, `select_first` returns an `Option<ElementRef>`. Finally, we use the
`Option::map` method, which lets us work with the item in the `Option` if it’s
present, and do nothing if it isn’t. (We could also use a `match` expression
here, but `map` is more idiomatic.) In the body of the function we supply to
`map`, we call `inner_html` on the `title` to get its content, which is a
`String`. When all is said and done, we have an `Option<String>`.
Notice that Rust’s `await` keyword goes _after_ the expression you’re awaiting,
not before it. That is, it’s a _postfix_ keyword. This may differ from what
you’re used to if you’ve used `async` in other languages, but in Rust it makes
chains of methods much nicer to work with. As a result, we could change the
body of `page_title` to chain the `trpl::get` and `text` function calls
together with `await` between them, as shown in Listing 17-2.
Listing 17-2: Chaining with the `await` keyword (src/main.rs)
```rust
    let response_text = trpl::get(url).await.text().await;
```


The Rust Programming Language › Our First Async Program › Defining the page_title Function

With that, we have successfully written our first async function! Before we add
some code in `main` to call it, let’s talk a little more about what we’ve
written and what it means.
When Rust sees a _block_ marked with the `async` keyword, it compiles it into a
unique, anonymous data type that implements the `Future` trait. When Rust sees
a _function_ marked with `async`, it compiles it into a non-async function
whose body is an async block. An async function’s return type is the type of
the anonymous data type the compiler creates for that async block.
Thus, writing `async fn` is equivalent to writing a function that returns a
_future_ of the return type. To the compiler, a function definition such as the
`async fn page_title` in Listing 17-1 is roughly equivalent to a non-async
function defined like this:
```rust
use std::future::Future;
use trpl::Html;

fn page_title(url: &str) -> impl Future<Output = Option<String>> {
    async move {
        let text = trpl::get(url).await.text().await;
        Html::parse(&text)
            .select_first("title")
            .map(|title| title.inner_html())
    }
}
```
Let’s walk through each part of the transformed version:


The Rust Programming Language › Our First Async Program › Defining the page_title Function

- It uses the `impl Trait` syntax we discussed back in Chapter 10 in the
  “Traits as Parameters” section.
- The returned value implements the `Future` trait with an associated type of
  `Output`. Notice that the `Output` type is `Option<String>`, which is the
  same as the original return type from the `async fn` version of `page_title`.
- All of the code called in the body of the original function is wrapped in
  an `async move` block. Remember that blocks are expressions. This whole block
  is the expression returned from the function.
- This async block produces a value with the type `Option<String>`, as just
  described. That value matches the `Output` type in the return type. This is
  just like other blocks you have seen.
- The new function body is an `async move` block because of how it uses the
  `url` parameter. (We’ll talk much more about `async` versus `async move`
  later in the chapter.)
Now we can call `page_title` in `main`.


The Rust Programming Language › Our First Async Program › Executing an Async Function with a Runtime

To start, we’ll get the title for a single page, shown in Listing 17-3.
Unfortunately, this code doesn’t compile yet.
Listing 17-3: Calling the `page_title` function from `main` with a user-supplied argument (src/main.rs)
```rust,ignore,does_not_compile
async fn main() {
    let args: Vec<String> = std::env::args().collect();
    let url = &args[1];
    match page_title(url).await {
        Some(title) => println!("The title for {url} was {title}"),
        None => println!("{url} had no title"),
    }
}
```
We follow the same pattern we used to get command line arguments in the
“Accepting Command Line Arguments” section in
Chapter 12. Then we pass the URL argument to `page_title` and await the result.
Because the value produced by the future is an `Option<String>`, we use a
`match` expression to print different messages to account for whether the page
had a `<title>`.
The only place we can use the `await` keyword is in async functions or blocks,
and Rust won’t let us mark the special `main` function as `async`.
```text
error[E0752]: `main` function is not allowed to be `async`
 --> src/main.rs:6:1
  |
6 | async fn main() {
  | ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`
```


The Rust Programming Language › Our First Async Program › Executing an Async Function with a Runtime

The reason `main` can’t be marked `async` is that async code needs a _runtime_:
a Rust crate that manages the details of executing asynchronous code. A
program’s `main` function can _initialize_ a runtime, but it’s not a runtime
_itself_. (We’ll see more about why this is the case in a bit.) Every Rust
program that executes async code has at least one place where it sets up a
runtime that executes the futures.
Most languages that support async bundle a runtime, but Rust does not. Instead,
there are many different async runtimes available, each of which makes different
tradeoffs suitable to the use case it targets. For example, a high-throughput
web server with many CPU cores and a large amount of RAM has very different
needs than a microcontroller with a single core, a small amount of RAM, and no
heap allocation ability. The crates that provide those runtimes also often
supply async versions of common functionality such as file or network I/O.
Here, and throughout the rest of this chapter, we’ll use the `block_on`
function from the `trpl` crate, which takes a future as an argument and blocks
the current thread until this future runs to completion. Behind the scenes,
calling `block_on` sets up a runtime using the `tokio` crate that’s used to run
the future passed in (the `trpl` crate’s `block_on` behavior is similar to
other runtime crates’ `block_on` functions). Once the future completes,
`block_on` returns whatever value the future produced.


The Rust Programming Language › Our First Async Program › Executing an Async Function with a Runtime

We could pass the future returned by `page_title` directly to `block_on` and,
once it completed, we could match on the resulting `Option<String>` as we tried
to do in Listing 17-3. However, for most of the examples in the chapter (and
most async code in the real world), we’ll be doing more than just one async
function call, so instead we’ll pass an `async` block and explicitly await the
result of the `page_title` call, as in Listing 17-4.
Listing 17-4: Awaiting an async block with `trpl::block_on` (src/main.rs)
```rust,should_panic,noplayground
fn main() {
    let args: Vec<String> = std::env::args().collect();

    trpl::block_on(async {
        let url = &args[1];
        match page_title(url).await {
            Some(title) => println!("The title for {url} was {title}"),
            None => println!("{url} had no title"),
        }
    })
}
```
When we run this code, we get the behavior we expected initially:
```console
$ cargo run -- "https://www.rust-lang.org"
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/async_await 'https://www.rust-lang.org'`
The title for https://www.rust-lang.org was
            Rust Programming Language
```
Phew—we finally have some working async code! But before we add the code to
race two sites against each other, let’s briefly turn our attention back to how
futures work.


The Rust Programming Language › Our First Async Program › Executing an Async Function with a Runtime

Each _await point_—that is, every place where the code uses the `await`
keyword—represents a place where control is handed back to the runtime. To make
that work, Rust needs to keep track of the state involved in the async block so
that the runtime could kick off some other work and then come back when it’s
ready to try advancing the first one again. This is an invisible state machine,
as if you’d written an enum like this to save the current state at each await
point:
```rust
enum PageTitleFuture<'a> {
    Initial { url: &'a str },
    GetAwaitPoint { url: &'a str },
    TextAwaitPoint { response: trpl::Response },
}
```
Writing the code to transition between each state by hand would be tedious and
error-prone, however, especially when you need to add more functionality and
more states to the code later. Fortunately, the Rust compiler creates and
manages the state machine data structures for async code automatically. The
normal borrowing and ownership rules around data structures all still apply,
and happily, the compiler also handles checking those for us and provides
useful error messages. We’ll work through a few of those later in the chapter.
Ultimately, something has to execute this state machine, and that something is
a runtime. (This is why you may come across mentions of _executors_ when
looking into runtimes: an executor is the part of a runtime responsible for
executing the async code.)


The Rust Programming Language › Our First Async Program › Executing an Async Function with a Runtime

Now you can see why the compiler stopped us from making `main` itself an async
function back in Listing 17-3. If `main` were an async function, something else
would need to manage the state machine for whatever future `main` returned, but
`main` is the starting point for the program! Instead, we called the
`trpl::block_on` function in `main` to set up a runtime and run the future
returned by the `async` block until it’s done.
Note: Some runtimes provide macros so you _can_ write an async `main`
function. Those macros rewrite `async fn main() { ... }` to be a normal `fn
main`, which does the same thing we did by hand in Listing 17-4: call a
function that runs a future to completion the way `trpl::block_on` does.
Now let’s put these pieces together and see how we can write concurrent code.


The Rust Programming Language › Our First Async Program › Racing Two URLs Against Each Other Concurrently

In Listing 17-5, we call `page_title` with two different URLs passed in from the
command line and race them by selecting whichever future finishes first.
Listing 17-5: Calling `page_title` for two URLs to see which returns first (src/main.rs)
```rust,should_panic,noplayground
use trpl::{Either, Html};

fn main() {
    let args: Vec<String> = std::env::args().collect();

    trpl::block_on(async {
        let title_fut_1 = page_title(&args[1]);
        let title_fut_2 = page_title(&args[2]);

        let (url, maybe_title) =
            match trpl::select(title_fut_1, title_fut_2).await {
                Either::Left(left) => left,
                Either::Right(right) => right,
            };

        println!("{url} returned first");
        match maybe_title {
            Some(title) => println!("Its page title was: '{title}'"),
            None => println!("It had no title."),
        }
    })
}

async fn page_title(url: &str) -> (&str, Option<String>) {
    let response_text = trpl::get(url).await.text().await;
    let title = Html::parse(&response_text)
        .select_first("title")
        .map(|title| title.inner_html());
    (url, title)
}
```
We begin by calling `page_title` for each of the user-supplied URLs. We save
the resulting futures as `title_fut_1` and `title_fut_2`. Remember, these don’t
do anything yet, because futures are lazy and we haven’t yet awaited them. Then
we pass the futures to `trpl::select`, which returns a value to indicate which
of the futures passed to it finishes first.


The Rust Programming Language › Our First Async Program › Racing Two URLs Against Each Other Concurrently

Note: Under the hood, `trpl::select` is built on a more general `select`
function defined in the `futures` crate. The `futures` crate’s `select`
function can do a lot of things that the `trpl::select` function can’t, but
it also has some additional complexity that we can skip over for now.
Either future can legitimately “win,” so it doesn’t make sense to return a
`Result`. Instead, `trpl::select` returns a type we haven’t seen before,
`trpl::Either`. The `Either` type is somewhat similar to a `Result` in that it
has two cases. Unlike `Result`, though, there is no notion of success or
failure baked into `Either`. Instead, it uses `Left` and `Right` to indicate
“one or the other”:
```rust
enum Either<A, B> {
    Left(A),
    Right(B),
}
```
The `select` function returns `Left` with that future’s output if the first
argument wins, and `Right` with the second future argument’s output if _that_
one wins. This matches the order the arguments appear in when calling the
function: the first argument is to the left of the second argument.
We also update `page_title` to return the same URL passed in. That way, if the
page that returns first does not have a `<title>` we can resolve, we can still
print a meaningful message. With that information available, we wrap up by
updating our `println!` output to indicate both which URL finished first and
what, if any, the `<title>` is for the web page at that URL.


The Rust Programming Language › Our First Async Program › Racing Two URLs Against Each Other Concurrently

You have built a small working web scraper now! Pick a couple URLs and run the
command line tool. You may discover that some sites are consistently faster
than others, while in other cases the faster site varies from run to run. More
importantly, you’ve learned the basics of working with futures, so now we can
dig deeper into what we can do with async.


The Rust Programming Language › Applying Concurrency with Async

In this section, we’ll apply async to some of the same concurrency challenges
we tackled with threads in Chapter 16. Because we already talked about a lot of
the key ideas there, in this section we’ll focus on what’s different between
threads and futures.
In many cases, the APIs for working with concurrency using async are very
similar to those for using threads. In other cases, they end up being quite
different. Even when the APIs _look_ similar between threads and async, they
often have different behavior—and they nearly always have different performance
characteristics.


The Rust Programming Language › Applying Concurrency with Async › Creating a New Task with `spawn_task`

The first operation we tackled in the “Creating a New Thread with
`spawn`” section in Chapter 16 was counting up on
two separate threads. Let’s do the same using async. The `trpl` crate supplies
a `spawn_task` function that looks very similar to the `thread::spawn` API, and
a `sleep` function that is an async version of the `thread::sleep` API. We can
use these together to implement the counting example, as shown in Listing 17-6.
Listing 17-6: Creating a new task to print one thing while the main task prints something else (src/main.rs)
```rust
use std::time::Duration;

fn main() {
    trpl::block_on(async {
        trpl::spawn_task(async {
            for i in 1..10 {
                println!("hi number {i} from the first task!");
                trpl::sleep(Duration::from_millis(500)).await;
            }
        });

        for i in 1..5 {
            println!("hi number {i} from the second task!");
            trpl::sleep(Duration::from_millis(500)).await;
        }
    });
}
```
As our starting point, we set up our `main` function with `trpl::block_on` so
that our top-level function can be async.
Note: From this point forward in the chapter, every example will include this
exact same wrapping code with `trpl::block_on` in `main`, so we’ll often skip it
just as we do with `main`. Remember to include it in your code!

Applying Concurrency with Async
Creating a New Task with `spawn_task`


The Rust Programming Language › Applying Concurrency with Async › Creating a New Task with `spawn_task`

Then we write two loops within that block, each containing a `trpl::sleep`
call, which waits for half a second (500 milliseconds) before sending the next
message. We put one loop in the body of a `trpl::spawn_task` and the other in a
top-level `for` loop. We also add an `await` after the `sleep` calls.
This code behaves similarly to the thread-based implementation—including the
fact that you may see the messages appear in a different order in your own
terminal when you run it:
```text
hi number 1 from the second task!
hi number 1 from the first task!
hi number 2 from the first task!
hi number 2 from the second task!
hi number 3 from the first task!
hi number 3 from the second task!
hi number 4 from the first task!
hi number 4 from the second task!
hi number 5 from the first task!
```
This version stops as soon as the `for` loop in the body of the main async
block finishes, because the task spawned by `spawn_task` is shut down when the
`main` function ends. If you want it to run all the way to the task’s
completion, you will need to use a join handle to wait for the first task to
complete. With threads, we used the `join` method to “block” until the thread
was done running. In Listing 17-7, we can use `await` to do the same thing,
because the task handle itself is a future. Its `Output` type is a `Result`, so
we also unwrap it after awaiting it.
Listing 17-7: Using `await` with a join handle to run a task to completion (src/main.rs)


The Rust Programming Language › Applying Concurrency with Async › Creating a New Task with `spawn_task`

```rust
        let handle = trpl::spawn_task(async {
            for i in 1..10 {
                println!("hi number {i} from the first task!");
                trpl::sleep(Duration::from_millis(500)).await;
            }
        });

        for i in 1..5 {
            println!("hi number {i} from the second task!");
            trpl::sleep(Duration::from_millis(500)).await;
        }

        handle.await.unwrap();
```
This updated version runs until _both_ loops finish:
```text
hi number 1 from the second task!
hi number 1 from the first task!
hi number 2 from the first task!
hi number 2 from the second task!
hi number 3 from the first task!
hi number 3 from the second task!
hi number 4 from the first task!
hi number 4 from the second task!
hi number 5 from the first task!
hi number 6 from the first task!
hi number 7 from the first task!
hi number 8 from the first task!
hi number 9 from the first task!
```
So far, it looks like async and threads give us similar outcomes, just with
different syntax: using `await` instead of calling `join` on the join handle,
and awaiting the `sleep` calls.
The bigger difference is that we didn’t need to spawn another operating system
thread to do this. In fact, we don’t even need to spawn a task here. Because
async blocks compile to anonymous futures, we can put each loop in an async
block and have the runtime run them both to completion using the `trpl::join`
function.


The Rust Programming Language › Applying Concurrency with Async › Creating a New Task with `spawn_task`

In the “Waiting for All Threads to Finish”
section in Chapter 16, we showed how to use the `join` method on the
`JoinHandle` type returned when you call `std::thread::spawn`. The `trpl::join`
function is similar, but for futures. When you give it two futures, it produces
a single new future whose output is a tuple containing the output of each
future you passed in once they _both_ complete. Thus, in Listing 17-8, we use
`trpl::join` to wait for both `fut1` and `fut2` to finish. We do _not_ await
`fut1` and `fut2` but instead the new future produced by `trpl::join`. We
ignore the output, because it’s just a tuple containing two unit values.
Listing 17-8: Using `trpl::join` to await two anonymous futures (src/main.rs)
```rust
        let fut1 = async {
            for i in 1..10 {
                println!("hi number {i} from the first task!");
                trpl::sleep(Duration::from_millis(500)).await;
            }
        };

        let fut2 = async {
            for i in 1..5 {
                println!("hi number {i} from the second task!");
                trpl::sleep(Duration::from_millis(500)).await;
            }
        };

        trpl::join(fut1, fut2).await;
```
When we run this, we see both futures run to completion:


The Rust Programming Language › Applying Concurrency with Async › Creating a New Task with `spawn_task`

```text
hi number 1 from the first task!
hi number 1 from the second task!
hi number 2 from the first task!
hi number 2 from the second task!
hi number 3 from the first task!
hi number 3 from the second task!
hi number 4 from the first task!
hi number 4 from the second task!
hi number 5 from the first task!
hi number 6 from the first task!
hi number 7 from the first task!
hi number 8 from the first task!
hi number 9 from the first task!
```
Now, you’ll see the exact same order every time, which is very different from
what we saw with threads and with `trpl::spawn_task` in Listing 17-7. That is
because the `trpl::join` function is _fair_, meaning it checks each future
equally often, alternating between them, and never lets one race ahead if the
other is ready. With threads, the operating system decides which thread to
check and how long to let it run. With async Rust, the runtime decides which
task to check. (In practice, the details get complicated because an async
runtime might use operating system threads under the hood as part of how it
manages concurrency, so guaranteeing fairness can be more work for a
runtime—but it’s still possible!) Runtimes don’t have to guarantee fairness for
any given operation, and they often offer different APIs to let you choose
whether or not you want fairness.
Try some of these variations on awaiting the futures and see what they do:
- Remove the async block from around either or both of the loops.
- Await each async block immediately after defining it.
- Wrap only the first loop in an async block, and await the resulting future
  after the body of second loop.
For an extra challenge, see if you can figure out what the output will be in
each case _before_ running the code!


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing

Sharing data between futures will also be familiar: we’ll use message passing
again, but this time with async versions of the types and functions. We’ll take
a slightly different path than we did in the “Transfer Data Between Threads
with Message Passing” section in
Chapter 16 to illustrate some of the key differences between thread-based and
futures-based concurrency. In Listing 17-9, we’ll begin with just a single
async block—_not_ spawning a separate task as we spawned a separate thread.
Listing 17-9: Creating an async channel and assigning the two halves to `tx` and `rx` (src/main.rs)
```rust
        let (tx, mut rx) = trpl::channel();

        let val = String::from("hi");
        tx.send(val).unwrap();

        let received = rx.recv().await.unwrap();
        println!("received '{received}'");
```
Here, we use `trpl::channel`, an async version of the multiple-producer,
single-consumer channel API we used with threads back in Chapter 16. The async
version of the API is only a little different from the thread-based version: it
uses a mutable rather than an immutable receiver `rx`, and its `recv` method
produces a future we need to await rather than producing the value directly.
Now we can send messages from the sender to the receiver. Notice that we don’t
have to spawn a separate thread or even a task; we merely need to await the
`rx.recv` call.


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing

The synchronous `Receiver::recv` method in `std::mpsc::channel` blocks until it
receives a message. The `trpl::Receiver::recv` method does not, because it is
async. Instead of blocking, it hands control back to the runtime until either a
message is received or the send side of the channel closes. By contrast, we
don’t await the `send` call, because it doesn’t block. It doesn’t need to,
because the channel we’re sending it into is unbounded.
Note: Because all of this async code runs in an async block in a
`trpl::block_on` call, everything within it can avoid blocking. However, the
code _outside_ it will block on the `block_on` function returning. That’s the
whole point of the `trpl::block_on` function: it lets you _choose_ where to
block on some set of async code, and thus where to transition between sync
and async code.
Notice two things about this example. First, the message will arrive right
away. Second, although we use a future here, there’s no concurrency yet.
Everything in the listing happens in sequence, just as it would if there were
no futures involved.
Let’s address the first part by sending a series of messages and sleeping in
between them, as shown in Listing 17-10.
Listing 17-10: Sending and receiving multiple messages over the async channel and sleeping with an `await` between each message (src/main.rs)


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing

```rust,ignore
        let (tx, mut rx) = trpl::channel();

        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("future"),
        ];

        for val in vals {
            tx.send(val).unwrap();
            trpl::sleep(Duration::from_millis(500)).await;
        }

        while let Some(value) = rx.recv().await {
            println!("received '{value}'");
        }
```
In addition to sending the messages, we need to receive them. In this case,
because we know how many messages are coming in, we could do that manually by
calling `rx.recv().await` four times. In the real world, though, we’ll generally
be waiting on some _unknown_ number of messages, so we need to keep waiting
until we determine that there are no more messages.
In Listing 16-10, we used a `for` loop to process all the items received from a
synchronous channel. Rust doesn’t yet have a way to use a `for` loop with an
_asynchronously produced_ series of items, however, so we need to use a loop we
haven’t seen before: the `while let` conditional loop. This is the loop version
of the `if let` construct we saw back in the “Concise Control Flow with `if
let` and `let...else`” section in Chapter 6. The loop
will continue executing as long as the pattern it specifies continues to match
the value.


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing › Code Within One Async Block Executes Linearly

The `rx.recv` call produces a future, which we await. The runtime will pause
the future until it is ready. Once a message arrives, the future will resolve
to `Some(message)` as many times as a message arrives. When the channel closes,
regardless of whether _any_ messages have arrived, the future will instead
resolve to `None` to indicate that there are no more values and thus we should
stop polling—that is, stop awaiting.
The `while let` loop pulls all of this together. If the result of calling
`rx.recv().await` is `Some(message)`, we get access to the message and we can
use it in the loop body, just as we could with `if let`. If the result is
`None`, the loop ends. Every time the loop completes, it hits the await point
again, so the runtime pauses it again until another message arrives.
The code now successfully sends and receives all of the messages.
Unfortunately, there are still a couple of problems. For one thing, the
messages do not arrive at half-second intervals. They arrive all at once, 2
seconds (2,000 milliseconds) after we start the program. For another, this
program also never exits! Instead, it waits forever for new messages. You will
need to shut it down using ctrl-C.
Let’s start by examining why the messages come in all at once after the full
delay, rather than coming in with delays between each one. Within a given async
block, the order in which `await` keywords appear in the code is also the order
in which they’re executed when the program runs.


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing › Code Within One Async Block Executes Linearly

There’s only one async block in Listing 17-10, so everything in it runs
linearly. There’s still no concurrency. All the `tx.send` calls happen,
interspersed with all of the `trpl::sleep` calls and their associated await
points. Only then does the `while let` loop get to go through any of the
`await` points on the `recv` calls.
To get the behavior we want, where the sleep delay happens between each
message, we need to put the `tx` and `rx` operations in their own async blocks,
as shown in Listing 17-11. Then the runtime can execute each of them separately
using `trpl::join`, just as in Listing 17-8. Once again, we await the result of
calling `trpl::join`, not the individual futures. If we awaited the individual
futures in sequence, we would just end up back in a sequential flow—exactly
what we’re trying _not_ to do.
Listing 17-11: Separating `send` and `recv` into their own `async` blocks and awaiting the futures for those blocks (src/main.rs)
```rust,ignore
        let tx_fut = async {
            let vals = vec![
                String::from("hi"),
                String::from("from"),
                String::from("the"),
                String::from("future"),
            ];

            for val in vals {
                tx.send(val).unwrap();
                trpl::sleep(Duration::from_millis(500)).await;
            }
        };

        let rx_fut = async {
            while let Some(value) = rx.recv().await {
                println!("received '{value}'");
            }
        };

        trpl::join(tx_fut, rx_fut).await;
```


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing › Moving Ownership Into an Async Block

With the updated code in Listing 17-11, the messages get printed at
500-millisecond intervals, rather than all in a rush after 2 seconds.
The program still never exits, though, because of the way the `while let` loop
interacts with `trpl::join`:
- The future returned from `trpl::join` completes only once _both_ futures
  passed to it have completed.
- The `tx_fut` future completes once it finishes sleeping after sending the last
  message in `vals`.
- The `rx_fut` future won’t complete until the `while let` loop ends.
- The `while let` loop won’t end until awaiting `rx.recv` produces `None`.
- Awaiting `rx.recv` will return `None` only once the other end of the channel
  is closed.
- The channel will close only if we call `rx.close` or when the sender side,
  `tx`, is dropped.
- We don’t call `rx.close` anywhere, and `tx` won’t be dropped until the
  outermost async block passed to `trpl::block_on` ends.
- The block can’t end because it is blocked on `trpl::join` completing, which
  takes us back to the top of this list.


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing › Joining a Number of Futures with the `join!` Macro

Right now, the async block where we send the messages only _borrows_ `tx`
because sending a message doesn’t require ownership, but if we could _move_
`tx` into that async block, it would be dropped once that block ends. In the
“Capturing References or Moving Ownership”
section in Chapter 13, you learned how to use the `move` keyword with closures,
and, as discussed in the “Using `move` Closures with
Threads” section in Chapter 16, we often need to
move data into closures when working with threads. The same basic dynamics
apply to async blocks, so the `move` keyword works with async blocks just as it
does with closures.
In Listing 17-12, we change the block used to send messages from `async` to
`async move`.
Listing 17-12: A revision of the code from Listing 17-11 that correctly shuts down when complete (src/main.rs)
```rust
        let (tx, mut rx) = trpl::channel();

        let tx_fut = async move {
            // --snip--
```
When we run _this_ version of the code, it shuts down gracefully after the last
message is sent and received. Next, let’s see what would need to change to send
data from more than one future.
This async channel is also a multiple-producer channel, so we can call `clone`
on `tx` if we want to send messages from multiple futures, as shown in Listing
17-13.
Listing 17-13: Using multiple producers with async blocks (src/main.rs)


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing › Joining a Number of Futures with the `join!` Macro

```rust
        let (tx, mut rx) = trpl::channel();

        let tx1 = tx.clone();
        let tx1_fut = async move {
            let vals = vec![
                String::from("hi"),
                String::from("from"),
                String::from("the"),
                String::from("future"),
            ];

            for val in vals {
                tx1.send(val).unwrap();
                trpl::sleep(Duration::from_millis(500)).await;
            }
        };

        let rx_fut = async {
            while let Some(value) = rx.recv().await {
                println!("received '{value}'");
            }
        };

        let tx_fut = async move {
            let vals = vec![
                String::from("more"),
                String::from("messages"),
                String::from("for"),
                String::from("you"),
            ];

            for val in vals {
                tx.send(val).unwrap();
                trpl::sleep(Duration::from_millis(1500)).await;
            }
        };

        trpl::join!(tx1_fut, tx_fut, rx_fut);
```
First, we clone `tx`, creating `tx1` outside the first async block. We move
`tx1` into that block just as we did before with `tx`. Then, later, we move the
original `tx` into a _new_ async block, where we send more messages on a
slightly slower delay. We happen to put this new async block after the async
block for receiving messages, but it could go before it just as well. The key is
the order in which the futures are awaited, not in which they’re created.
Both of the async blocks for sending messages need to be `async move` blocks so
that both `tx` and `tx1` get dropped when those blocks finish. Otherwise, we’ll
end up back in the same infinite loop we started out in.


The Rust Programming Language › Applying Concurrency with Async › Sending Data Between Two Tasks Using Message Passing › Joining a Number of Futures with the `join!` Macro

Finally, we switch from `trpl::join` to `trpl::join!` to handle the additional
future: the `join!` macro awaits an arbitrary number of futures where we know
the number of futures at compile time. We’ll discuss awaiting a collection of
an unknown number of futures later in this chapter.
Now we see all the messages from both sending futures, and because the sending
futures use slightly different delays after sending, the messages are also
received at those different intervals:
```text
received 'hi'
received 'more'
received 'from'
received 'the'
received 'messages'
received 'future'
received 'for'
received 'you'
```
We’ve explored how to use message passing to send data between futures, how
code within an async block runs sequentially, how to move ownership into an
async block, and how to join multiple futures. Next, let’s discuss how and why
to tell the runtime it can switch to another task.


The Rust Programming Language › Yielding Control to the Runtime

Recall from the “Our First Async Program”
section that at each await point, Rust gives a runtime a chance to pause the
task and switch to another one if the future being awaited isn’t ready. The
inverse is also true: Rust _only_ pauses async blocks and hands control back to
a runtime at an await point. Everything between await points is synchronous.
That means if you do a bunch of work in an async block without an await point,
that future will block any other futures from making progress. You may sometimes
hear this referred to as one future _starving_ other futures. In some cases,
that may not be a big deal. However, if you are doing some kind of expensive
setup or long-running work, or if you have a future that will keep doing some
particular task indefinitely, you’ll need to think about when and where to hand
control back to the runtime.
Let’s simulate a long-running operation to illustrate the starvation problem,
then explore how to solve it. Listing 17-14 introduces a `slow` function.
Listing 17-14: Using `thread::sleep` to simulate slow operations (src/main.rs)
```rust
fn slow(name: &str, ms: u64) {
    thread::sleep(Duration::from_millis(ms));
    println!("'{name}' ran for {ms}ms");
}
```
This code uses `std::thread::sleep` instead of `trpl::sleep` so that calling
`slow` will block the current thread for some number of milliseconds. We can
use `slow` to stand in for real-world operations that are both long-running and
blocking.
In Listing 17-15, we use `slow` to emulate doing this kind of CPU-bound work in
a pair of futures.
Listing 17-15: Calling the `slow` function to simulate slow operations (src/main.rs)


The Rust Programming Language › Yielding Control to the Runtime

```rust
        let a = async {
            println!("'a' started.");
            slow("a", 30);
            slow("a", 10);
            slow("a", 20);
            trpl::sleep(Duration::from_millis(50)).await;
            println!("'a' finished.");
        };

        let b = async {
            println!("'b' started.");
            slow("b", 75);
            slow("b", 10);
            slow("b", 15);
            slow("b", 350);
            trpl::sleep(Duration::from_millis(50)).await;
            println!("'b' finished.");
        };

        trpl::select(a, b).await;
```
Each future hands control back to the runtime only _after_ carrying out a bunch
of slow operations. If you run this code, you will see this output:
```text
'a' started.
'a' ran for 30ms
'a' ran for 10ms
'a' ran for 20ms
'b' started.
'b' ran for 75ms
'b' ran for 10ms
'b' ran for 15ms
'b' ran for 350ms
'a' finished.
```


The Rust Programming Language › Yielding Control to the Runtime

As with Listing 17-5 where we used `trpl::select` to race futures fetching two
URLs, `select` still finishes as soon as `a` is done. There’s no interleaving
between the calls to `slow` in the two futures, though. The `a` future does all
of its work until the `trpl::sleep` call is awaited, then the `b` future does
all of its work until its own `trpl::sleep` call is awaited, and finally the
`a` future completes. To allow both futures to make progress between their slow
tasks, we need await points so we can hand control back to the runtime. That
means we need something we can await!
We can already see this kind of handoff happening in Listing 17-15: if we
removed the `trpl::sleep` at the end of the `a` future, it would complete
without the `b` future running _at all_. Let’s try using the `trpl::sleep`
function as a starting point for letting operations switch off making progress,
as shown in Listing 17-16.
Listing 17-16: Using `trpl::sleep` to let operations switch off making progress (src/main.rs)


The Rust Programming Language › Yielding Control to the Runtime

```rust
        let one_ms = Duration::from_millis(1);

        let a = async {
            println!("'a' started.");
            slow("a", 30);
            trpl::sleep(one_ms).await;
            slow("a", 10);
            trpl::sleep(one_ms).await;
            slow("a", 20);
            trpl::sleep(one_ms).await;
            println!("'a' finished.");
        };

        let b = async {
            println!("'b' started.");
            slow("b", 75);
            trpl::sleep(one_ms).await;
            slow("b", 10);
            trpl::sleep(one_ms).await;
            slow("b", 15);
            trpl::sleep(one_ms).await;
            slow("b", 350);
            trpl::sleep(one_ms).await;
            println!("'b' finished.");
        };
```
We’ve added `trpl::sleep` calls with await points between each call to `slow`.
Now the two futures’ work is interleaved:
```text
'a' started.
'a' ran for 30ms
'b' started.
'b' ran for 75ms
'a' ran for 10ms
'b' ran for 10ms
'a' ran for 20ms
'b' ran for 15ms
'a' finished.
```
The `a` future still runs for a bit before handing off control to `b`, because
it calls `slow` before ever calling `trpl::sleep`, but after that the futures
swap back and forth each time one of them hits an await point. In this case, we
have done that after every call to `slow`, but we could break up the work in
whatever way makes the most sense to us.


The Rust Programming Language › Yielding Control to the Runtime

We don’t really want to _sleep_ here, though: we want to make progress as fast
as we can. We just need to hand back control to the runtime. We can do that
directly, using the `trpl::yield_now` function. In Listing 17-17, we replace
all those `trpl::sleep` calls with `trpl::yield_now`.
Listing 17-17: Using `yield_now` to let operations switch off making progress (src/main.rs)
```rust
        let a = async {
            println!("'a' started.");
            slow("a", 30);
            trpl::yield_now().await;
            slow("a", 10);
            trpl::yield_now().await;
            slow("a", 20);
            trpl::yield_now().await;
            println!("'a' finished.");
        };

        let b = async {
            println!("'b' started.");
            slow("b", 75);
            trpl::yield_now().await;
            slow("b", 10);
            trpl::yield_now().await;
            slow("b", 15);
            trpl::yield_now().await;
            slow("b", 350);
            trpl::yield_now().await;
            println!("'b' finished.");
        };
```
This code is both clearer about the actual intent and can be significantly
faster than using `sleep`, because timers such as the one used by `sleep` often
have limits on how granular they can be. The version of `sleep` we are using,
for example, will always sleep for at least a millisecond, even if we pass it a
`Duration` of one nanosecond. Again, modern computers are _fast_: they can do a
lot in one millisecond!


The Rust Programming Language › Yielding Control to the Runtime

This means that async can be useful even for compute-bound tasks, depending on
what else your program is doing, because it provides a useful tool for
structuring the relationships between different parts of the program (but at a
cost of the overhead of the async state machine). This is a form of
_cooperative multitasking_, where each future has the power to determine when
it hands over control via await points. Each future therefore also has the
responsibility to avoid blocking for too long. In some Rust-based embedded
operating systems, this is the _only_ kind of multitasking!
In real-world code, you won’t usually be alternating function calls with await
points on every single line, of course. While yielding control in this way is
relatively inexpensive, it’s not free. In many cases, trying to break up a
compute-bound task might make it significantly slower, so sometimes it’s better
for _overall_ performance to let an operation block briefly. Always
measure to see what your code’s actual performance bottlenecks are. The
underlying dynamic is important to keep in mind, though, if you _are_ seeing a
lot of work happening in serial that you expected to happen concurrently!


The Rust Programming Language › Building Our Own Async Abstractions

We can also compose futures together to create new patterns. For example, we can
build a `timeout` function with async building blocks we already have. When
we’re done, the result will be another building block we could use to create
still more async abstractions.
Listing 17-18 shows how we would expect this `timeout` to work with a slow
future.
Listing 17-18: Using our imagined `timeout` to run a slow operation with a time limit (src/main.rs)
```rust,ignore,does_not_compile
        let slow = async {
            trpl::sleep(Duration::from_secs(5)).await;
            "Finally finished"
        };

        match timeout(slow, Duration::from_secs(2)).await {
            Ok(message) => println!("Succeeded with '{message}'"),
            Err(duration) => {
                println!("Failed after {} seconds", duration.as_secs())
            }
        }
```
Let’s implement this! To begin, let’s think about the API for `timeout`:
- It needs to be an async function itself so we can await it.
- Its first parameter should be a future to run. We can make it generic to allow
  it to work with any future.
- Its second parameter will be the maximum time to wait. If we use a `Duration`,
  that will make it easy to pass along to `trpl::sleep`.
- It should return a `Result`. If the future completes successfully, the
  `Result` will be `Ok` with the value produced by the future. If the timeout
  elapses first, the `Result` will be `Err` with the duration that the timeout
  waited for.
Listing 17-19 shows this declaration.
Listing 17-19: Defining the signature of `timeout` (src/main.rs)


The Rust Programming Language › Building Our Own Async Abstractions

```rust,ignore,does_not_compile
async fn timeout<F: Future>(
    future_to_try: F,
    max_time: Duration,
) -> Result<F::Output, Duration> {
    // Here is where our implementation will go!
}
```
That satisfies our goals for the types. Now let’s think about the _behavior_ we
need: we want to race the future passed in against the duration. We can use
`trpl::sleep` to make a timer future from the duration, and use `trpl::select`
to run that timer with the future the caller passes in.
In Listing 17-20, we implement `timeout` by matching on the result of awaiting
`trpl::select`.
Listing 17-20: Defining `timeout` with `select` and `sleep` (src/main.rs)
```rust
use trpl::Either;

// --snip--

async fn timeout<F: Future>(
    future_to_try: F,
    max_time: Duration,
) -> Result<F::Output, Duration> {
    match trpl::select(future_to_try, trpl::sleep(max_time)).await {
        Either::Left(output) => Ok(output),
        Either::Right(_) => Err(max_time),
    }
}
```
The implementation of `trpl::select` is not fair: it always polls arguments in
the order in which they are passed (other `select` implementations will
randomly choose which argument to poll first). Thus, we pass `future_to_try` to
`select` first so it gets a chance to complete even if `max_time` is a very
short duration. If `future_to_try` finishes first, `select` will return `Left`
with the output from `future_to_try`. If `timer` finishes first, `select` will
return `Right` with the timer’s output of `()`.


The Rust Programming Language › Building Our Own Async Abstractions

If the `future_to_try` succeeds and we get a `Left(output)`, we return
`Ok(output)`. If the sleep timer elapses instead and we get a `Right(())`, we
ignore the `()` with `_` and return `Err(max_time)` instead.
With that, we have a working `timeout` built out of two other async helpers. If
we run our code, it will print the failure mode after the timeout:
```text
Failed after 2 seconds
```
Because futures compose with other futures, you can build really powerful tools
using smaller async building blocks. For example, you can use this same
approach to combine timeouts with retries, and in turn use those with
operations such as network calls (such as those in Listing 17-5).
In practice, you’ll usually work directly with `async` and `await`, and
secondarily with functions such as `select` and macros such as the `join!`
macro to control how the outermost futures are executed.
We’ve now seen a number of ways to work with multiple futures at the same time.
Up next, we’ll look at how we can work with multiple futures in a sequence over
time with _streams_.


The Rust Programming Language › Streams: Futures in Sequence

Recall how we used the receiver for our async channel earlier in this chapter
in the “Message Passing” section. The async
`recv` method produces a sequence of items over time. This is an instance of a
much more general pattern known as a _stream_. Many concepts are naturally
represented as streams: items becoming available in a queue, chunks of data
being pulled incrementally from the filesystem when the full data set is too
large for the computer’s memory, or data arriving over the network over time.
Because streams are futures, we can use them with any other kind of future and
combine them in interesting ways. For example, we can batch up events to avoid
triggering too many network calls, set timeouts on sequences of long-running
operations, or throttle user interface events to avoid doing needless work.
We saw a sequence of items back in Chapter 13, when we looked at the Iterator
trait in “The Iterator Trait and the `next` Method”
 section, but there are two differences between iterators and the
async channel receiver. The first difference is time: iterators are
synchronous, while the channel receiver is asynchronous. The second difference
is the API. When working directly with `Iterator`, we call its synchronous
`next` method. With the `trpl::Receiver` stream in particular, we called an
asynchronous `recv` method instead. Otherwise, these APIs feel very similar,
and that similarity isn’t a coincidence. A stream is like an asynchronous form
of iteration. Whereas the `trpl::Receiver` specifically waits to receive
messages, though, the general-purpose stream API is much broader: it provides
the next item the way `Iterator` does, but asynchronously.


The Rust Programming Language › Streams: Futures in Sequence

The similarity between iterators and streams in Rust means we can actually
create a stream from any iterator. As with an iterator, we can work with a
stream by calling its `next` method and then awaiting the output, as in Listing
17-21, which won’t compile yet.
Listing 17-21: Creating a stream from an iterator and printing its values (src/main.rs)
```rust,ignore,does_not_compile
        let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        let iter = values.iter().map(|n| n * 2);
        let mut stream = trpl::stream_from_iter(iter);

        while let Some(value) = stream.next().await {
            println!("The value was: {value}");
        }
```
We start with an array of numbers, which we convert to an iterator and then
call `map` on to double all the values. Then we convert the iterator into a
stream using the `trpl::stream_from_iter` function. Next, we loop over the
items in the stream as they arrive with the `while let` loop.
Unfortunately, when we try to run the code, it doesn’t compile but instead
reports that there’s no `next` method available:


The Rust Programming Language › Streams: Futures in Sequence

```text
error[E0599]: no method named `next` found for struct `tokio_stream::iter::Iter` in the current scope
  --> src/main.rs:10:40
   |
10 |         while let Some(value) = stream.next().await {
   |                                        ^^^^
   |
   = help: items from traits can only be used if the trait is in scope
help: the following traits which provide `next` are implemented but not in scope; perhaps you want to import one of them
   |
1  + use crate::trpl::StreamExt;
   |
1  + use futures_util::stream::stream::StreamExt;
   |
1  + use std::iter::Iterator;
   |
1  + use std::str::pattern::Searcher;
   |
help: there is a method `try_next` with a similar name
   |
10 |         while let Some(value) = stream.try_next().await {
   |                                        ~~~~~~~~
```
As this output explains, the reason for the compiler error is that we need the
right trait in scope to be able to use the `next` method. Given our discussion
so far, you might reasonably expect that trait to be `Stream`, but it’s
actually `StreamExt`. Short for _extension_, `Ext` is a common pattern in the
Rust community for extending one trait with another.
The `Stream` trait defines a low-level interface that effectively combines the
`Iterator` and `Future` traits. `StreamExt` supplies a higher-level set of APIs
on top of `Stream`, including the `next` method as well as other utility
methods similar to those provided by the `Iterator` trait. `Stream` and
`StreamExt` are not yet part of Rust’s standard library, but most ecosystem
crates use similar definitions.


The Rust Programming Language › Streams: Futures in Sequence

The fix to the compiler error is to add a `use` statement for
`trpl::StreamExt`, as in Listing 17-22.
Listing 17-22: Successfully using an iterator as the basis for a stream (src/main.rs)
```rust
use trpl::StreamExt;

fn main() {
    trpl::block_on(async {
        let values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        // --snip--
```
With all those pieces put together, this code works the way we want! What’s
more, now that we have `StreamExt` in scope, we can use all of its utility
methods, just as with iterators.


The Rust Programming Language › A Closer Look at the Traits for Async

Throughout the chapter, we’ve used the `Future`, `Stream`, and `StreamExt`
traits in various ways. So far, though, we’ve avoided getting too far into the
details of how they work or how they fit together, which is fine most of the
time for your day-to-day Rust work. Sometimes, though, you’ll encounter
situations where you’ll need to understand a few more of these traits’ details,
along with the `Pin` type and the `Unpin` trait. In this section, we’ll dig in
just enough to help in those scenarios, still leaving the _really_ deep dive
for other documentation.


The Rust Programming Language › A Closer Look at the Traits for Async › The `Future` Trait

Let’s start by taking a closer look at how the `Future` trait works. Here’s how
Rust defines it:
```rust
use std::pin::Pin;
use std::task::{Context, Poll};

pub trait Future {
    type Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
```
That trait definition includes a bunch of new types and also some syntax we
haven’t seen before, so let’s walk through the definition piece by piece.
First, `Future`’s associated type `Output` says what the future resolves to.
This is analogous to the `Item` associated type for the `Iterator` trait.
Second, `Future` has the `poll` method, which takes a special `Pin` reference
for its `self` parameter and a mutable reference to a `Context` type, and
returns a `Poll<Self::Output>`. We’ll talk more about `Pin` and `Context` in a
moment. For now, let’s focus on what the method returns, the `Poll` type:
```rust
pub enum Poll<T> {
    Ready(T),
    Pending,
}
```
This `Poll` type is similar to an `Option`. It has one variant that has a value,
`Ready(T)`, and one that does not, `Pending`. `Poll` means something quite
different from `Option`, though! The `Pending` variant indicates that the future
still has work to do, so the caller will need to check again later. The `Ready`
variant indicates that the `Future` has finished its work and the `T` value is
available.

A Closer Look at the Traits for Async
The `Future` Trait


The Rust Programming Language › A Closer Look at the Traits for Async › The `Future` Trait

Note: It’s rare to need to call `poll` directly, but if you do need to, keep
in mind that with most futures, the caller should not call `poll` again after
the future has returned `Ready`. Many futures will panic if polled again after
becoming ready. Futures that are safe to poll again will say so explicitly in
their documentation. This is similar to how `Iterator::next` behaves.
When you see code that uses `await`, Rust compiles it under the hood to code
that calls `poll`. If you look back at Listing 17-4, where we printed out the
page title for a single URL once it resolved, Rust compiles it into something
kind of (although not exactly) like this:
```rust,ignore
match page_title(url).poll() {
    Ready(page_title) => match page_title {
        Some(title) => println!("The title for {url} was {title}"),
        None => println!("{url} had no title"),
    }
    Pending => {
        // But what goes here?
    }
}
```
What should we do when the future is still `Pending`? We need some way to try
again, and again, and again, until the future is finally ready. In other words,
we need a loop:
```rust,ignore
let mut page_title_fut = page_title(url);
loop {
    match page_title_fut.poll() {
        Ready(value) => match page_title {
            Some(title) => println!("The title for {url} was {title}"),
            None => println!("{url} had no title"),
        }
        Pending => {
            // continue
        }
    }
}
```


The Rust Programming Language › A Closer Look at the Traits for Async › The `Future` Trait

If Rust compiled it to exactly that code, though, every `await` would be
blocking—exactly the opposite of what we were going for! Instead, Rust ensures
that the loop can hand off control to something that can pause work on this
future to work on other futures and then check this one again later. As we’ve
seen, that something is an async runtime, and this scheduling and coordination
work is one of its main jobs.
In the “Sending Data Between Two Tasks Using Message
Passing” section, we described waiting on
`rx.recv`. The `recv` call returns a future, and awaiting the future polls it.
We noted that a runtime will pause the future until it’s ready with either
`Some(message)` or `None` when the channel closes. With our deeper
understanding of the `Future` trait, and specifically `Future::poll`, we can
see how that works. The runtime knows the future isn’t ready when it returns
`Poll::Pending`. Conversely, the runtime knows the future _is_ ready and
advances it when `poll` returns `Poll::Ready(Some(message))` or
`Poll::Ready(None)`.
The exact details of how a runtime does that are beyond the scope of this book,
but the key is to see the basic mechanics of futures: a runtime _polls_ each
future it is responsible for, putting the future back to sleep when it is not
yet ready.


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

Back in Listing 17-13, we used the `trpl::join!` macro to await three
futures. However, it’s common to have a collection such as a vector containing
some number of futures that won’t be known until runtime. Let’s change Listing
17-13 to the code in Listing 17-23 that puts the three futures into a vector
and calls the `trpl::join_all` function instead, which won’t compile yet.
Listing 17-23: Awaiting futures in a collection (src/main.rs)
```rust,ignore,does_not_compile
        let tx_fut = async move {
            // --snip--
        };

        let futures: Vec<Box<dyn Future<Output = ()>>> =
            vec![Box::new(tx1_fut), Box::new(rx_fut), Box::new(tx_fut)];

        trpl::join_all(futures).await;
```
We put each future within a `Box` to make them into _trait objects_, just as
we did in the “Returning Errors from `run`” section in Chapter 12. (We’ll cover
trait objects in detail in Chapter 18.) Using trait objects lets us treat each
of the anonymous futures produced by these types as the same type, because all
of them implement the `Future` trait.
This might be surprising. After all, none of the async blocks returns anything,
so each one produces a `Future<Output = ()>`. Remember that `Future` is a
trait, though, and that the compiler creates a unique enum for each async
block, even when they have identical output types. Just as you can’t put two
different handwritten structs in a `Vec`, you can’t mix compiler-generated
enums.

A Closer Look at the Traits for Async
The `Pin` Type and the `Unpin` Trait


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

Then we pass the collection of futures to the `trpl::join_all` function and
await the result. However, this doesn’t compile; here’s the relevant part of
the error messages.
```text
error[E0277]: `dyn Future<Output = ()>` cannot be unpinned
  --> src/main.rs:48:33
   |
48 |         trpl::join_all(futures).await;
   |                                 ^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = ()>`
   |
   = note: consider using the `pin!` macro
           consider using `Box::pin` if you need to access the pinned value outside of the current scope
   = note: required for `Box<dyn Future<Output = ()>>` to implement `Future`
note: required by a bound in `futures_util::future::join_all::JoinAll`
  --> file:///home/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/futures-util-0.3.30/src/future/join_all.rs:29:8
   |
27 | pub struct JoinAll<F>
   |            ------- required by a bound in this struct
28 | where
29 |     F: Future,
   |        ^^^^^^ required by this bound in `JoinAll`
```
The note in this error message tells us that we should use the `pin!` macro to
_pin_ the values, which means putting them inside the `Pin` type that
guarantees the values won’t be moved in memory. The error message says pinning
is required because `dyn Future<Output = ()>` needs to implement the `Unpin`
trait and it currently does not.


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

The `trpl::join_all` function returns a struct called `JoinAll`. That struct is
generic over a type `F`, which is constrained to implement the `Future` trait.
Directly awaiting a future with `await` pins the future implicitly. That’s why
we don’t need to use `pin!` everywhere we want to await futures.
However, we’re not directly awaiting a future here. Instead, we construct a new
future, JoinAll, by passing a collection of futures to the `join_all` function.
The signature for `join_all` requires that the types of the items in the
collection all implement the `Future` trait, and `Box<T>` implements `Future`
only if the `T` it wraps is a future that implements the `Unpin` trait.
That’s a lot to absorb! To really understand it, let’s dive a little further
into how the `Future` trait actually works, in particular around pinning. Look
again at the definition of the `Future` trait:
```rust
use std::pin::Pin;
use std::task::{Context, Poll};

pub trait Future {
    type Output;

    // Required method
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
```
The `cx` parameter and its `Context` type are the key to how a runtime actually
knows when to check any given future while still being lazy. Again, the details
of how that works are beyond the scope of this chapter, and you generally only
need to think about this when writing a custom `Future` implementation. We’ll
focus instead on the type for `self`, as this is the first time we’ve seen a
method where `self` has a type annotation. A type annotation for `self` works
like type annotations for other function parameters but with two key
differences:


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

- It tells Rust what type `self` must be for the method to be called.
- It can’t be just any type. It’s restricted to the type on which the method is
  implemented, a reference or smart pointer to that type, or a `Pin` wrapping a
  reference to that type.
We’ll see more on this syntax in Chapter 18. For now,
it’s enough to know that if we want to poll a future to check whether it is
`Pending` or `Ready(Output)`, we need a `Pin`-wrapped mutable reference to the
type.
`Pin` is a wrapper for pointer-like types such as `&`, `&mut`, `Box`, and `Rc`.
(Technically, `Pin` works with types that implement the `Deref` or `DerefMut`
traits, but this is effectively equivalent to working only with references and
smart pointers.) `Pin` is not a pointer itself and doesn’t have any behavior of
its own like `Rc` and `Arc` do with reference counting; it’s purely a tool the
compiler can use to enforce constraints on pointer usage.
Recalling that `await` is implemented in terms of calls to `poll` starts to
explain the error message we saw earlier, but that was in terms of `Unpin`, not
`Pin`. So how exactly does `Pin` relate to `Unpin`, and why does `Future` need
`self` to be in a `Pin` type to call `poll`?


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

Remember from earlier in this chapter that a series of await points in a future
get compiled into a state machine, and the compiler makes sure that state
machine follows all of Rust’s normal rules around safety, including borrowing
and ownership. To make that work, Rust looks at what data is needed between one
await point and either the next await point or the end of the async block. It
then creates a corresponding variant in the compiled state machine. Each
variant gets the access it needs to the data that will be used in that section
of the source code, whether by taking ownership of that data or by getting a
mutable or immutable reference to it.
So far, so good: if we get anything wrong about the ownership or references in
a given async block, the borrow checker will tell us. When we want to move
around the future that corresponds to that block—like moving it into a `Vec` to
pass to `join_all`—things get trickier.
When we move a future—whether by pushing it into a data structure to use as an
iterator with `join_all` or by returning it from a function—that actually means
moving the state machine Rust creates for us. And unlike most other types in
Rust, the futures Rust creates for async blocks can end up with references to
themselves in the fields of any given variant, as shown in the simplified illustration in Figure 17-4.

Figure 17-4: A self-referential data type


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

By default, though, any object that has a reference to itself is unsafe to move,
because references always point to the actual memory address of whatever they
refer to (see Figure 17-5). If you move the data structure itself, those
internal references will be left pointing to the old location. However, that
memory location is now invalid. For one thing, its value will not be updated
when you make changes to the data structure. For another—more important—thing,
the computer is now free to reuse that memory for other purposes! You could end
up reading completely unrelated data later.

<img alt="Two tables, depicting two futures, fut1 and fut2, each of which has one column and three rows, representing the result of having moved a future out of fut1 into fut2. The first, fut1, is grayed out, with a question mark in each index, representing unknown memory. The second, fut2, has 0 and 1 in the first and second rows and an arrow pointing from its third row back to the second row of fut1, representing a pointer that is referencing the old location in memory of the future before it was moved." src="img/trpl17-05.svg" class="center" />

Figure 17-5: The unsafe result of moving a self-referential data type

Theoretically, the Rust compiler could try to update every reference to an
object whenever it gets moved, but that could add a lot of performance overhead,
especially if a whole web of references needs updating. If we could instead make
sure the data structure in question _doesn’t move in memory_, we wouldn’t have
to update any references. This is exactly what Rust’s borrow checker is for:
in safe code, it prevents you from moving any item with an active reference to
it.


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

`Pin` builds on that to give us the exact guarantee we need. When we _pin_ a
value by wrapping a pointer to that value in `Pin`, it can no longer move. Thus,
if you have `Pin<Box<SomeType>>`, you actually pin the `SomeType` value, _not_
the `Box` pointer. Figure 17-6 illustrates this process.

<img alt="Three boxes laid out side by side. The first is labeled “Pin”, the second “b1”, and the third “pinned”. Within “pinned” is a table labeled “fut”, with a single column; it represents a future with cells for each part of the data structure. Its first cell has the value “0”, its second cell has an arrow coming out of it and pointing to the fourth and final cell, which has the value “1” in it, and the third cell has dashed lines and an ellipsis to indicate there may be other parts to the data structure. All together, the “fut” table represents a future which is self-referential. An arrow leaves the box labeled “Pin”, goes through the box labeled “b1” and terminates inside the “pinned” box at the “fut” table." src="img/trpl17-06.svg" class="center" />

Figure 17-6: Pinning a `Box` that points to a self-referential future type


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

In fact, the `Box` pointer can still move around freely. Remember: we care about
making sure the data ultimately being referenced stays in place. If a pointer
moves around, _but the data it points to_ is in the same place, as in Figure
17-7, there’s no potential problem. (As an independent exercise, look at the docs
for the types as well as the `std::pin` module and try to work out how you’d do
this with a `Pin` wrapping a `Box`.) The key is that the self-referential type
itself cannot move, because it is still pinned.

Figure 17-7: Moving a `Box` which points to a self-referential future type


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

However, most types are perfectly safe to move around, even if they happen to be
behind a `Pin` pointer. We only need to think about pinning when items have
internal references. Primitive values such as numbers and Booleans are safe
because they obviously don’t have any internal references.
Neither do most types you normally work with in Rust. You can move around
a `Vec`, for example, without worrying. Given what we have seen so far, if
you have a `Pin<Vec<String>>`, you’d have to do everything via the safe but
restrictive APIs provided by `Pin`, even though a `Vec<String>` is always safe
to move if there are no other references to it. We need a way to tell the
compiler that it’s fine to move items around in cases like this—and that’s
where `Unpin` comes into play.
`Unpin` is a marker trait, similar to the `Send` and `Sync` traits we saw in
Chapter 16, and thus has no functionality of its own. Marker traits exist only
to tell the compiler it’s safe to use the type implementing a given trait in a
particular context. `Unpin` informs the compiler that a given type does _not_
need to uphold any guarantees about whether the value in question can be safely
moved.
Just as with `Send` and `Sync`, the compiler implements `Unpin` automatically
for all types where it can prove it is safe. A special case, again similar to
`Send` and `Sync`, is where `Unpin` is _not_ implemented for a type. The
notation for this is impl !Unpin for SomeType, where
SomeType is the name of a type that _does_ need to uphold
those guarantees to be safe whenever a pointer to that type is used in a `Pin`.


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

In other words, there are two things to keep in mind about the relationship
between `Pin` and `Unpin`. First, `Unpin` is the “normal” case, and `!Unpin` is
the special case. Second, whether a type implements `Unpin` or `!Unpin` _only_
matters when you’re using a pinned pointer to that type like Pin<&mut
SomeType>.
To make that concrete, think about a `String`: it has a length and the Unicode
characters that make it up. We can wrap a `String` in `Pin`, as seen in Figure
17-8. However, `String` automatically implements `Unpin`, as do most other types
in Rust.

Figure 17-8: Pinning a `String`; the dotted line indicates that the `String` implements the `Unpin` trait and thus is not pinned


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

As a result, we can do things that would be illegal if `String` implemented
`!Unpin` instead, such as replacing one string with another at the exact same
location in memory as in Figure 17-9. This doesn’t violate the `Pin` contract,
because `String` has no internal references that make it unsafe to move around.
That is precisely why it implements `Unpin` rather than `!Unpin`.

Figure 17-9: Replacing the `String` with an entirely different `String` in memory

Now we know enough to understand the errors reported for that `join_all` call
from back in Listing 17-23. We originally tried to move the futures produced by
async blocks into a `Vec<Box<dyn Future<Output = ()>>>`, but as we’ve seen,
those futures may have internal references, so they don’t automatically
implement `Unpin`. Once we pin them, we can pass the resulting `Pin` type into
the `Vec`, confident that the underlying data in the futures will _not_ be
moved. Listing 17-24 shows how to fix the code by calling the `pin!` macro
where each of the three futures are defined and adjusting the trait object type.
Listing 17-24: Pinning the futures to enable moving them into the vector


The Rust Programming Language › A Closer Look at the Traits for Async › The `Pin` Type and the `Unpin` Trait

```rust
use std::pin::{Pin, pin};

// --snip--

        let tx1_fut = pin!(async move {
            // --snip--
        });

        let rx_fut = pin!(async {
            // --snip--
        });

        let tx_fut = pin!(async move {
            // --snip--
        });

        let futures: Vec<Pin<&mut dyn Future<Output = ()>>> =
            vec![tx1_fut, rx_fut, tx_fut];
```
This example now compiles and runs, and we could add or remove futures from the
vector at runtime and join them all.
`Pin` and `Unpin` are mostly important for building lower-level libraries, or
when you’re building a runtime itself, rather than for day-to-day Rust code.
When you see these traits in error messages, though, now you’ll have a better
idea of how to fix your code!
Note: This combination of `Pin` and `Unpin` makes it possible to safely
implement a whole class of complex types in Rust that would otherwise prove
challenging because they’re self-referential. Types that require `Pin` show up
most commonly in async Rust today, but every once in a while, you might see
them in other contexts, too.
The specifics of how `Pin` and `Unpin` work, and the rules they’re required
to uphold, are covered extensively in the API documentation for `std::pin`, so
if you’re interested in learning more, that’s a great place to start.
If you want to understand how things work under the hood in even more detail,
see Chapters 2 and
4 of
_Asynchronous Programming in Rust_.


The Rust Programming Language › A Closer Look at the Traits for Async › The `Stream` Trait

Now that you have a deeper grasp on the `Future`, `Pin`, and `Unpin` traits, we
can turn our attention to the `Stream` trait. As you learned earlier in the
chapter, streams are similar to asynchronous iterators. Unlike `Iterator` and
`Future`, however, `Stream` has no definition in the standard library as of
this writing, but there _is_ a very common definition from the `futures` crate
used throughout the ecosystem.
Let’s review the definitions of the `Iterator` and `Future` traits before
looking at how a `Stream` trait might merge them together. From `Iterator`, we
have the idea of a sequence: its `next` method provides an
`Option<Self::Item>`. From `Future`, we have the idea of readiness over time:
its `poll` method provides a `Poll<Self::Output>`. To represent a sequence of
items that become ready over time, we define a `Stream` trait that puts those
features together:
```rust
use std::pin::Pin;
use std::task::{Context, Poll};

trait Stream {
    type Item;

    fn poll_next(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>
    ) -> Poll<Option<Self::Item>>;
}
```
The `Stream` trait defines an associated type called `Item` for the type of the
items produced by the stream. This is similar to `Iterator`, where there may be
zero to many items, and unlike `Future`, where there is always a single
`Output`, even if it’s the unit type `()`.

A Closer Look at the Traits for Async
The `Stream` Trait


The Rust Programming Language › A Closer Look at the Traits for Async › The `Stream` Trait

`Stream` also defines a method to get those items. We call it `poll_next`, to
make it clear that it polls in the same way `Future::poll` does and produces a
sequence of items in the same way `Iterator::next` does. Its return type
combines `Poll` with `Option`. The outer type is `Poll`, because it has to be
checked for readiness, just as a future does. The inner type is `Option`,
because it needs to signal whether there are more messages, just as an iterator
does.
Something very similar to this definition will likely end up as part of Rust’s
standard library. In the meantime, it’s part of the toolkit of most runtimes,
so you can rely on it, and everything we cover next should generally apply!
In the examples we saw in the “Streams: Futures in Sequence”
 section, though, we didn’t use `poll_next` _or_ `Stream`, but
instead used `next` and `StreamExt`. We _could_ work directly in terms of the
`poll_next` API by hand-writing our own `Stream` state machines, of course,
just as we _could_ work with futures directly via their `poll` method. Using
`await` is much nicer, though, and the `StreamExt` trait supplies the `next`
method so we can do just that:
```rust
trait StreamExt: Stream {
    async fn next(&mut self) -> Option<Self::Item>
    where
        Self: Unpin;

    // other methods...
}
```
Note: The actual definition we used earlier in the chapter looks slightly
different than this, because it supports versions of Rust that did not yet
support using async functions in traits. As a result, it looks like this:
```rust,ignore
fn next(&mut self) -> Next<'_, Self> where Self: Unpin;
```


The Rust Programming Language › A Closer Look at the Traits for Async › The `Stream` Trait

That `Next` type is a `struct` that implements `Future` and allows us to name
the lifetime of the reference to `self` with `Next<'_, Self>`, so that `await`
can work with this method.
The `StreamExt` trait is also the home of all the interesting methods available
to use with streams. `StreamExt` is automatically implemented for every type
that implements `Stream`, but these traits are defined separately to enable the
community to iterate on convenience APIs without affecting the foundational
trait.
In the version of `StreamExt` used in the `trpl` crate, the trait not only
defines the `next` method but also supplies a default implementation of `next`
that correctly handles the details of calling `Stream::poll_next`. This means
that even when you need to write your own streaming data type, you _only_ have
to implement `Stream`, and then anyone who uses your data type can use
`StreamExt` and its methods with it automatically.
That’s all we’re going to cover for the lower-level details on these traits. To
wrap up, let’s consider how futures (including streams), tasks, and threads all
fit together!


The Rust Programming Language › Putting It All Together: Futures, Tasks, and Threads

As we saw in Chapter 16, threads provide one approach to
concurrency. We’ve seen another approach in this chapter: using async with
futures and streams. If you’re wondering when to choose one method over the other,
the answer is: it depends! And in many cases, the choice isn’t threads _or_
async but rather threads _and_ async.
Many operating systems have supplied threading-based concurrency models for
decades now, and many programming languages support them as a result. However,
these models are not without their tradeoffs. On many operating systems, they
use a fair bit of memory for each thread. Threads are also only an option when
your operating system and hardware support them. Unlike mainstream desktop and
mobile computers, some embedded systems don’t have an OS at all, so they also
don’t have threads.
The async model provides a different—and ultimately complementary—set of
tradeoffs. In the async model, concurrent operations don’t require their own
threads. Instead, they can run on tasks, as when we used `trpl::spawn_task` to
kick off work from a synchronous function in the streams section. A task is
similar to a thread, but instead of being managed by the operating system, it’s
managed by library-level code: the runtime.


The Rust Programming Language › Putting It All Together: Futures, Tasks, and Threads

There’s a reason the APIs for spawning threads and spawning tasks are so
similar. Threads act as a boundary for sets of synchronous operations;
concurrency is possible _between_ threads. Tasks act as a boundary for sets of
_asynchronous_ operations; concurrency is possible both _between_ and _within_
tasks, because a task can switch between futures in its body. Finally, futures
are Rust’s most granular unit of concurrency, and each future may represent a
tree of other futures. The runtime—specifically, its executor—manages tasks,
and tasks manage futures. In that regard, tasks are similar to lightweight,
runtime-managed threads with added capabilities that come from being managed by
a runtime instead of by the operating system.
This doesn’t mean that async tasks are always better than threads (or vice
versa). Concurrency with threads is in some ways a simpler programming model
than concurrency with `async`. That can be a strength or a weakness. Threads are
somewhat “fire and forget”; they have no native equivalent to a future, so they
simply run to completion without being interrupted except by the operating
system itself.
And it turns out that threads and tasks often work
very well together, because tasks can (at least in some runtimes) be moved
around between threads. In fact, under the hood, the runtime we’ve been
using—including the `spawn_blocking` and `spawn_task` functions—is multithreaded
by default! Many runtimes use an approach called _work stealing_ to
transparently move tasks around between threads, based on how the threads are
currently being utilized, to improve the system’s overall performance. That
approach actually requires threads _and_ tasks, and therefore futures.
When thinking about which method to use when, consider these rules of thumb:


The Rust Programming Language › Putting It All Together: Futures, Tasks, and Threads

- If the work is _very parallelizable_ (that is, CPU-bound), such as processing
  a bunch of data where each part can be processed separately, threads are a
  better choice.
- If the work is _very concurrent_ (that is, I/O-bound), such as handling
  messages from a bunch of different sources that may come in at different
  intervals or different rates, async is a better choice.
And if you need both parallelism and concurrency, you don’t have to choose
between threads and async. You can use them together freely, letting each
play the part it’s best at. For example, Listing 17-25 shows a fairly common
example of this kind of mix in real-world Rust code.
Listing 17-25: Sending messages with blocking code in a thread and awaiting the messages in an async block (src/main.rs)
```rust
use std::{thread, time::Duration};

fn main() {
    let (tx, mut rx) = trpl::channel();

    thread::spawn(move || {
        for i in 1..11 {
            tx.send(i).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    trpl::block_on(async {
        while let Some(message) = rx.recv().await {
            println!("{message}");
        }
    });
}
```
We begin by creating an async channel, then spawning a thread that takes
ownership of the sender side of the channel using the `move` keyword. Within
the thread, we send the numbers 1 through 10, sleeping for a second between
each. Finally, we run a future created with an async block passed to
`trpl::block_on` just as we have throughout the chapter. In that future, we
await those messages, just as in the other message-passing examples we have
seen.


The Rust Programming Language › Putting It All Together: Futures, Tasks, and Threads

To return to the scenario we opened the chapter with, imagine running a set of
video encoding tasks using a dedicated thread (because video encoding is
compute-bound) but notifying the UI that those operations are done with an
async channel. There are countless examples of these kinds of combinations in
real-world use cases.


The Rust Programming Language › Summary

This isn’t the last you’ll see of concurrency in this book. The project in
Chapter 21 will apply these concepts in a more realistic
situation than the simpler examples discussed here and compare problem-solving
with threading versus tasks and futures more directly.
No matter which of these approaches you choose, Rust gives you the tools you
need to write safe, fast, concurrent code—whether for a high-throughput web
server or an embedded operating system.
Next, we’ll talk about idiomatic ways to model problems and structure solutions
as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idioms
relate to those you might be familiar with from object-oriented programming.


The Rust Programming Language › Object-Oriented Programming Features

Object-oriented programming (OOP) is a way of modeling programs. Objects as a
programmatic concept were introduced in the programming language Simula in the
1960s. Those objects influenced Alan Kay’s programming architecture in which
objects pass messages to each other. To describe this architecture, he coined
the term _object-oriented programming_ in 1967. Many competing definitions
describe what OOP is, and by some of these definitions Rust is object oriented
but by others it is not. In this chapter, we’ll explore certain characteristics
that are commonly considered object oriented and how those characteristics
translate to idiomatic Rust. We’ll then show you how to implement an
object-oriented design pattern in Rust and discuss the trade-offs of doing so
versus implementing a solution using some of Rust’s strengths instead.


The Rust Programming Language › Characteristics of Object-Oriented Languages

There is no consensus in the programming community about what features a
language must have to be considered object oriented. Rust is influenced by many
programming paradigms, including OOP; for example, we explored the features
that came from functional programming in Chapter 13. Arguably, OOP languages
share certain common characteristics—namely, objects, encapsulation, and
inheritance. Let’s look at what each of those characteristics means and whether
Rust supports it.


The Rust Programming Language › Characteristics of Object-Oriented Languages › Objects Contain Data and Behavior

The book _Design Patterns: Elements of Reusable Object-Oriented Software_ by
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley,
1994), colloquially referred to as _The Gang of Four_ book, is a catalog of
object-oriented design patterns. It defines OOP in this way:
Object-oriented programs are made up of objects. An **object** packages both
data and the procedures that operate on that data. The procedures are
typically called **methods** or **operations**.
Using this definition, Rust is object oriented: Structs and enums have data,
and `impl` blocks provide methods on structs and enums. Even though structs and
enums with methods aren’t _called_ objects, they provide the same
functionality, according to the Gang of Four’s definition of objects.


The Rust Programming Language › Characteristics of Object-Oriented Languages › Encapsulation That Hides Implementation Details

Another aspect commonly associated with OOP is the idea of _encapsulation_,
which means that the implementation details of an object aren’t accessible to
code using that object. Therefore, the only way to interact with an object is
through its public API; code using the object shouldn’t be able to reach into
the object’s internals and change data or behavior directly. This enables the
programmer to change and refactor an object’s internals without needing to
change the code that uses the object.
We discussed how to control encapsulation in Chapter 7: We can use the `pub`
keyword to decide which modules, types, functions, and methods in our code
should be public, and by default everything else is private. For example, we
can define a struct `AveragedCollection` that has a field containing a vector
of `i32` values. The struct can also have a field that contains the average of
the values in the vector, meaning the average doesn’t have to be computed on
demand whenever anyone needs it. In other words, `AveragedCollection` will
cache the calculated average for us. Listing 18-1 has the definition of the
`AveragedCollection` struct.
Listing 18-1: An `AveragedCollection` struct that maintains a list of integers and the average of the items in the collection (src/lib.rs)
```rust,noplayground
pub struct AveragedCollection {
    list: Vec<i32>,
    average: f64,
}
```
The struct is marked `pub` so that other code can use it, but the fields within
the struct remain private. This is important in this case because we want to
ensure that whenever a value is added or removed from the list, the average is
also updated. We do this by implementing `add`, `remove`, and `average` methods
on the struct, as shown in Listing 18-2.


The Rust Programming Language › Characteristics of Object-Oriented Languages › Encapsulation That Hides Implementation Details

Listing 18-2: Implementations of the public methods `add`, `remove`, and `average` on `AveragedCollection` (src/lib.rs)
```rust,noplayground
impl AveragedCollection {
    pub fn add(&mut self, value: i32) {
        self.list.push(value);
        self.update_average();
    }

    pub fn remove(&mut self) -> Option<i32> {
        let result = self.list.pop();
        match result {
            Some(value) => {
                self.update_average();
                Some(value)
            }
            None => None,
        }
    }

    pub fn average(&self) -> f64 {
        self.average
    }

    fn update_average(&mut self) {
        let total: i32 = self.list.iter().sum();
        self.average = total as f64 / self.list.len() as f64;
    }
}
```
The public methods `add`, `remove`, and `average` are the only ways to access
or modify data in an instance of `AveragedCollection`. When an item is added to
`list` using the `add` method or removed using the `remove` method, the
implementations of each call the private `update_average` method that handles
updating the `average` field as well.
We leave the `list` and `average` fields private so that there is no way for
external code to add or remove items to or from the `list` field directly;
otherwise, the `average` field might become out of sync when the `list`
changes. The `average` method returns the value in the `average` field,
allowing external code to read the `average` but not modify it.


The Rust Programming Language › Characteristics of Object-Oriented Languages › Encapsulation That Hides Implementation Details

Because we’ve encapsulated the implementation details of the struct
`AveragedCollection`, we can easily change aspects, such as the data structure,
in the future. For instance, we could use a `HashSet<i32>` instead of a
`Vec<i32>` for the `list` field. As long as the signatures of the `add`,
`remove`, and `average` public methods stayed the same, code using
`AveragedCollection` wouldn’t need to change. If we made `list` public instead,
this wouldn’t necessarily be the case: `HashSet<i32>` and `Vec<i32>` have
different methods for adding and removing items, so the external code would
likely have to change if it were modifying `list` directly.
If encapsulation is a required aspect for a language to be considered object
oriented, then Rust meets that requirement. The option to use `pub` or not for
different parts of code enables encapsulation of implementation details.


The Rust Programming Language › Characteristics of Object-Oriented Languages › Inheritance as a Type System and as Code Sharing

_Inheritance_ is a mechanism whereby an object can inherit elements from
another object’s definition, thus gaining the parent object’s data and behavior
without you having to define them again.
If a language must have inheritance to be object oriented, then Rust is not
such a language. There is no way to define a struct that inherits the parent
struct’s fields and method implementations without using a macro.
However, if you’re used to having inheritance in your programming toolbox, you
can use other solutions in Rust, depending on your reason for reaching for
inheritance in the first place.
You would choose inheritance for two main reasons. One is for reuse of code:
You can implement particular behavior for one type, and inheritance enables you
to reuse that implementation for a different type. You can do this in a limited
way in Rust code using default trait method implementations, which you saw in
Listing 10-14 when we added a default implementation of the `summarize` method
on the `Summary` trait. Any type implementing the `Summary` trait would have
the `summarize` method available on it without any further code. This is
similar to a parent class having an implementation of a method and an
inheriting child class also having the implementation of the method. We can
also override the default implementation of the `summarize` method when we
implement the `Summary` trait, which is similar to a child class overriding the
implementation of a method inherited from a parent class.
The other reason to use inheritance relates to the type system: to enable a
child type to be used in the same places as the parent type. This is also
called _polymorphism_, which means that you can substitute multiple objects for
each other at runtime if they share certain characteristics.


The Rust Programming Language › Characteristics of Object-Oriented Languages › Polymorphism

To many people, polymorphism is synonymous with inheritance. But it’s
actually a more general concept that refers to code that can work with data of
multiple types. For inheritance, those types are generally subclasses.
Rust instead uses generics to abstract over different possible types and
trait bounds to impose constraints on what those types must provide. This is
sometimes called _bounded parametric polymorphism_.
Rust has chosen a different set of trade-offs by not offering inheritance.
Inheritance is often at risk of sharing more code than necessary. Subclasses
shouldn’t always share all characteristics of their parent class but will do so
with inheritance. This can make a program’s design less flexible. It also
introduces the possibility of calling methods on subclasses that don’t make
sense or that cause errors because the methods don’t apply to the subclass. In
addition, some languages will only allow _single inheritance_ (meaning a
subclass can only inherit from one class), further restricting the flexibility
of a program’s design.
For these reasons, Rust takes the different approach of using trait objects
instead of inheritance to achieve polymorphism at runtime. Let’s look at how
trait objects work.