async fn learn_and_sing() {
let song = learn_song().await; // 1
sing_song(song).await; // 2
sing_song(song).await; // 3
}
Tasks
Wakers
Executors
Pin
Every async function that awaits creates tasks
Effectively "subtasks" of the function
Tasks describe dependencies
async fn learn_and_sing() {
let song = learn_song().await; // 1
sing_song(song).await; // 2
sing_song(song).await; // 3
}
Functions become a state machine
State machines can restart once progress can be made
Similar to generators
Polling all the tasks is a busy wait
Wakers allow us to register a way to wake
All types by default can move
But what if you want to prevent it
Pin: underlying memory can not move
#[tokio::main]
async fn main() {
let mut stream = async_stream();
let sleep = time::sleep(Duration::from_secs(10));
tokio::pin!(sleep);
loop {
tokio::select! {
maybe_v = stream.next() => {
if maybe_v.is_none() { break }
println!("got = {:?}", maybe_v);
}
_ = &mut sleep => {
println!("timeout: 10 secs elapsed");
break;
}
}
}
}
Start with the top-level Futures and drive to completions
Calls wake()
when a task can make progress