如何解决从 Rust 中的全局 HashMap 获取项目的引用
我正在尝试使用静态 HashMap
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())
}
}
所以问题是:有没有办法正确地做到这一点?我可以使用 Rust 中的任何设计模式来达到这种行为吗?
非常感谢!
解决方法
你试图做的是正确被编译器拒绝,因为如果你能返回一个引用,那么糟糕的事情就会发生。由于函数返回后,互斥锁不再被锁定,
- 其他一些线程可能会锁定互斥锁并获得自己对会话的可变引用,这违反了可变引用提供独占访问的规则。
- 其他一些线程可以锁定互斥锁并从 HashMap 中删除会话——现在您正在访问已释放的内存。
解决方案:每个会话都应该是它自己的 Arc<Mutex<_>>
。即:
lazy_static! {
static ref REPOSITORY: Mutex<HashMap<String,Arc<Mutex<Session>>>> = {
...
impl SessionRepository for REPOSITORY {
fn find(cookie: &str) -> Result<Arc<Mutex<Session>>,Box<dyn Error>> {
let mut repo = REPOSITORY.lock()?;
if let Some(sess) = repo.get(cookie) {
return Ok(Arc::clone(sess));
}
...
}
Arc
允许会话保持活动状态,无论是存储库还是在其上调用 find()
的线程,从而获得自己的 Arc
引用计数指针的克隆。 Mutex
允许独立地改变每个会话。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。