1

I am writing code that divides a vector into chunks which are given to different threads for processing. Thread.join() is called on all the threads guaranteeing that they no longer have access to the vector and then the code returns the vector. The threads, however, (understandably) require a static lifetime to ensure that the data isn't dropped while they have access to it. Is there any way around this?

I have looked into both Arc and Mutex (although I'm not entirely familiar with either) and have found them to create problems with the original mutability. The alternative, as far as I'm aware, is each thread returning a vector and each of these vectors having to be joined together as I require the output to be in a single vector which I expect to be quite slow as I'm expecting a vector of size 3840 * 2160.

{
    let mut data: Vec<u8> = vec![0; (render_config.resolution.0 * render_config.resolution.1 * 3) as usize];
    
    let chunks = data.chunks_mut(((render_config.resolution.0 * render_config.resolution.1 * 3) / 12) as usize);

    let mut ts = Vec::with_capacity(chunks.len());

    let mut offset = 0;
    for chunk in chunks {
        ts.push(thread::spawn(|| { Self::get_image_sub_threaded(self.clone(), render_config.clone(), is_screenshot, chunk, offset); }));
        offset += chunk.len();
    }

    for t in ts {
        t.join();
    }

    data
}
error[E0597]: `data` does not live long enough
  --> src\rendering\camera.rs:26:22
   |
26 |         let chunks = data.chunks_mut(((render_config.resolution.0 * render_config.resolution.1 * 3) / 12) as usize);
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
32 |             ts.push(thread::spawn(|| { Self::get_image_sub_threaded(self.clone(), render_config.clone(), is_screenshot, chunk, offset); }));
   |                     ---------------------------------------------------------------------------------------------------------------------- argument requires that `data` is borrowed for `'static`
...
41 |     }
   |     - `data` dropped here while still borrowed

Edit: While I have found the answer to this question in the linked question, I thought I'd put my quickly cobbled-together solution here incase anyone finds it useful:

pub fn get_image_threaded(&self, render_config: &RenderConfig) -> Vec<u8> {
    let mut data: Vec<u8> = vec![0; (render_config.screenshot_resolution.0 * render_config.screenshot_resolution.1 * 3) as usize];
    
    let chunks = data.chunks_mut(((render_config.screenshot_resolution.0 * render_config.screenshot_resolution.1 * 3) as usize) / num_cpus::get());
    println!("CPUs available: {}", num_cpus::get());
    
    // let mut offset = 0;
    // for chunk in chunks {
    //     ts.push(thread::spawn(|| { Self::get_image_sub_threaded(self.clone(), render_config.clone(), is_screenshot, chunk, offset); }));
    //     offset += chunk.len();
    // }

    thread::scope(|scope| {
        let mut ts = Vec::with_capacity(chunks.len());
        let mut offset = 0;
        let mut i: u32 = 0;
        for chunk in chunks {
            let o = offset;
            let len = chunk.len() / 3;
            ts.push(scope.spawn(move || { Self::get_image_sub_threaded(self.clone(), render_config.clone(), true, chunk, o, i); }));
            offset += len;
            i += 1;
        }
        for t in ts {
            t.join().unwrap();
        }
    });

    data
}

0 Answers0