您如何称呼future ::从采用& mut self的方法中存储在结构中的Future上进行选择? [英] How do you call future::select on a Future stored in a struct from a method that takes &mut self?
问题描述
我想存储一个我们偶尔会在结构中等待的未来.我的用例是发出一个信号,通知我的网络数据包处理程序正常关闭.一个最小的例子可能是这样的,它依赖于期货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,
另请参阅:
- 为什么Iterator :: take_while拥有迭代器的所有权?
- 为什么在迭代器和读取特征之间by_ref().take()的用法不同?
- 在Rust中多次使用同一个迭代器
- 尝试转移所有权时无法移出借用的内容
- 不能移出借用的内容/不能移出共享引用的后面
- 暂时移出借用的内容
- 如何移出作为选项的结构字段?
- 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 ::从采用& mut self的方法中存储在结构中的Future上进行选择?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!