You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 00:51:16