Async Implementation Details
Main components of Async/Await
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