-
大致概念:[80%-sure] 以 Rust 为例,运行到 func().await 时 (func 为 async fn)
- func() 内部代码完全交由 async runtime 处理
- func() 内部通常有等待IO/GPU/定时器的异步部分。这些部分不由 CPU 负责运算,不应该让 CPU 干等着,所以才写成异步函数.
- 如果 func() 内部全是同步代码,没有 .await 或手动挂起点,写成异步(async fn)没有实际意义
- 它是不会挂起的,会同步执行完毕。
-
轮询
- poll 调用次数不是固定的,取决于任务的完成时机和外部事件。
Rust
1async fn my_async(x: u32) -> u32 {2 let a = x + 1;3 a * 24}5
6let fut = my_async(10);7fut.await; // 开始轮询
- 编译器生成的大致逻辑:
1enum MyAsyncState {2 Start { x: u32 },3 Done,4}5
6struct MyAsyncFuture {7 state: MyAsyncState,8}9
10impl Future for MyAsyncFuture {11 type Output = u32;12
13 fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<u32> {14 match self.state {15 MyAsyncState::Start { x } => {11 collapsed lines
16 let a = x + 1;17 let result = a * 2;18 self.state = MyAsyncState::Done;19 Poll::Ready(result)20 },21 MyAsyncState::Done => {22 panic!("polled after completion");23 }24 }25 }26}
- 另一个例子:
1async fn my_async(x: u32) -> u32 {2 let a = x + 1;3 tokio::time::sleep(Duration::from_secs(3)).await;4 a * 25}
1enum MyAsyncState {2 Start { x: u32 },3 Waiting { a: u32, sleep_future: Sleep },4 Done,5}6
7impl Future for MyAsyncFuture {8 type Output = u32;9
10 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<u32> {11 loop {12 match self.state {13 MyAsyncState::Start { x } => {14 let a = x + 1;15 let sleep_future = tokio::time::sleep(Duration::from_secs(3));19 collapsed lines
16 self.state = MyAsyncState::Waiting { a, sleep_future };17 },18 MyAsyncState::Waiting { a, ref mut sleep_future } => {19 match Pin::new(sleep_future).poll(cx) {20 Poll::Pending => return Poll::Pending,21 Poll::Ready(_) => {22 let result = a * 2;23 self.state = MyAsyncState::Done;24 return Poll::Ready(result);25 }26 }27 },28 MyAsyncState::Done => {29 panic!("polled after completion");30 }31 }32 }33 }34}