Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Async Snippets

This chapter isolates async Rust recall snippets so the mental model stays separate from the synchronous core language.

Mental Model

  • async fn returns a future.
  • Futures are state machines.
  • .await is a suspension point.
  • Async gives concurrency, not magic.
  • Blocking code inside async can still block a Tokio worker thread.

Basic async function

#![allow(unused)]
fn main() {
async fn fetch_value() -> u32 {
    42
}
}

tokio::main

#[tokio::main]
async fn main() {
    let value = fetch_value().await;
    println!("{value}");
}

Spawn task

#[tokio::main]
async fn main() {
    let handle = tokio::spawn(async {
        5 + 5
    });

    let result = handle.await.unwrap();
    println!("{result}");
}

tokio::select!

use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() {
    tokio::select! {
        _ = sleep(Duration::from_millis(10)) => {
            println!("timer 1");
        }
        _ = sleep(Duration::from_millis(20)) => {
            println!("timer 2");
        }
    }
}

Async error handling

#![allow(unused)]
fn main() {
async fn parse_async(input: &str) -> Result<u32, std::num::ParseIntError> {
    let n = input.parse::<u32>()?;
    Ok(n)
}
}

Blocking hazard

#![allow(unused)]
fn main() {
async fn bad() {
    std::thread::sleep(std::time::Duration::from_millis(50));
}
}

spawn_blocking

#[tokio::main]
async fn main() {
    let result = tokio::task::spawn_blocking(|| {
        std::thread::sleep(std::time::Duration::from_millis(50));
        42
    })
    .await
    .unwrap();

    println!("{result}");
}

Async shared state

use std::sync::Arc;
use tokio::sync::Mutex;

#[tokio::main]
async fn main() {
    let value = Arc::new(Mutex::new(0));

    let v = Arc::clone(&value);
    let handle = tokio::spawn(async move {
        let mut guard = v.lock().await;
        *guard += 1;
    });

    handle.await.unwrap();
    println!("{}", *value.lock().await);
}

Async Recall Checklist

  • Can I explain what an async fn returns?
  • Can I explain why futures are state machines?
  • Can I explain .await as a suspension point?
  • Can I explain why blocking inside async Rust is dangerous?
  • Can I explain when spawn_blocking is the right tool?