gpt4 book ai didi

asynchronous - 在异步Rust中,如何实现围绕民意调查的包装?

转载 作者:行者123 更新时间:2023-12-03 11:39:32 24 4
gpt4 key购买 nike

假设我有一个异步函数foo返回了一些值。每次调用后返回的值是不同的(例如,可以从文件或随机数生成器中读取数据块)。

我想围绕实现 foo AsyncRead实现一个包装器结构。包装器从foo读取值,以某种方式处理它们,然后将其放入用户提供的缓冲区中。

这是我尝试过的:

use futures::io::AsyncRead;
use pin_utils::pin_mut;
use std::io;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;

async fn foo() -> u8 {
b'x'
}

pub struct FooReader;

impl AsyncRead for FooReader {
fn poll_read(self: Pin<&mut Self>, ctx: &mut Context<'_>, buf: &mut [u8])
-> Poll<io::Result<usize>>
{
if buf.is_empty() {
return Poll::Ready(Ok(0));
}
match foo().poll() { // << problem here
Poll::Ready(byte) => {
buf[0] = byte;
Poll::Ready(Ok(1))
},
Poll::Pending => Poll::Pending,
}
}
}

(Link to Playground)

这显然无法编译,因为 poll()需要固定值。现在, 如何固定foo返回的 future ? 我尝试了 Box::pinPin::newpin_mut!的各种组合,但是它们都不起作用。

另外, 我是否应该将Future存储在我的结构FooReader中,直到准备好为止? 还是我可以在每次通话后随意删除它,即使它正在等待处理?

编辑:以下工作原理:

let mut future: Pin<Box<dyn Future<Output = u8>>> = Box::pin(foo());
match future.as_mut().poll(ctx) {
...
}

(Link to Playground)

出于某种原因,我必须给 future一个显式的类型注释,否则它将无法编译(以某种方式,编译器会在 impl Futuredyn Future之间造成混淆)。

即使有效,我仍然想知道这是否是“官方”的方式。

最佳答案

由于某种原因,Future特性不在标准的前奏中,因此您必须在调用函数之前对其进行use(提示在那里,埋在所有其他编译器错误之间):

use std::future::Future;

然后,是的,您必须在使用前固定好将来。在您的情况下,最简单的方法是使用 pin_mut!,它使用有趣的语法:
let f = foo();
pin_mut!(f);

现在,您可以调用 poll(),但是请记住,您必须转发 Context参数:
match f.poll(ctx) {

Playground与工作代码。

关于存储或丢弃 future ,您可以根据确切的语义做任何您想做的事情。我个人希望您能保留 future 并完成它,除非文档中另有明确说明。

自然地,如果将future存储在结构中,则 pin_mut!将不起作用,因为它消耗了其参数。您需要将其保留在 Pin<Box>中,或从 self投影该引脚,因为该引脚已被固定。

要保留 Pin<Box>,请执行以下操作:
pub struct FooReader {
f: Option<Pin<Box<dyn Future<Output=u8>>>>,
}

然后要使用它,请不要忘记 Box::as_mut(),因为您需要 Pin<&mut Future>,而不是 Pin<Box<impl Future>>:
        let f = foo();
self.f = Some(Box::pin(f)); //remember to declare (mut self) above!
match self.f.as_mut().unwrap().as_mut().poll(ctx) {

您可能需要在再次调用 self.f之前检查 foo(),但您明白了。

引脚投影的选项更好,因为您避免了为Box分配额外的空间,但是这样做比较复杂,并且需要额外的包装箱或一些不安全的代码。如果您真的有兴趣,我认为它值得一个新的问题。

关于asynchronous - 在异步Rust中,如何实现围绕民意调查的包装?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61905627/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com