Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying a Mutex<Option<>>

Tags:

rust

I have a quick stylistic or idiomatic question about Mutex.

Is there a more elegant way to modify the data in fn upper() than using *string = match *string. It seems odd to dereference on both side, but if I don't, I don't know how to handle the <MutexGuard> part of string.

Link to playground

use std::sync::{Mutex};

#[derive(Debug)]
struct SharedFile{
    file: Mutex<Option<String>>
}

impl SharedFile{
    fn new()-> SharedFile{
       SharedFile{
           file: Mutex::new(Some("test".to_owned())),
           //file: Mutex::new(None),
       }
    }

    fn upper(&self){
      let mut string  = self.file.lock().unwrap();

      *string= match *string{
         Some(ref mut x) => Some(x.to_uppercase()),
         None => Some("Empty".to_owned()),
      };

      println!("{:?}", *string);
    }
}

fn main() {
        let shared = SharedFile::new();
        shared.upper();
        println!("{:?}", shared);
}
like image 675
Xavier T. Avatar asked Mar 11 '16 10:03

Xavier T.


1 Answers

Sure, there is:

*string = string.as_ref()
    .map(|x| x.to_uppercase())
    .unwrap_or_else(|| "Empty".to_owned())

This in fact is not specific to Mutex; the same problem and solution apply to &mut Option<String>, for example. That said, the solution with *string = match *string { ... } is absolutely fine as well. BTW, you don't need mut in Some(ref mut x), just Some(ref x) is fine - to_uppercase() only needs a shared reference to the string.

like image 145
Vladimir Matveev Avatar answered Nov 16 '22 12:11

Vladimir Matveev