A Rust Async Primer-Pt 2
This is part 2 in a 3 part series on understanding the basics of asynchronous programming in Rust. Part 1 focused on the concepts around asynchronous programming, and specifically, how Rust implements it. In this one, we’re going to look at some example code.
First, let’s create a new project using Cargo with
cargo new rustasync --bin
Now, open up the generated Cargo.toml file and add the futures-rs crate to the dependencies section. You can follow the link above to learn more and find the complete documentation but in summary, it’s a bare-bones implementation of an async runtime. Your toml file should look similar to the one below:
name = "rust-async"
version = "0.1.0"
edition = "2021"# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html[dependencies]
futures = "0.3"
The futures-rs crate implements some of Rust's core abstractions for asynchronous programming. We’ll go over those in more depth later but for now, the
Future trait is of the most relevance to us.
Let’s imagine that we’re going to fix breakfast at home. We might choose to make some coffee, eggs, and because I’m trying to be healthy, use the oven to make some bacon. My process would be something like starting the coffee maker and getting the coffee brewing. While that’s happening I could pre-heat the oven. While the oven is pre-heating I can get the bacon out and ready it for the oven. Once the bacon is ready I can put it in the oven, pour myself some coffee, and cook the eggs while waiting for the bacon to finish. I’m sure you get the idea at this point. If we were to prepare breakfast synchronously, one task after the other, it would take significantly longer to complete preparing breakfast and most of it would be cold by the time we got to eat it.
Let’s write a simple application to try and mimic this approach by using asynchronous code. Open up the main.rs file under the src directory and add the following code.
// The block_on function simply blocks the current thread until the
// Future has completed and returned.use futures::executor::block_on;