nat*_*ore 18 function-pointers channel rust
我试图弄清楚如何通过一个通道发送一个函数,以及如何避免额外的克隆,以便在另一端执行该函数.如果我在闭包内删除额外的克隆操作,我会收到以下错误:
error: cannot move out of captured outer variable in an 'Fn' closure
Run Code Online (Sandbox Code Playgroud)
忽略这个代码绝对没有任何东西,并使用全局可变静态这一事实Sender<T>
,它代表了我正在尝试实现的同时给出正确的编译器错误.这段代码不打算运行,只是编译.
use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
use std::collections::LinkedList;
use std::sync::mpsc::{Sender, Receiver};
type SafeList = Arc<Mutex<LinkedList<u8>>>;
type SendableFn = Arc<Mutex<(Fn() + Send + Sync + 'static)>>;
static mut tx: *mut Sender<SendableFn> = 0 as *mut Sender<SendableFn>;
fn main() {
let list: SafeList = Arc::new(Mutex::new(LinkedList::new()));
loop {
let t_list = list.clone();
run(move || {
foo(t_list.clone());
});
}
}
fn run<T: Fn() + Send + Sync + 'static>(task: T) {
unsafe {
let _ = (*tx).send(Arc::new(Mutex::new(task)));
}
}
#[allow(dead_code)]
fn execute(rx: Receiver<SendableFn>) {
for t in rx.iter() {
let mut guard = t.lock().unwrap();
let task = guard.deref_mut();
task();
}
}
#[allow(unused_variables)]
fn foo(list: SafeList) { }
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来解决这个错误和/或我应该通过渠道发送功能的另一种方式?
oli*_*obk 18
问题Fn()
是你可以多次调用它.如果您移出捕获的值,则下次调用时该值将不再可用.你需要一个FnOnce()
确保调用闭包也移出它,所以它已经消失了,不能再被调用.
没有办法了Arc<Mutex<(FnOnce() + Send + Sync + 'static)>>
.这将再次要求您静态保证在调用该函数后,没有其他人可以再次调用它.你不能,因为别人可能有另一个Arc
指向你的FnOnce
.您可以做的是将其装箱并发送Box<FnOnce() + Send + Sync + 'static>
.只有一个拥有者Box
.
麻烦的FnOnce()
是,你不能真正地调用它Box
,因为这需要将它移出Box
并调用它.但是我们不知道它的大小,所以我们无法将其移出Box
.将来,Box<FnOnce()>
闭包可能会直接使用.
"幸运的是"这个问题经常发生,所以有FnBox
.可悲的是,这需要每晚工作.此外,我无法弄清楚如何使用在该文档中描述的功能调用语法,但你可以手动调用call_box
上Box<FnBox()>
.在游乐场试试吧