Sharing a reference in multiple threads inside a function

87 Views Asked by At

I want to build a function that takes a HashMap reference as an argument. This HashMap should be shared between threads for read only access. The code example is very simple: I insert some value into the HashMap, pass it to the function and want antoher thread to read that value. I get an Error that the borrowed value does not live long enough at line let exit_code = test(&m);. Why is this not working?


use std::thread;
use std::collections::HashMap;
use std::sync::{Arc, RwLock };

fn main(){
    let mut m: HashMap<u32, f64> = HashMap::new();
    m.insert(0, 0.1);
    let exit_code = test(&m);
    std::process::exit(exit_code);
}

fn test(m: &'static HashMap<u32, f64>) -> i32{

    let map_lock = Arc::new(RwLock::new(m));

    let read_thread = thread::spawn(move || {
            if let Ok(r_guard) = map_lock.read(){
                println!("{:?}", r_guard.get(&0).unwrap());
            }
            
        });

    read_thread.join().unwrap();
    return 0;
}


if I don't put the 'static in the function signature for the HashMap argument, Arc::new(RwLock::new(m)); doesn't work. How can I sovlve this problem?

1

There are 1 best solutions below

0
On

A reference is not safe to share unless is 'static meaning that something will live for the extent of the program. Otherwise the compiler is not able to track the liveliness of the shared element.

You should wrap it outside of the function, and take ownership of an Arc:

use std::thread;
use std::collections::HashMap;
use std::sync::{Arc, RwLock };

fn main(){
    let mut map = HashMap::new();
    map.insert(0, 0.1);
    let m = Arc::new(RwLock::new(map));
    let exit_code = test(m);
    std::process::exit(exit_code);
}

fn test(map_lock: Arc<RwLock<HashMap<u32, f64>>>) -> i32 {


    let read_thread = thread::spawn(move || {
            if let Ok(r_guard) = map_lock.read(){
                println!("{:?}", r_guard.get(&0).unwrap());
            }
            
        });

    read_thread.join().unwrap();
    return 0;
}

Playground