是否有一种方法可以使Rust闭包仅将一些变量移入其中?

问题描述 投票:3回答:1

为了确保不陷入XY问题,这是我正在尝试做的事情:

  1. 我有
    • 带有设置的常规struct
    • 我想调整并使用的额外变量设置。
  2. 对于整数范围内的所有可能值,我想将此变量设置为该值来启动(作用域)线程。 (根据此值,它们执行的工作会略有不同)。
  3. 但是,这些线程中的每一个都应该能够读取常规设置结构。

在伪锈中:

extern crate crossbeam;

struct Settings {
  // ... many fields
}

fn main() {
  crossbeam::scope(|scope| {
    for score in 0..max_feasible_score {
      scope.spawn(|_| {
         let work_result = do_cool_computation(&settings, score);
         println!(work_result);
      }
    }
  }).unwrap();
}

现在无法编译。 Rust抱怨score被借用到可能超过其外部功能的闭包中,并建议更改scope.spawn闭包参数以转换为move || {...}闭包。

但是,这将使&settings无效,因为第一次循环迭代将在移动闭包中获得settings的所有权。

[使其唯一可行的方法就是例如将Settings结构复制到每个线程中(在我的实际应用中这是相当昂贵的),或在settings周围引入一个圆弧,这也感到有点不幸。

我们有没有办法在这里规避引用计数?有没有一种方法可以将score移入内部闭包,同时仍然允许引用settings

multithreading rust closures move-semantics lifetime
1个回答
4
投票

我在rayon::scope的文档中找到了一个答案,该答案恰好与以下问题有关:“ [从有作用域的线程范围内访问堆栈数据]”。该页面上还有一个示例,比该问题中的伪代码更清楚。

事实证明,您可以:-使用移动闭包,但在外部作用域中通过用引用将其阴影化来引用变量,因此使用let settings = &settings:]通过引用而不是按值捕获它们

fn main() {
  crossbeam::scope(|scope| {
    let settings = &settings; // refer to outer variable by reference
    for score in 0..max_feasible_score {
      scope.spawn(move |_| {
         let work_result = do_cool_computation(&settings, score);
         println!(work_result);
      }
    }
  }).unwrap();
}
  • 使用普通的闭包,仅通过使用let score = score在闭包内隐藏所需变量,即可移动所需的变量:
fn main() {
  crossbeam::scope(|scope| {
    for score in 0..max_feasible_score {
      scope.spawn(|_| {
         let score = score; // capture only score 
         let work_result = do_cool_computation(&settings, score);
         println!(work_result);
      }
    }
  }).unwrap();
}

所以:

  • 是,可以仅将一个或某些变量移至闭包中(而不是全部或不移动。)
  • 是,可以用于“规避”引用计数。
© www.soinside.com 2019 - 2024. All rights reserved.