How to move the content of Mutex wrapped by Arc


#1

Please consider the following example:

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

fn main() {
	let w_vec = Arc::new(Mutex::new(vec![1, 2, 3]));
	let v = w_vec.lock().unwrap();
	print(*v);
}

fn print(v: Vec<i32>) {
	println!("{:?}", v);
}

I got the following error:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:7:8
  |
7 | 	print(*v);
  | 	      ^^ cannot move out of borrowed content

error: aborting due to previous error

error: Could not compile `blah`. 

rustc --version: rustc 1.16.0 (30cf806ef 2017-03-10)


#2

You can’t “move out” of that. It would mean w_vec is invalid state.

You can either make print take a reference: fn print(v : &[i32]) and call it as print(v.as_slice()) or if you really want to move out the stuff from w_vec use https://doc.rust-lang.org/std/mem/fn.replace.html to substitute it with a new vec, so that w_vec state is valid.


#3

If the compiler let you do this directly, then the next caller to lock the mutex would see undefined memory.

But both types have ways to move by proving you’re the sole owner. Arc::try_unwrap will attempt this, succeeding only if the reference count is 1 (just you). Then Mutex::into_inner can move from that into the inner content.


#5

it worked using let v = Arc::try_unwrap(w_vec).unwrap().into_inner().unwrap();
thank you @cuviper


#6

As far as I can see you don’t need to move the content out of the Arc. Instead you can pass the vector to print by reference. This version of the code allows you to print the vector more than once.

fn main() {
    ....
    print(v);
}

fn print(v: &Vec<i32>) {
    println!("{:?}", *v);
}