尝试修改 Rc<RefCell<...>> 中的期货 Vec
Trying to modify a Vec of futures inside a Rc<RefCell<...>>
我尝试等待并从 Vec
期货中逐一删除期货。这是行不通的。我明白为什么它不起作用:Pin
不可复制。但是如何纠正这个错误呢?
extern crate futures;
use std::cell::{RefCell};
use std::rc::Rc;
use std::pin::Pin;
use std::future::Future;
use futures::channel::oneshot::Canceled;
use futures::executor::block_on;
use futures::future::select_all;
fn run_queries_body() {
let _futures: Vec<Pin<Box<dyn Future<Output=Result<(), Canceled>>>>> = Vec::new();
let futuresRc = Rc::new(RefCell::new(_futures)); // TODO: Cell instead
// This in actual could be called inside another future, so we need Rc<RefCell<...>>
let mut futures = futuresRc.borrow_mut();
let f3 = futures.iter().map(|x| *x);
let (_res, _idx, remaining_futures) = block_on(select_all(f3));
*futures = remaining_futures;
}
error[E0507]: cannot move out of `*x` which is behind a shared reference
--> src/lib.rs:16:37
|
16 | let f3 = futures.iter().map(|x| *x);
| ^^ move occurs because `*x` has type `std::pin::Pin<std::boxed::Box<dyn futures::Future<Output = std::result::Result<(), futures::channel::oneshot::Canceled>>>>`, which does not implement the `Copy` trait
问题不在于大头针 - 盒装未来可以安全地与其大头针一起移动,因为盒子意味着未来是 heap-allocated,所以移动盒子不会移动未来。该图钉用于禁止将未来 移出 其框,但您不要尝试这样做。您的代码无法编译,因为 Vec::iter()
遍历 references 到元素,并且您不能将对象移出引用,因为它会使原始值处于未定义状态.这种移动只允许用于可以简单复制的类型,例如数字或布尔值,这些类型由 Copy
特征标记。编译器的消息令人困惑,因为它提到了 Pin<...>
,但它这样做只是因为这是引用背后的文字类型,并且编译器报告所讨论的类型不是 Copy
,但没有暗示任何关于Pin
语义。
一个简单的解决方法是使 futures
成为一个选项向量。这允许您通过在 &mut Option<T>
上调用 Option::take
来拥有元素的可变迭代器,从而从向量中提取元素。这是 well-defined,因为它提取了值,但还在向量中的旧位置留下了 None
。
在您的情况下,您将使用 iter_mut()
(playground):
迭代向量
pub fn run_queries_body() {
let futures: Vec<Option<Pin<Box<dyn Future<Output = Result<(), Canceled>>>>>> = vec![];
let futures_rc = Rc::new(RefCell::new(futures));
let mut futures = futures_rc.borrow_mut();
let f3 = futures.iter_mut().map(|f| f.take().unwrap());
let (_res, _idx, remaining_futures) = block_on(select_all(f3));
*futures = remaining_futures.into_iter().map(Some).collect();
}
正如@Jmb 所指出的,一种更简单的方法是使用 Vec::drain
, which removes the elements from the vector and gives you an iterator over the removed elements (playground):
pub fn run_queries_body() {
let futures: Vec<Pin<Box<dyn Future<Output = Result<(), Canceled>>>>> = vec![];
let futures_rc = Rc::new(RefCell::new(futures));
let mut futures = futures_rc.borrow_mut();
let f3 = futures.drain(..);
let (_res, _idx, remaining_futures) = block_on(select_all(f3));
*futures = remaining_futures;
}
我尝试等待并从 Vec
期货中逐一删除期货。这是行不通的。我明白为什么它不起作用:Pin
不可复制。但是如何纠正这个错误呢?
extern crate futures;
use std::cell::{RefCell};
use std::rc::Rc;
use std::pin::Pin;
use std::future::Future;
use futures::channel::oneshot::Canceled;
use futures::executor::block_on;
use futures::future::select_all;
fn run_queries_body() {
let _futures: Vec<Pin<Box<dyn Future<Output=Result<(), Canceled>>>>> = Vec::new();
let futuresRc = Rc::new(RefCell::new(_futures)); // TODO: Cell instead
// This in actual could be called inside another future, so we need Rc<RefCell<...>>
let mut futures = futuresRc.borrow_mut();
let f3 = futures.iter().map(|x| *x);
let (_res, _idx, remaining_futures) = block_on(select_all(f3));
*futures = remaining_futures;
}
error[E0507]: cannot move out of `*x` which is behind a shared reference
--> src/lib.rs:16:37
|
16 | let f3 = futures.iter().map(|x| *x);
| ^^ move occurs because `*x` has type `std::pin::Pin<std::boxed::Box<dyn futures::Future<Output = std::result::Result<(), futures::channel::oneshot::Canceled>>>>`, which does not implement the `Copy` trait
问题不在于大头针 - 盒装未来可以安全地与其大头针一起移动,因为盒子意味着未来是 heap-allocated,所以移动盒子不会移动未来。该图钉用于禁止将未来 移出 其框,但您不要尝试这样做。您的代码无法编译,因为 Vec::iter()
遍历 references 到元素,并且您不能将对象移出引用,因为它会使原始值处于未定义状态.这种移动只允许用于可以简单复制的类型,例如数字或布尔值,这些类型由 Copy
特征标记。编译器的消息令人困惑,因为它提到了 Pin<...>
,但它这样做只是因为这是引用背后的文字类型,并且编译器报告所讨论的类型不是 Copy
,但没有暗示任何关于Pin
语义。
一个简单的解决方法是使 futures
成为一个选项向量。这允许您通过在 &mut Option<T>
上调用 Option::take
来拥有元素的可变迭代器,从而从向量中提取元素。这是 well-defined,因为它提取了值,但还在向量中的旧位置留下了 None
。
在您的情况下,您将使用 iter_mut()
(playground):
pub fn run_queries_body() {
let futures: Vec<Option<Pin<Box<dyn Future<Output = Result<(), Canceled>>>>>> = vec![];
let futures_rc = Rc::new(RefCell::new(futures));
let mut futures = futures_rc.borrow_mut();
let f3 = futures.iter_mut().map(|f| f.take().unwrap());
let (_res, _idx, remaining_futures) = block_on(select_all(f3));
*futures = remaining_futures.into_iter().map(Some).collect();
}
正如@Jmb 所指出的,一种更简单的方法是使用 Vec::drain
, which removes the elements from the vector and gives you an iterator over the removed elements (playground):
pub fn run_queries_body() {
let futures: Vec<Pin<Box<dyn Future<Output = Result<(), Canceled>>>>> = vec![];
let futures_rc = Rc::new(RefCell::new(futures));
let mut futures = futures_rc.borrow_mut();
let f3 = futures.drain(..);
let (_res, _idx, remaining_futures) = block_on(select_all(f3));
*futures = remaining_futures;
}