Future trait 深入
学习目标
- 理解 Future 的 poll 机制
- 理解 Waker 的作用
- 掌握手写 Future
核心概念
Future trait
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
poll 机制
// 执行器不断调用 poll:
// 1. 返回 Poll::Ready(value) → 完成
// 2. 返回 Poll::Pending → 注册 Waker,稍后通知
// 流程:
// 执行器 → poll() → Pending → 注册 Waker
// ↓
// IO 就绪 → Waker 通知执行器
// ↓
// 执行器 → poll() → Ready(value)
手写 Future
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
struct Delay {
when: Instant,
}
impl Delay {
fn new(duration: Duration) -> Self {
Delay { when: Instant::now() + duration }
}
}
impl Future for Delay {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
if Instant::now() >= self.when {
Poll::Ready(())
} else {
// 注册 waker,实际中应该让 IO 操作完成后调用 wake()
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
async 块的 Future
// async { expr } 会被编译器转换为实现了 Future 的匿名类型
let future = async {
1 + 2
};
// 等价于手写的 Future,状态机自动管理
小结
| 概念 | 说明 |
|---|---|
poll | 驱动 Future 的方法 |
Poll::Ready | 完成 |
Poll::Pending | 未完成 |
Waker | 通知执行器的机制 |
Pin | 防止值被移动 |