Async Concepts
Await Chain
One Future Uses Another
Inside an async function, .await waits for another future and then continues with its returned value.
Program
Play the program to choose a count and watch one async function await another before formatting the label.
await_chain.rs
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
fn main() {
let count = ;
let future = build_label("task", count);
let label = block_on(future);
println!("{label}");
}
async fn build_label(prefix: &str, count: i32) -> String {
let label = make_label(prefix).await;
format!("{label}:{count}")
}
async fn make_label(prefix: &str) -> String {
format!("{prefix}-ready")
}
fn block_on<F: Future>(future: F) -> F::Output {
let waker = noop_waker();
let mut context = Context::from_waker(&waker);
let mut future = pin!(future);
loop {
match future.as_mut().poll(&mut context) {
Poll::Ready(value) => return value,
Poll::Pending => {}
}
}
}
fn noop_waker() -> Waker {
unsafe { Waker::from_raw(noop_raw_waker()) }
}
fn noop_raw_waker() -> RawWaker {
RawWaker::new(std::ptr::null(), &VTABLE)
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(|_| noop_raw_waker(), |_| {}, |_| {}, |_| {});
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
fn main() {
let count = ;
let future = build_label("task", count);
let label = block_on(future);
println!("{label}");
}
async fn build_label(prefix: &str, count: i32) -> String {
let label = make_label(prefix).await;
format!("{label}:{count}")
}
async fn make_label(prefix: &str) -> String {
format!("{prefix}-ready")
}
fn block_on<F: Future>(future: F) -> F::Output {
let waker = noop_waker();
let mut context = Context::from_waker(&waker);
let mut future = pin!(future);
loop {
match future.as_mut().poll(&mut context) {
Poll::Ready(value) => return value,
Poll::Pending => {}
}
}
}
fn noop_waker() -> Waker {
unsafe { Waker::from_raw(noop_raw_waker()) }
}
fn noop_raw_waker() -> RawWaker {
RawWaker::new(std::ptr::null(), &VTABLE)
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(|_| noop_raw_waker(), |_| {}, |_| {}, |_| {});
use std::future::Future;
use std::pin::pin;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
fn main() {
let count = ;
let future = build_label("task", count);
let label = block_on(future);
println!("{label}");
}
async fn build_label(prefix: &str, count: i32) -> String {
let label = make_label(prefix).await;
format!("{label}:{count}")
}
async fn make_label(prefix: &str) -> String {
format!("{prefix}-ready")
}
fn block_on<F: Future>(future: F) -> F::Output {
let waker = noop_waker();
let mut context = Context::from_waker(&waker);
let mut future = pin!(future);
loop {
match future.as_mut().poll(&mut context) {
Poll::Ready(value) => return value,
Poll::Pending => {}
}
}
}
fn noop_waker() -> Waker {
unsafe { Waker::from_raw(noop_raw_waker()) }
}
fn noop_raw_waker() -> RawWaker {
RawWaker::new(std::ptr::null(), &VTABLE)
}
static VTABLE: RawWakerVTable = RawWakerVTable::new(|_| noop_raw_waker(), |_| {}, |_| {}, |_| {});
.await
`.await` pauses the surrounding async function until the awaited future is ready.
continuation
After `make_label(prefix).await`, `build_label` continues with the returned string.
composition
Async functions can be composed by awaiting one future inside another.