I try to process an array with multiple worker threads, just like Rayon's par_iter()
function, but i want to have a mutable reference target
, one for each thread.
I have a simple function like this
pub fn parallel_map_vector<A:Sync,T:Send,B:Send>(a:&[A], t:&mut [T], b:&mut [B], f:impl Fn(&A,&mut T)+Send+Sync){
assert_eq!(a.len(),b.len());
let atomic_counter = AtomicUsize::new(0);
crossbeam::scope(|scope| {
for target in t {
scope.spawn( |_| {
loop {
let idx = atomic_counter.fetch_add(1, Ordering::Relaxed);
if idx < a.len() {unsafe{std::slice::from_raw_parts_mut(b,b_len)};
f(&a[idx], target)
}else{
break
}
}
});
}
}).unwrap();
}
For some reason i keep getting the error
error[E0373]: closure may outlive the current function, but it borrows `target`, which is owned by the current function
--> htm/src/parallel.rs:11:26
|
9 | crossbeam::scope(|scope| {
| ----- has type `&crossbeam::thread::Scope<'1>`
10 | for target in t {
11 | scope.spawn( |_| {
| ^^^ may outlive borrowed value `target`
...
17 | f(&a[idx], target)
| ------ `target` is borrowed here
|
note: function requires argument type to outlive `'1`
--> htm/src/parallel.rs:11:13
|
11 | / scope.spawn( |_| {
12 | | loop {
13 | | let idx = atomic_counter.fetch_add(1, Ordering::Relaxed);
14 | | if idx < a.len() {
... |
21 | | }
22 | | });
| |______________^
help: to force the closure to take ownership of `target` (and any other referenced variables), use the `move` keyword
|
11 | scope.spawn( move |_| {
but when i try it in rust playground it compiles without problem https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0a10cbfd2f135975f4682c843664d539 What could be wrong here? The code looks safe to me.