-1

如何实现Futures::poll以下将调用async具有完全所有权的方法的代码self

use anyhow::Error;
use futures::Future;
use futures::channel::oneshot;
use futures::task::{Context, Poll};
use std::pin::Pin;

struct MyLongTask {
    rx: oneshot::Receiver<()>,
}

impl MyLongTask {
    // The method and full ownership to `self` is important to keep!
    async fn recv(mut self) -> Result<(), Error> {
        self.rx.await.map_err(|_| Error::msg("can't recv"))
    }
}

// TryFuture not necessary here
impl Future for MyLongTask {
    type Output = Result<(), Error>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        todo!("how to `self.recv().await` here?")
    }
}

fn main() { }

如果需要,游乐场。

4

1 回答 1

2

你不能调用self.recv()insidepoll首先是因为它不拥有self,其次因为它不是 asyncFuture::poll是同步的,但无论返回值是否准备好,都必须快速返回(这就是 的全部思想Poll::Pending)。在您的情况下,您应该简单地将其委托pollself.rx:(操场

impl Future for MyLongTask {
    type Output = Result<(), Error>;
    
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match Pin::new(&mut self.rx).poll(cx) {
            Poll::Ready(x) => Poll::Ready(x.map_err(|_| Error::msg("can't recv"))),
            Poll::Pending => Poll::Pending,
        }
    }
}

现在task.recv().await,您可以不使用task.await. 我还建议您实施或提供方法。否则,当您更改一个实现而忘记更改另一个时,您可能会遇到麻烦。Future recv

于 2021-03-01T22:43:56.127 回答