Rust:在任务内执行取消引用的闭包



我有一些代码,它接受函数的向量,然后迭代它们并在每一步执行每个函数。我正在尝试将任务合并到 for 循环中,以便可以异步执行这些函数调用,而不是让第一个阻止第二个,依此类推......

let mut arr: Vec<|i32| -> i32> = Vec::new();
arr.push(function1);
arr.push(function2);
let ref num_in = os::args()[1];
let num_str = num_in.to_string();
let num = match from_str::<i32>(num_str.as_slice()) {
    Some(x) => x,
    None => panic!("Not a number"),
};
for f in arr.iter_mut() {
    spawn(proc(){
        println!("{}", (*f)(num.clone()));
    });
};

如果没有任务,只需在 for 循环中执行println!,这段代码运行得很好,但以一种阻止的方式运行,我试图通过使用任务来避免。在任务中,我收到这些错误和注释...

error: the trait 'core::kinds::Send' is not implemented for the type '&mut |i32| -> i32'

note: the closure that captures 'f' requires that all captured variables implement the trait 'core::kinds::Send'

代码中存在几个问题:

f,就像编译器告诉你的那样,是一个&mut |i32|->i32。它是对其中一个矢量元素的借用引用。此类借用的引用不能跨任务边界发送。这是防止悬空指针和内存安全错误的简单规则,因为如果涉及多个线程,则基于范围的生存期保证根本无法正常工作。

但即使是 |i32|->i32 型的东西目前也像借来的引用(通常(,因为它借用了它的环境。如果您没有捕获任何变量("空环境"(,则可以改用fn(i32) -> i32来获取可发送的内容。您可以将其视为一个简单的函数指针。

让其他任务执行带有自己环境的东西(如"未借用"(通常是通过proc完成的。这就是它的目的。出于这个原因,您已经在使用 proc s。编译器只是将f复制到proc中,这使得整个proc不可发送,因为借用的引用是不可发送的。

在不久的将来,我们将得到"未装箱的封口",这将使proc变得多余。然后,您应该能够使用 Vec<Box<FnOnce(i32)->i32 + Send>>Vec<Box<Fn(i32)->i32 + Send>> 作为 Vec<proc(i32)->i32> 的替代品。创建这些类型的框可能涉及boxmove关键字以及对 trait 对象的强制转换。

最新更新