您如何称呼future ::从采用& mut self的方法中存储在结构中的Future上进行选择? [英] How do you call future::select on a Future stored in a struct from a method that takes &mut self?

查看:58
本文介绍了您如何称呼future ::从采用& mut self的方法中存储在结构中的Future上进行选择?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想存储一个我们偶尔会在结构中等待的未来.我的用例是发出一个信号,通知我的网络数据包处理程序正常关闭.一个最小的例子可能是这样的,它依赖于期货0.3:

I want to store a future that we occasionally await in a struct. My use-case is to have a signal to tell my network packet handler to shut down gracefully. A minimal example could look like this, with a dependency on futures 0.3:

use futures::{
    executor::block_on,
    future::{pending, select, Either, Future},
}; // 0.3.4

struct Foo<F: Future + Unpin> {
    fut: F,
    fut_opt: Option<F>,
}

impl<F: Future + Unpin> Foo<F> {
    async fn wait(self: &mut Self) {
        let bar = pending::<&str>();
        match select(self.fut, bar).await {
            Either::Left(_) => println!("foo"),
            Either::Right(_) => println!("bar"),
        }
    }

    async fn wait_optional(self: &mut Self) {
        let bar = pending::<&str>();
        if let Some(foo) = self.fut_opt.take() {
            match select(foo, bar).await {
                Either::Left(_) => println!("foo"),
                Either::Right((_, foo_fut)) => {
                    self.fut_opt.replace(foo_fut);
                    println!("bar")
                }
            }
        }
    }
}

fn main() {
    let mut foo = Foo {
        fut: pending::<()>(),
        fut_opt: Option::from(pending::<()>()),
    };

    block_on(foo.wait())
}

问题是 select 想要在 fn wait(..)版本中移动值,所以我遇到了编译错误:

The problem is that select wants to move the value in the fn wait(..) version, so I'm getting a compile error:

error[E0507]: cannot move out of `self.fut` which is behind a mutable reference
  --> src/main.rs:14:22
   |
14 |         match select(self.fut, bar).await {
   |                      ^^^^^^^^ move occurs because `self.fut` has type `F`, which does not implement the `Copy` trait

我想出的解决方法可以在 fn wait_optional 中看到:我(ab)使用 Option 存储未来,在需要时将其取出,然后将其放回原处,因为 select 会在 Either 中返回未等待的将来.这样可以编译,并且看起来工作正常-但感觉很hack.是否有适当"的方式来实现这一目标?

A workaround I came up with can be seen in fn wait_optional: I'm (ab)using an Option to store the future, take it out when needed and then put it back in as select returns the unawaited future in Either. This compiles and seems to work just fine - but it feels hacky. Is there a "proper" way for achieving this?

推荐答案

对未来进行可变的引用:

Take a mutable reference to the future:

use futures::{
    executor::block_on,
    future::{pending, select, Either, Future},
}; // 0.3.4

struct Foo<F: Future + Unpin> {
    fut: F,
}

impl<F: Future + Unpin> Foo<F> {
    async fn wait(&mut self) {
        let bar = pending::<&str>();
        match select(&mut self.fut, bar).await {
            Either::Left(_) => println!("foo"),
            Either::Right(_) => println!("bar"),
        }
    }
}

fn main() {
    let mut foo = Foo {
        fut: pending::<()>(),
    };

    block_on(foo.wait())
}

这是因为 Future 实现了对 Future 的任何可变引用,但有一定的限制:

This is because Future is implemented for any mutable reference to a Future with certain restrictions:

impl<'_, F> Future for &'_ mut F
where
    F: Unpin + Future + ?Sized, 

另请参阅:

  • Why does Iterator::take_while take ownership of the iterator?
  • Why does the usage of by_ref().take() differ between the Iterator and Read traits?
  • Using the same iterator multiple times in Rust
  • Cannot move out of borrowed content when trying to transfer ownership
  • Cannot move out of borrowed content / cannot move out of behind a shared reference
  • Temporarily move out of borrowed content
  • How do I move out of a struct field that is an Option?

这篇关于您如何称呼future ::从采用&amp; mut self的方法中存储在结构中的Future上进行选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆