In this chapter, we’ll start by improving our coroutines by adding the ability to store variables across state changes. We’ll see how this leads to our coroutines needing to take references to themselves and the issues that arise as a result of that. The reason for dedicating a whole chapter to this topic is that it’s an integral part of getting async/await to work in Rust, and also a topic that is somewhat difficult to get a good understanding of.
The reason for this is that the whole concept of pinning is foreign to many developers and just like the Rust ownership system, it takes some time to get a good and working mental model of it.
Fortunately, the concept of pinning is not that difficult to understand, but how it’s implemented in the language and how it interacts with Rust’s type system is abstract and hard to grasp.
While we won’t cover absolutely everything about pinning in this chapter, we’ll try to get a good and sound understanding of it. The major goal here is to feel confident with the topic and understand why we need it and how to use it.
As mentioned previously, this chapter is not only about pinning in Rust, so the first thing we’ll do is make some important improvements where we left off by improving the final example in Chapter 8.
Then, we’ll explain what self-referential structs are and how they’re connected to futures before we explain how pinning can solve our problems.
This chapter will cover the following main topics
- Improving our example 1 – variables
- Improving our example 2 – references
- Improving our example 3 – this is… not… good…
- Discovering self-referential structs
- Pinning in Rust
- Improving our example 4 – pinning to the rescue
Technical requirements
The examples in this chapter will build on the code from the previous chapter, so the requirements are the same. The examples will all be cross-platform and work on all platforms that Rust (https://doc.rust-lang.org/stable/rustc/platform-support.html) and mio (https://github.com/tokio-rs/mio#platforms) support. The only thing you need is Rust installed and this book’s GitHub repository downloaded locally. All the code in this chapter can be found in the ch09 folder.
To follow the examples step by step, you’ll also need corofy installed on your machine. If you didn’t install it in Chapter 7, install it now by going into the ch07/corofy folder in the repository and running the following:
cargo install –force –path .
We’ll also use delayserver in this example, so you need to open a separate terminal, enter the delayserver folder at the root of the repository, and write cargo run so that it’s ready and available for the examples going forward.
Remember to change the port number in the code if you have to change what port delayserver listens on.