Summary and Reference Card
Quick Reference Card
Async Mental Model
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā 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" ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Common Patterns Cheat Sheet
| 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) |
Pinning Quick Reference
| 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 Selection Guide
| Channel | Producers | Consumers | Values | Use When |
|---|---|---|---|---|
mpsc | N | 1 | Stream | Work queues, event buses |
oneshot | 1 | 1 | Single | Request/response, completion notification |
broadcast | N | N | All recv all | Fan-out notifications, shutdown signals |
watch | 1 | N | Latest only | Config updates, health status |
Mutex Selection Guide
| Mutex | Use When |
|---|---|
std::sync::Mutex | Lock is held briefly, never across .await |
tokio::sync::Mutex | Lock must be held across .await |
parking_lot::Mutex | High contention, no .await, need performance |
tokio::sync::RwLock | Many readers, few writers, locks cross .await |
Decision Quick Reference
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
Common Error Messages and Fixes
| Error | Cause | Fix |
|---|---|---|
future is not Send | Holding !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 spawn | tokio::spawn requires 'static | Use Arc, clone(), or FuturesUnordered |
the trait Future is not implemented for () | Missing .await | Add .await to the async call |
cannot borrow as mutable in poll | Self-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 |
Further Reading
| Resource | Why |
|---|---|
| Tokio Tutorial | Official hands-on guide ā excellent for first projects |
| Async Book (official) | Covers Future, Pin, Stream at the language level |
| Jon Gjengset ā Crust of Rust: async/await | 2-hour deep dive into internals with live coding |
| Alice Ryhl ā Actors with Tokio | Production architecture pattern for stateful services |
| Without Boats ā Pin, Unpin, and why Rust needs them | The original motivation from the language designer |
| Tokio mini-Redis | Complete async Rust project ā study-quality production code |
| Tower documentation | Middleware/service architecture used by axum, tonic, hyper |
End of Async Rust Training Guide