gpt4 book ai didi

rust - 闭包: expected a closure that implements the `Fn` trait,内部的Arc >,但此闭包仅实现 `FnOnce`

转载 作者:行者123 更新时间:2023-12-03 11:43:48 25 4
gpt4 key购买 nike

我正在尝试与闭包共享一个Arc<Mutex<T>>。我收到closure is FnOnce because it moves the variable shared_wake_deque_ out of its environment的错误:

use core::task::{Context, Poll, Waker};
use hyper::client::connect::{Connection, Connected};
use std::sync::{Arc, Mutex};
use std::collections::VecDeque;

pub type OnPollRead = Arc<dyn Fn(&mut Context<'_>, &mut tokio::io::ReadBuf<'_>) -> Poll<std::io::Result<()>> + Send + Sync>;
pub type OnPollWrite = Arc<dyn Fn(&mut Context<'_>, &[u8]) -> Poll<core::result::Result<usize, std::io::Error>> + Send + Sync>;

#[derive(Clone)]
pub struct CustomTransporter {
on_poll_read: Option<OnPollRead>,
on_poll_write: Option<OnPollWrite>,
}

pub struct OVPNClient {
}

impl OVPNClient {
pub fn send(&self, buffer: &[u8]) {

}
}

unsafe impl Send for OVPNClient {}


unsafe impl Send for CustomTransporter {}

impl CustomTransporter {
pub fn new(on_poll_read: Option<OnPollRead>, on_poll_write: Option<OnPollWrite>) -> CustomTransporter {
CustomTransporter{
on_poll_read: on_poll_read,
on_poll_write: on_poll_write
}
}
}

fn main () {
let openvpn_client = Arc::new(Mutex::new(OVPNClient{}));

let shared_wake_deque = Arc::new(Mutex::new(VecDeque::<Waker>::new()));

let shared_wake_deque_ = shared_wake_deque.clone();
let on_poll_read = Arc::new(|context: &mut Context, buffer: &mut tokio::io::ReadBuf| -> Poll<std::io::Result<()>> {
let shared_wake_deque__ = shared_wake_deque_;
Poll::Ready(Ok(()))
});

let on_poll_write = Arc::new(|context: &mut Context, buffer: &[u8]| -> Poll<core::result::Result<usize, std::io::Error>>{
openvpn_client.lock().unwrap().send(buffer);
Poll::Ready(Ok(0))
});

let connector = CustomTransporter::new(Some(on_poll_read), Some(on_poll_write));
}
错误:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
--> src/main.rs:44:33
|
44 | let on_poll_read = Arc::new(|context: &mut Context, buffer: &mut tokio::io::ReadBuf| -> Poll<std::io::Result<()>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this closure implements `FnOnce`, not `Fn`
45 | let shared_wake_deque__ = shared_wake_deque_;
| ------------------ closure is `FnOnce` because it moves the variable `shared_wake_deque_` out of its environment
...
54 | let connector = CustomTransporter::new(Some(on_poll_read), Some(on_poll_write));
| ------------ the requirement to implement `Fn` derives from here
我知道移动只能发生一次。我什至没有关闭 move。如您所见,我正在尝试使用 Arc<Mutex<T>>的副本,因此我并未完全移动它。您可以看到我尝试了克隆,所以我移动了仅在此闭包上使用过的变量,并且不再使用了,但是它不起作用。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d996163f5d2a6e9322af9a7472581ce6

最佳答案

因为你有

let shared_wake_deque__ = shared_wake_deque_;
作为一个简单的任务,它与
let foo = vec![];
let foo2 = foo;
运行代码将vec的所有权从 foo转移到 foo2。因为您在lambda中具有此属性,所以运行显式会将 shared_wake_deque_值的所有权转移到 shared_wake_deque__,这意味着不再可以使用 shared_wake_deque_。为了做到这一点,要求 on_poll_read只能运行一次,因为否则,很多事情将试图拥有同一对象( on_poll_read,因为它需要拥有它才能在将来的调用中使用,并且先前调用中的 shared_wake_deque__也仍然必须拥有它)。因为那只能由一件东西所有,所以这将违反Rust的安全保证,因此您会遇到此错误。
最有可能的是,您想要的是给我们的引用,例如
let shared_wake_deque__ = &shared_wake_deque_;
通过使用对 shared_wake_deque_的引用,该闭包可以运行多次并给出多个共享引用。但是,仅此一项,您就可以
error[E0597]: `shared_wake_deque_` does not live long enough
因为您要尝试引用在闭包外部声明的变量,并且闭包可以在删除 shared_wake_deque_后运行。为了解决这个问题,您需要关闭以获取 shared_wake_deque_的所有权,这可以通过使用 move关键字来实现,例如
let on_poll_read = Arc::new(move |context: &mut Context, buffer: &mut tokio::io::ReadBuf| -> Poll<std::io::Result<()>> {
let shared_wake_deque__ = &shared_wake_deque_;
那么 on_poll_write也会出现相同的问题,因此也需要是 move:
let on_poll_write = Arc::new(move |context: &mut Context, buffer: &[u8]| -> Poll<core::result::Result<usize, std::io::Error>>{
( Rust playground)

关于rust - 闭包: expected a closure that implements the `Fn` trait,内部的Arc <Mutex <T >>,但此闭包仅实现 `FnOnce`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66502376/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com