Async Snippets
This chapter isolates async Rust recall snippets so the mental model stays separate from the synchronous core language.
Mental Model
async fnreturns a future.- Futures are state machines.
.awaitis 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 fnreturns? - Can I explain why futures are state machines?
- Can I explain
.awaitas a suspension point? - Can I explain why blocking inside async Rust is dangerous?
- Can I explain when
spawn_blockingis the right tool?