Borrowed value inside async task

How to use a borrowed value inside an async task?

async fn main(){

    let mut map:HashMap<String, Sender<i32>> = HashMap::new();
    
    async fn send_msg(map: &mut HashMap<String, Sender<i32>>){

        let (s, r) = bounded::<i32>(1);        
        map.insert(String::from("id"), s);
        r.recv().await;
    }

    task::spawn(send_msg(&mut map)); // compiler already complains here

   somefn(map) // need to use map afterwards too

    println!("{}", "Ok()");

}
error[E0597]: `map` does not live long enough
  --> src\main.rs:38:23
   |
38 |     task::spawn(send_msg(&mut map));
   |                 ------^^^^^^^^-
   |                 |     |
   |                 |     borrowed value does not live long enough
   |                 argument requires that `map` is borrowed for `'static`
...
55 | }
   | - `map` dropped here while still borrowed

pretty sure this is about lifetimes...

The prerequisite for spawning a task is that it doesn't borrow anything. This is so that it cannot be made invalid (holding references to deallocated memory) by the function that spawned it exiting (or being cancelled, if it's an async fn).

You will need to design so that anything the task need is owned, or shared with Arc, not borrowed. Maybe you could use a channel to send s to the owner of the map?

1 Like

making it owned would be really hard, because I might use the "map" later on.

I guess Arc should work.

I don't know if this works, how do I access the map inside arc inside mutex?

    let mut map:Arc<Mutex<HashMap<String, Sender<i32>>>> = Arc::new(Mutex::new(HashMap::new()));

    let (s, r) = bounded::<i32>(1);

    let x = Arc::clone(&mut map);
    
    x.insert(String::from("lol"), s);
    
    async fn send_msg(map: &mut HashMap<String, Sender<i32>>){

        let (s, r) = bounded::<i32>(1);
        
        map.insert(String::from("id"), s);
        
        r.recv().await;
    }

You will need to lock the Mutex whenever you want access to the data it owns:

use std::sync::{Arc, Mutex};

async fn main(){
    let map = Arc::new(Mutex::new(HashMap::new()));
    
    async fn send_msg(map: Arc<Mutex<HashMap<String, Sender<i32>>>>){
        let (s, mut r) = bounded::<i32>(1);        
        map.lock().expect("lock poisoned").insert(String::from("id"), s);
        r.recv().await;
    }

    task::spawn(send_msg(map.clone())); // compiler already complains here

    somefn(map); // need to use map afterwards too

    println!("{}", "Ok()");
}
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.