matklad / once_cell

Rust library for single assignment cells and lazy statics without macros

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how to get Mutex inner variable in CONFIG in once_cell

baoyachi opened this issue · comments

how to get reference Ext in CONFIG

use once_cell::sync::Lazy;
use std::sync::Mutex;
use std::collections::HashMap;
use std::fmt::Debug;

trait IExt: Debug + Send + Sync {
    fn get_key(&self);
}

#[derive(Debug)]
struct Ext;

impl IExt for Ext {
    fn get_key(&self) {}
}


static CONFIG: Lazy<Mutex<HashMap<String, Box<dyn IExt>>>> = Lazy::new(|| Mutex::new(Default::default()));

fn add() {
    CONFIG.lock().unwrap().insert("1".to_string(), Box::new(Ext));
}

fn get_key<'a>() -> &'a Box<dyn IExt> {
    CONFIG.lock().unwrap().get("1").unwrap()
}


fn main() {
    add();
    let key = get_key();
    println!("{:?}", key);
}

compile error:

error[E0515]: cannot return value referencing temporary value
  --> src/main.rs:27:5
   |
27 |     CONFIG.lock().unwrap().get("1").unwrap()
   |     ----------------------^^^^^^^^^^^^^^^^^^
   |     |
   |     returns a value referencing data owned by the current function
   |     temporary value created here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0515`.
error: could not compile `rustls-example`.

To learn more, run the command again with --verbose.

Process finished with exit code 101

That's not possible, because that would be unsfae.You are trying to return a pointer inside the value, protected by the mutex, but the pointer is not protected by a lock guard. That means that some other thread could sucesfully lock the mutext and mutate the protected data, invalidating the pointer. You need to either clone the data (using Arc<dyn IExt> would help) or use something like map from parking lot: https://docs.rs/lock_api/0.4.0/lock_api/struct.MutexGuard.html#method.map