rust - 弧> 内部闭包:期望一个实现了 `Fn` 特性的闭包,但这个闭包只实现了 `FnOnce`
问题描述
我正在尝试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>>
所以我并没有完全移动它。您可以看到我尝试了克隆,因此我移动了一个仅在此闭包中使用的变量,并且不再使用,但它不起作用。
解决方案
因为你有
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>>{
(锈操场)
推荐阅读
- google-cloud-platform - cloud-builds pub/sub 主题似乎未列出或无法访问
- unity3d - 从 Unity 上传的 Google Play 未更新
- python - 如何在单元格中将txt文件转换为csv文件
- python - 熊猫如何根据后面的行过滤前面的行
- c# - 错误 CS1703 在构建 Enterprise Bot Framework 项目时已导入具有相同标识的多个程序集
- php - 创建多维数组
- java - Saxparser:格式不正确(无效标记)
- amazon-web-services - 如何在代码中将 nginx 部署到 AWS Fargate?
- mysql - 如何使用 mysql unix_timestamp() 作为自增的起点?
- python - 无法创建 Django 模型的实例