I'm trying to use a static HashMap<String, Object> to store some data that I want to use and modify globally in the future. I found out that some way of declaring such a global map is by using lazy_static and mutex in order to share data safely. However, I'm getting some ownership troubles when I want to return these objects as reference, as I do in the code above:
use std::error::Error;
use std::collections::HashMap;
use std::sync::Mutex;
use super::domain::{Session, SessionRepository}; // object and trait declaration
lazy_static! {
static ref REPOSITORY: Mutex<HashMap<String, Session>> = {
let mut repo = HashMap::new();
Mutex::new(repo)
};
}
impl SessionRepository for REPOSITORY {
fn find(cookie: &str) -> Result<&mut Session, Box<dyn Error>> {
let mut repo = REPOSITORY.lock()?;
if let Some(sess) = repo.get_mut(cookie) {
return Ok(sess);
}
Err("Not found".into())
}
}
So the question is: Is there any way of doing this correctly? Does it exists any design pattern in Rust I could use in order to reach this behavior?
Thank you very much!
What you're trying to do is correctly rejected by the compiler, because if you could return a reference, then bad things can happen. Since after the function returns, the mutex is no longer locked,
Solution: each session should be in its own
Arc<Mutex<_>>
. That is:The
Arc
allows the session to be kept alive both by the repository and whichever threads have calledfind()
on it and thus gotten their own clone of theArc
reference-counted pointer. TheMutex
allows each session to be independently mutated.