Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot move data out of a Mutex

Consider the following code example, I have a vector of JoinHandlers in which I need it iterate over to join back to the main thread, however, upon doing so I am getting the error error: cannot move out of borrowed content.

let threads = Arc::new(Mutex::new(Vec::new()));

for _x in 0..100 {
     let handle = thread::spawn(move || {
          //do some work
     }

     threads.lock().unwrap().push((handle));
}

for t in threads.lock().unwrap().iter() {
     t.join();
}
like image 903
Jacob Clark Avatar asked Jun 01 '15 12:06

Jacob Clark


1 Answers

Unfortunately, you can't do this directly. When Mutex consumes the data structure you fed to it, you can't get it back by value again. You can only get &mut reference to it, which won't allow moving out of it. So even into_iter() won't work - it needs self argument which it can't get from MutexGuard.

There is a workaround, however. You can use Arc<Mutex<Option<Vec<_>>>> instead of Arc<Mutex<Vec<_>>> and then just take() the value out of the mutex:

for t in threads.lock().unwrap().take().unwrap().into_iter() {
}

Then into_iter() will work just fine as the value is moved into the calling thread.

Of course, you will need to construct the vector and push to it appropriately:

let threads = Arc::new(Mutex::new(Some(Vec::new())));
...
threads.lock().unwrap().as_mut().unwrap().push(handle);

However, the best way is to just drop the Arc<Mutex<..>> layer altogether (of course, if this value is not used from other threads).

like image 189
Vladimir Matveev Avatar answered Sep 30 '22 00:09

Vladimir Matveev