Hello!
Like many others, I am butting heads with the borrow checker, and I can't seem to figure out what exactly I should be doing in my case.
I have checked out a few related issues, but what I am doing isn't exactly the same.
I am attempting to process some data in parallel, while using Arc to share the (read only) data across those processes.
I am aware Rust sees sending the Arc and it's contents into multiple processes as dangerous, since it "could" outlive the program.
However, it's clear I am immediately joining everything before the end of the function.
How do I convince Rust to let me do this? What changes do I need to make for this to work?
I tried following the compilers first suggestion, adding a 'static for &Data, but on trying it, and researching it, it's obvious I don't want the data to live for the full program length.
The [E0495] came when I tried to use 'a for &Data, which I could not get to work, in several combinations.
There must be a way to do this?
Here is my sample code, it is similar to what I am actually doing, but with all of the rest of it stripped away:
use std::thread::spawn;
use std::sync::Arc;
extern crate num_cpus;
use num_cpus::get;
struct Reader {
a_count : usize,
a_vec : Vec<i64>
}
struct ReaderContainer {
rdrs : Vec<Box<Reader>>
}
struct Data {
repeat : usize,
something : Vec<i64>
}
fn main() {
let length = a_secondary_function();
println!(
"length of Reader vec in container: {}",
length
);
}
fn a_secondary_function() -> usize {
let data_chunk : Data = get_data();
a_function_in_the_middle(&data_chunk)
}
fn a_function_in_the_middle(data_chunk : &Data) -> usize {
let mut container : ReaderContainer = make_container();
do_a_bunch_in_parallel(&data_chunk, &mut container);
container.rdrs.len()
}
fn do_a_bunch_in_parallel(data_chunk : &Data, container : &mut ReaderContainer) {
let shared_data = Arc::new(data_chunk);
let mut t_handles = vec![];
for _ in 0 .. get() {
let arc_data = shared_data.clone();
let boxed_reader_opt = container.rdrs.pop();
match boxed_reader_opt {
Some(boxed_reader) => {
t_handles.push(
spawn(
move || {
process(boxed_reader, arc_data)
}
)
);
}
None => {
panic!("//(0 o 0)//");
}
}
}
for handler in t_handles {
container.rdrs.push(handler.join().unwrap());
}
}
fn process(data_reader : Box<Reader>, shared_data : Arc<&Data>) -> Box<Reader> {
let mut read : Reader = *data_reader;
let inner_data : &Data = &shared_data;
let borrowed_vec : &Vec<i64> = &shared_data.something;
for i in 0 .. read.a_vec.len() {
read.a_vec[i] = borrowed_vec[i];
}
let mut a : usize = 0;
// simulates doing a bunch of stuff.
for k in 0 .. shared_data.repeat {
a += k;
}
read.a_count = a;
Box::new(read)
}
fn get_data() -> Data {
Data {
repeat : 100000000,
something : vec![1; 10]
}
}
fn make_Reader() -> Reader {
Reader {
a_count : 0,
a_vec : vec![10; 10]
}
}
fn make_container() -> ReaderContainer {
let mut readers : Vec<Box<Reader>> = Vec::new();
for i in 0 .. get() {
readers.push(
Box::new(
make_Reader()
)
);
}
ReaderContainer {
rdrs : readers
}
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0621]: explicit lifetime required in the type of `data_chunk`
--> src/main.rs:51:21
|
40 | fn do_a_bunch_in_parallel(data_chunk : &Data, container : &mut ReaderContainer) {
| ----- help: add explicit lifetime `'static` to the type of `data_chunk`: `&'static Data`
...
51 | spawn(
| ^^^^^ lifetime `'static` required
error: aborting due to previous error
For more information about this error, try `rustc --explain E0621`.
error: could not compile `playground`
To learn more, run the command again with --verbose.