如何实现Rust简单Future计数器并正确调用Waker唤醒
阻塞原因
Future trait的核心契约:当poll返回Poll::Pending时,必须承诺未来在该Future可以继续推进时,调用传入Context中的Waker通知执行器。你注释掉wake调用后,执行器收到Pending结果就会永久挂起等待唤醒信号,不会再主动轮询该Future,计数器自然无法推进导致永久阻塞。
最简wake实现
不需要额外设计延后调用逻辑,直接取消你注释的cx.waker().wake()代码就是可运行的最简实现。
修正后的完整可运行代码:
use std::future::Future; use std::task::{Poll, Context}; use std::pin::Pin; use futures::executor::block_on; struct MyStruct { counter: u32 } impl Future for MyStruct { type Output = String; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { if self.counter == 5 { Poll::Ready(self.counter.to_string()) } else { // MyStruct仅包含u32类型字段,自动实现Unpin,无需unsafe操作 self.get_mut().counter += 1; // 返回Pending前唤醒,通知执行器立即再次轮询当前Future cx.waker().wake(); Poll::Pending } } } fn main() { let ms = MyStruct{counter: 0}; let result = block_on(ms); println!("{}", result); // 输出5 }
注意事项
- 这种返回Pending前立刻唤醒的写法属于忙等,仅适合做功能演示。生产环境的Future(例如IO操作、定时器)会将Waker克隆后存储,等到对应的异步事件(IO就绪、计时结束)实际触发时再调用wake,避免无意义的轮询空耗CPU。
- 原代码中使用
Pin::get_unchecked_mut的unsafe写法没有必要:所有字段都实现Unpin的自定义结构体会自动实现Unpin,可直接通过Pin::get_mut安全获取可变引用。
内容的提问来源于stack exchange,提问作者unegare
相关产品推荐
相关产品推荐

