【问题标题】:How to make Future counter?如何制作未来计数器?
【发布时间】:2022-06-15 23:49:01
【问题描述】:

我愿意impl 一个简单的Future 计数器,但是这绝对是错误的。如果不使用Context,以下程序将永远阻塞;

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 {
            unsafe {
                Pin::get_unchecked_mut(self).counter += 1;
            }
//            cx.waker().wake();
            Poll::Pending
        }
    }
}

fn main() {
    let ms = MyStruct{counter: 0};
    block_on(ms);
}

我想我必须以某种方式推迟Waker 的通话,但这并不是那么简单。所以我想知道,如何以最简单的形式wake呢?

【问题讨论】:

  • 不确定我是否理解目标。未来不会产生多个结果,因此即使您的 poll() 工作正常,也与立即返回 Poll::Ready("5") 没有什么不同。
  • @kmdreko,我想让它被轮询几次,直到用Poll::Ready(...)解决它
  • 但是为什么呢?或者这只是一个学习练习?
  • @kmdreko,只是自学经验)在 Future 的普通实现中,有套接字或其他一些 fd,所以整个魔法都在 epoll 系统调用中。这么多额外的东西并没有引起太大的兴趣。所以我想构建一个不涉及任何套接字的简洁示例。
  • 您的代码(每次都正确调用.wake()does work,因为它将被轮询完成。在最基本的层面上,调用.wake() 将再次告诉处理未来的执行者.poll()

标签: rust future


【解决方案1】:

您可以拨打.wake_by_ref()。唤醒唤醒器将告诉正在处理Future 的执行程序再次成为.poll()

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 {
            unsafe {
                Pin::get_unchecked_mut(self).counter += 1;
            }
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

因此,您的实施将始终要求立即重新轮询。我会注意到,这在逻辑上与在第一次调用时简单地返回 Poll::Ready("5".to_string()) 没有什么不同,因为这里没有异步工作正在完成。因此,它根本没有理由成为Future

【讨论】:

  • 我会说这更像是循环(或递归)然后返回Poll::Ready
猜你喜欢
  • 2012-08-05
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多