Move out of a Mutex in a static element

Viewed 50

I have this static element:

pub static CREDENTIALS: Mutex<DatabaseCredentials> = Mutex::new(DatabaseCredentials::new());

and I want to take the content out of the Mutex:

let creds = CREDENTIALS.into_inner().unwrap().clone();

and I am getting this error:

let creds = CREDENTIALS.into_inner().unwrap();
   |                     ^^^^^^^^^^^ move occurs because `CREDENTIALS` has type `std::sync::Mutex<connection::credentials::DatabaseCredentials<'_>>`, which does not implement the `Copy` trait

Where my DatabaseCredentials looks as follows:

#[derive(Clone, Copy)]
pub struct DatabaseCredentials<'a> {
    pub username: &'a str,
    pub password: &'a str,
    pub host: &'a str,
    pub db_name: &'a str
}

unsafe impl Send for DatabaseCredentials<'_> {}
unsafe impl Sync for DatabaseCredentials<'_> {}

// impl block...

How can I get rid out of the error, and take the underlying value inside the Mutex?

1 Answers

How can I get rid out of the error, and take the underlying value inside the Mutex?

I would suggest reworking your system so you don't have to, because it's odd, why would you have a mutex and want to move things out of it rather than just use the protected object in-place?

But if you really need to, given your mutex is static you have three options:

  1. Copy or Clone the stored DatabaseCredentials, no need to into_inner anything, just deref' the MutexGuard. That will create an owned copy of the credentials.
  2. Add an indirection through an Option, this way you can Option::take the DatabaseCredentials out of the Mutex. This will leave the mutex valid but containing a None.
  3. std::mem::replace the contents of the mutex by a newly created DatabaseCredentials, you'll get the one which was stored in the mutex.

In all three cases, you have to lock the mutex first.

Related