rust - 无法移出 `Fn` 闭包中捕获的外部变量

标签 rust function-pointers channel

我正在尝试弄清楚如何通过 channel 发送函数,以及如何避免额外的克隆以便在另一端执行该函数。如果我删除闭包内的额外克隆操作,我会收到以下错误:

error: cannot move out of captured outer variable in an 'Fn' closure

忽略此代码完全不执行任何操作并使用全局可变静态 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) { }

是否有更好的方法来解决该错误和/或我应该通过 channel 发送函数的其他方式?

最佳答案

Fn() 的问题是你可以多次调用它。如果您移出捕获的值,则该值在下一次调用时将不再可用。你需要一个FnOnce()以确保调用闭包也移出它,所以它已经消失并且不能再次调用。

没有办法得到 Arc<Mutex<(FnOnce() + Send + Sync + 'static)>> .这将再次要求您静态地保证在调用该函数后,没有其他人可以再次调用它。你不能,因为其他人可能有另一个 Arc指向你的 FnOnce .您可以做的是将其装箱并作为 Box<FnOnce() + Send + Sync + 'static> 发送。 . Box 的拥有者只有一个.

FnOnce() 的问题是的,当它在 Box 中时,你真的不能调用它吗? ,因为这需要将其移出 Box并调用它。但是我们不知道它的大小,所以我们不能将它移出 Box。 .以后Box<FnOnce()>闭包可能会直接可用。

“幸运的是”这个问题发生的频率更高,所以有 FnBox .遗憾的是,这需要每晚才能工作。我也不知道如何使用文档中描述的函数调用语法,但您可以手动调用 call_boxBox<FnBox()> 上.在 Playground 中试用

关于rust - 无法移出 `Fn` 闭包中捕获的外部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33662098/

相关文章:

rust - 翻转 boolean 值的最快方法

rust - 在对迭代器进行分区时,未为Vec实现特征Extend

c++ - 函数指针作为参数

VBScript 函数作为参数,或类似的构造

android - 路由器管理员使用 android 以编程方式更改 Wi-Fi 信道

function - 以下涉及 Go 中 channel 的函数参数有什么区别?

rust - 拆分字符串并返回 Vec<String>

c - 是否可以交换 C 函数?

python - 如何在 Python OpenCV 中读取 TIFF 图像的 alpha channel ?

rust - 令人困惑的错误消息? (解包运算符)