liveBook · Manning

Tokio

As explained in Learn Rust in a Month of Lunches

Tokio is a Rust asynchronous runtime and library for scheduling tasks, polling futures, and performing asynchronous I/O.

Tokio is a Rust asynchronous runtime and library. It manages the polling that lets futures make progress, so asynchronous code can run even though Rust has no built-in official runtime. section 19.3.2

The simplest entry point is #[tokio::main]. Place it above an async main function, then use .await inside that function. Tokio arranges the runtime work behind the scenes and lets the program finish after the asynchronous block completes. section 19.3.3

When using Tokio, remember these practical rules:

  • Use .await only inside an async function or async block. section 19.3.3
  • Make a regular function async when it needs to await an asynchronous function. section 19.3.3
  • Expect regular functions to block their thread while they run. section 19.3.3

Async HTTP request

A Tokio program can create a default reqwest client, send a request with .await, and await the response body before printing it. section 19.3.3

use tokio;
 
async fn async_give_8() -> u8 {
    8
}
 
fn main() {                                                   #1
    let body = async {                                        #2
        let some_number = async_give_8().await;
        let second_number = async_give_8().await;
        {
            ::std::io::_print(format_args!("{0}, {1}\n", some_number,
            second_number));
        };
    };
 
    {
        return tokio::runtime::Builder::new_multi_thread()    #3
            .enable_all()
            .build()
            .expect("Failed building the Runtime")
            .block_on(body);                                  #4
    }
}
#1 Look here—async fn is a lie! It’s actually just a regular fn main(). As far as Rust is concerned, the main() function is not async at all.
#2 First, everything gets enclosed inside a big async block called body. The .await keyword can be used inside here.
#3 Now the Tokio run time starts. It uses the builder pattern to set some configuration.
#4 And, finally, the part that matters: a method called block_on(). Tokio is actually just blocking until everything has been resolved!

Inspecting the expanded macro reveals a regular main function, an async block, and a Tokio runtime that calls block_on. section 19.3.3

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains runtime necessity, #[tokio::main], .await placement, and macro expansion down to block_on.
Examples
Uses async_give_8, #[tokio::main], macro expansion, and an asynchronous reqwest HTTP request.
What it assumes
Assumes basic Rust functions and return types while teaching futures, .await, and runtime polling from the immediate problem.
What you can do after
Apply it via #[tokio::main] to run async functions, await futures, and perform asynchronous requests.
How it connects
Connects async functions, futures, .await, asynchronous I/O, and reqwest.

Also explained in

Compare how 3 books explain Tokio →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.