As far as I learned, in Rust to get access to fields from context to the spawned thread I need to move them (not only borrow them) which is ok. Let's consider example:
use std::thread;
fn main() {
let v1 = vec![1, 2, 3];
let v2 = vec![4, 5, 6];
let handle = thread::spawn(move || {
println!("{:?}", v1);
println!("{:?}", v2);
(v1, v2)
});
let (v1, v2) = handle.join().unwrap();
println!("{:?}", v1);
println!("{:?}", v2);
}
Here v1 and v2 are moved to thread and if I want to use them again in main thread I need to return them from thread and assign them again using handle.join() (which waits until thread is done which is also nice).
My question: is it possible to somehow return all moved values back to their original fields? I can imagine that there is much more than just two fields I would move and writing down all of them to return and assign them again would look obscure.
CodePudding user response:
If you need to move a lot of variables together, the obvious way to do that is with a struct.
use std::thread;
struct ManyFields {
v1: Vec<i32>,
v2: Vec<i32>,
// ...and many others...
}
fn main() {
let fields = ManyFields {
v1: vec![1, 2, 3],
v2: vec![4, 5, 6],
};
let handle = thread::spawn(move || {
println!("{:?}", fields.v1);
println!("{:?}", fields.v2);
fields
});
let fields = handle.join().unwrap();
println!("{:?}", fields.v1);
println!("{:?}", fields.v2);
// and many others...
}
Depending on exactly why you needed the thread to take ownership, you may be able to avoid that altogether using scoped threads. Scopes introduce an explicit lifetime in which a thread is guaranteed to finish, allowing you borrow values as long as they outlive the scope.
use crossbeam::scope;
fn main() {
let v1 = vec![1, 2, 3];
let v2 = vec![4, 5, 6];
scope(|scope| {
scope.spawn(|_| {
println!("{:?}", v1);
println!("{:?}", v2);
});
})
.unwrap();
println!("{:?}", v1);
println!("{:?}", v2);
}
From rust 1.63 you will be able to do this without a third party crate, as it will be part of std.