How to access a map inside mutex inside arc?

I'm finding myself having to use arc due to a timer function that runs async and accesses some values in outer scope. The solution is either moving or sharing. I need to share the value using arc:

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

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

    let mut x = Arc::clone(&mut map).lock().unwrap();
    
    x.insert(String::from("id"), s);
error[E0599]: no method named `insert` found for enum `Result` in the current scope
    --> src\main.rs:34:7
     |
34   |     x.insert(String::from("id"), s);
     |       ^^^^^^
     |
note: the method `insert` exists on the type `std::sync::MutexGuard<'_, HashMap<std::string::String, async_std::channel::Sender<i32>>>`
error[E0716]: temporary value dropped while borrowed
  --> src\main.rs:32:17
   |
32 |     let mut x = Arc::clone(&mut map).lock().unwrap();
   |                 ^^^^^^^^^^^^^^^^^^^^                - temporary value is freed at the end of this statement
   |                 |
   |                 creates a temporary which is freed while still in use
33 |
34 |     x.insert(String::from("id"), s);
   |     ------------------------------- borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value

This code, after adding necessary imports, yields another (expected) error (playground):

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:11:17
   |
11 |     let mut x = Arc::clone(&mut map).lock().unwrap();
   |                 ^^^^^^^^^^^^^^^^^^^^                - temporary value is freed at the end of this statement
   |                 |
   |                 creates a temporary which is freed while still in use
12 |     
13 |     x.insert(String::from("id"), s);
   |     ------------------------------- borrow later used here
   |
help: consider using a `let` binding to create a longer lived value
   |
11 ~     let binding = Arc::clone(&mut map);
12 ~     let mut x = binding.lock().unwrap();
   |

And after applying compiler suggestion, it builds successfully. What's the code with the actual problem?

I had a version without unwrap() i think. Both don't compile.

I guess this works

    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.lock().unwrap().insert(String::from("id"), s);
    

It's entirely unnecessary to clone the Arc or to make it mutable, though.

where do I have to remove mut?

In your four-line snippet above, you can remove the mut from the first line, and remove the third line altogether (and use map directly on the fourth line).

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.