┌─────────────────────────────────────────────────────┐
│ async fn → State Machine (enum) → impl Future │
│ .await → poll() the inner future │
│ executor → loop { poll(); sleep_until_woken(); } │
│ waker → "hey executor, poll me again" │
│ Pin → "promise I won't move in memory" │
└─────────────────────────────────────────────────────┘
Goal Use
Run two futures concurrently tokio::join!(a, b)
Race two futures tokio::select! { ... }
Spawn a background task tokio::spawn(async { ... })
Run blocking code in async tokio::task::spawn_blocking(\|\| { ... })
Limit concurrency Semaphore::new(N)
Collect many task results JoinSet
Share state across tasks Arc<Mutex<T>> or channels
Graceful shutdown watch::channel + select!
Process a stream N-at-a-time .buffer_unordered(N)
Timeout a future tokio::time::timeout(dur, fut)
Retry with backoff Custom combinator (see Ch. 13)
Situation Use
Pin a future on the heap Box::pin(fut)
Pin a future on the stack tokio::pin!(fut)
Pin an Unpin type Pin::new(&mut val) — safe, free
Return a pinned trait object -> Pin<Box<dyn Future<Output = T> + Send>>
Channel Producers Consumers Values Use When
mpscN 1 Stream Work queues, event buses
oneshot1 1 Single Request/response, completion notification
broadcastN N All recv all Fan-out notifications, shutdown signals
watch1 N Latest only Config updates, health status
Mutex Use When
std::sync::MutexLock is held briefly, never across .await
tokio::sync::MutexLock must be held across .await
parking_lot::MutexHigh contention, no .await, need performance
tokio::sync::RwLockMany readers, few writers, locks cross .await
Need concurrency?
├── I/O-bound → async/await
├── CPU-bound → rayon / std::thread
└── Mixed → spawn_blocking for CPU parts
Choosing runtime?
├── Server app → tokio
├── Library → runtime-agnostic (futures crate)
├── Embedded → embassy
└── Minimal → smol
Need concurrent futures?
├── Can be 'static + Send → tokio::spawn
├── Can be 'static + !Send → LocalSet
├── Can't be 'static → FuturesUnordered
└── Need to track/abort → JoinSet
Error Cause Fix
future is not SendHolding !Send type across .await Scope the value so it’s dropped before .await, or use current_thread runtime
borrowed value does not live long enough in spawntokio::spawn requires 'staticUse Arc, clone(), or FuturesUnordered
the trait Future is not implemented for ()Missing .await Add .await to the async call
cannot borrow as mutable in pollSelf-referential borrow Use Pin<&mut Self> correctly (see Ch. 4)
Program hangs silently Forgot to call waker.wake() Ensure every Pending path registers and triggers the waker
End of Async Rust Training Guide