Home > Software engineering >  How can I get a String as a return from an Arc Mutex
How can I get a String as a return from an Arc Mutex

Time:08-30

Here is the code.

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

fn main() {
    let test_s = Test{ s: Arc::new(Mutex::new(String::new())) };
    test_s.setter(String::from("whatever"));
    println!("{}", test_s.getter())
}

struct Test {
    s: Arc<Mutex<String>>,
}

impl Test {
    pub fn getter(&self) -> String {
        *self.s.lock().unwrap() // Error occured here !
    }
    
    pub fn setter(&self, s: String) {
        *self.s.lock().unwrap() = s
    }
}

And here is the Error output

   Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of dereference of `MutexGuard<'_, String>`
  --> src/main.rs:15:9
   |
15 |         *self.s.lock().unwrap()
   |         ^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground` due to previous error

I can get the s value just use test_s.s.lock().unwrap(), and use it as a &str just with &test_s.s.lock().unwrap()

Is there an easy way to return a String?

CodePudding user response:

You do not need to deref directly there (*), also you will need to Clone the String:

...
    pub fn getter(&self) -> String {
         self.s.lock().unwrap().clone()
    }
...

Playground

CodePudding user response:

Alternatively return the MutextGuard, which derefs to the underlying type. You won't have to clone the string. You won't need the setter anymore. But you'll have to remember to drop the guard before using the getter again.

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

fn main() {
    let test_s = Test{ s: Arc::new(Mutex::new(String::new())) };

    {
        let mut s = test_s.getter();
        s.push_str("what");
        // MutexGuard s is dropped here - lock is released
    }
    println!("{}", test_s.getter());

    {
        let mut s = test_s.getter();
        *s = "whatever".to_string();
        // MutexGuard s is dropped here - lock is released
    }
    println!("{}", test_s.getter());
}

struct Test {
    s: Arc<Mutex<String>>,
}

impl Test {
    pub fn getter(&self) -> MutexGuard<String> {
        self.s.lock().unwrap()
    }
}
  • Related