Mandragor
Mandragor

Reputation: 5574

Pass a matrix (Vec<Vec<f64>>) readonly to multiple threads

I am new to Rust and I am struggling with the concept of borrowing.

I want to load a Vec<Vec<f64>> matrix and then process it in parallel. However when I try to compile this piece of code I get error: capture of moved value: `matrix` [E0382] at the let _ = line.

This matrix is supposed to be readonly for the threads, they won't modify it. How can I pass it readonly and make the "moved value" error go away?

fn process(matrix: &Vec<Vec<f64>>) {
    // do nothing for now
}

fn test() {
    let filename = "matrix.tsv";
    // loads matrix into a Vec<Vec<f64>>
    let mut matrix = load_matrix(filename);

    // Determine number of cpus
    let ncpus = num_cpus::get();
    println!("Number of cpus on this machine: {}", ncpus);
    for i in 0..ncpus {
        // In the next line the "error: capture of moved value: matrix" happens
        let _ = thread::spawn(move || {
            println!("Thread number: {}", i);
            process(&matrix);
        });
    }
    let d = Duration::from_millis(1000 * 1000);
    thread::sleep(d);
}

Upvotes: 4

Views: 870

Answers (1)

A.B.
A.B.

Reputation: 16660

Wrap the object to be shared into an Arc which stands for atomically reference counted (pointer). For each thread, clone this pointer and pass ownership of the clone to the thread. The wrapped object will be deallocated when it's no longer used by anything.

fn process(matrix: &Vec<Vec<f64>>) {
    // do nothing for now
}

fn test() {
    use std::sync::Arc;
    let filename = "matrix.tsv";
    // loads matrix into a Vec<Vec<f64>>
    let mut matrix = Arc::new(load_matrix(filename));

    // Determine number of cpus
    let ncpus = num_cpus::get();
    println!("Number of cpus on this machine: {}", ncpus);
    for i in 0..ncpus {
        let matrix = matrix.clone();
        let _ = thread::spawn(move || {
            println!("Thread number: {}", i);
            process(&matrix);
        });
    }
    let d = Duration::from_millis(1000 * 1000);
    thread::sleep(d);
}

Upvotes: 4

Related Questions