Я хочу сохранить будущее, которое мы иногда ожидаем, в структуре. Мой вариант использования - получить сигнал, чтобы мой обработчик сетевых пакетов корректно завершил работу. Минимальный пример может выглядеть следующим образом, с зависимостью от фьючерса 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(..)
, поэтому я получаю компиляцию ошибка:
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
. Это компилируется и, кажется, работает просто отлично - но это кажется хакерским. Есть ли «правильный» способ добиться этого?