【发布时间】:2017-07-25 19:32:33
【问题描述】:
我一直在研究一个函数,该函数将使用 Rust 和线程将一堆文件从源复制到目标。我在让线程共享迭代器时遇到了一些麻烦。借钱系统我还不习惯:
extern crate libc;
extern crate num_cpus;
use libc::{c_char, size_t};
use std::thread;
use std::fs::copy;
fn python_str_array_2_str_vec<T, U, V>(_: T, _: U) -> V {
unimplemented!()
}
#[no_mangle]
pub extern "C" fn copyFiles(
sources: *const *const c_char,
destinies: *const *const c_char,
array_len: size_t,
) {
let src: Vec<&str> = python_str_array_2_str_vec(sources, array_len);
let dst: Vec<&str> = python_str_array_2_str_vec(destinies, array_len);
let mut iter = src.iter().zip(dst);
let num_threads = num_cpus::get();
let threads = (0..num_threads).map(|_| {
thread::spawn(|| while let Some((s, d)) = iter.next() {
copy(s, d);
})
});
for t in threads {
t.join();
}
}
fn main() {}
我遇到了这个我无法解决的编译错误:
error[E0597]: `src` does not live long enough
--> src/main.rs:20:20
|
20 | let mut iter = src.iter().zip(dst);
| ^^^ does not live long enough
...
30 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
error[E0373]: closure may outlive the current function, but it borrows `**iter`, which is owned by the current function
--> src/main.rs:23:23
|
23 | thread::spawn(|| while let Some((s, d)) = iter.next() {
| ^^ ---- `**iter` is borrowed here
| |
| may outlive borrowed value `**iter`
|
help: to force the closure to take ownership of `**iter` (and any other referenced variables), use the `move` keyword, as shown:
| thread::spawn(move || while let Some((s, d)) = iter.next() {
我已经看过以下问题:
Value does not live long enough when using multiple threads
我没有使用chunks,我想尝试通过线程共享一个迭代器,尽管创建块将它们传递给线程将是经典的解决方案。
Unable to send a &str between threads because it does not live long enough 我已经看到了一些使用通道与线程通信的答案,但我不太确定使用它们。应该有一种更简单的方法来通过线程共享一个对象。
Why doesn't a local variable live long enough for thread::scoped
这引起了我的注意,scoped 应该修复我的错误,但由于它位于不稳定的通道中,我想看看是否有另一种方法可以使用 spawn。
有人可以解释我应该如何修复生命周期以便可以从线程中访问迭代器吗?
【问题讨论】:
-
@Shepmaster,所有线程都将共享耻辱迭代器,对于块解决方案,所有线程都有不同的迭代器。但是,如果是最便宜和/或最简单的解决方案,我会继续这样做:)
-
@DanielSanchez,您可以使用
Arc<Mutex<...>>Playground 共享迭代器 -
您的代码实际上不会并行运行:它会创建并立即一个接一个地加入线程,因为
map是惰性的。你应该使用 for 循环,或者collect结果。 -
@interjay,好的,我将尝试收集并仅使用块并对其进行迭代以向线程发送垃圾邮件。谢谢!
标签: multithreading rust borrowing