如何在互斥锁中的静态哈希图中返回对项目的引用?



我正在尝试访问静态哈希图进行读写,但我总是收到错误:

use std::collections::HashMap;
use std::sync::Mutex;
pub struct ModuleItem {
pub absolute_path: String,
}
lazy_static! {
static ref MODULE_MAP: Mutex<HashMap<i32, ModuleItem>> = Mutex::new(HashMap::new());
}
pub fn insert(identity_hash: i32, module_item: ModuleItem) {
MODULE_MAP
.lock()
.unwrap()
.insert(identity_hash, module_item);
}
pub fn get(identity_hash: i32) -> Option<&'static ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).clone()
}

但是我在获取函数cannot return value referencing temporary value上收到错误

我尝试了.cloned().clone()甚至什么都没有,但我无法让它工作。你可以帮我吗?

我尝试使用.cloned((,.clone((甚至什么都没有,但我无法让它工作。你可以帮我吗?

Option::clone所做的只是克隆底层结构,在这种情况下,这是一个&ModuleItem,所以它只是克隆引用,你仍然有一个引用,你不能返回,因为你只能在持有锁时访问哈希映射的内容(否则它不起作用(。

Option::cloned实际上克隆了通过引用保存的对象,但在此处不编译,因为无法克隆 ModuleItem。

首先你必须返回一个Option<ModuleItem>,你不能返回对映射内容的引用,因为锁将在函数结束时释放,并且你不能跨互斥体边界保留哈希图内容的句柄,因为它们可能随时消失(例如,另一个线程可以移动它们, 甚至完全清除地图(。

然后复制模块项,方法是在ModuleItem上派生Clone(然后调用Option::cloned(或通过"手动"创建一个新的模块项,例如

pub fn get(identity_hash: i32) -> Option<ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).map(|m| 
ModuleItem { absolute_path: m.absolute_path.clone() }
)
}

如果您需要经常get钥匙并且担心性能,您可以随时存储Arc<ModuleItem>。这有一些成本(因为它是一个指针,所以你的字符串现在在两个指针后面(,但是克隆 Arc 非常便宜。

为了避免双指针,您可以将ModuleItem变成未调整大小的类型,并让它存储一个str但是......这很难使用,所以我不推荐它。

函数get不能使用静态生存期,因为数据不会在程序的整个生命周期内存在(来自 Rust 书(:

作为引用生存期,"static "表示引用指向的数据在正在运行的程序的整个生存期内存在。它仍然可以被胁迫到更短的寿命。

因此,您必须返回非静态引用或HashMap值的副本。引用是不可能的,因为MODULE_MAP.lock().unwrap()返回一个MutexGuard,该是一个局部变量,因此是一个保存HashMap的临时变量。get()HashMap返回引用。

由于临时MutexGuard将在函数结束时销毁,因此get返回的引用将指向临时值。

要解决此问题,您可以使ModuleItem可克隆并返回该值的副本:

use std::collections::HashMap;
use std::sync::Mutex;
#[derive(Clone)]
pub struct ModuleItem {
pub absolute_path: String,
}
lazy_static::lazy_static! {
static ref MODULE_MAP: Mutex<HashMap<i32, ModuleItem>> = Mutex::new(HashMap::new());
}
pub fn insert(identity_hash: i32, module_item: ModuleItem) {
MODULE_MAP
.lock()
.unwrap()
.insert(identity_hash, module_item);
}
pub fn get(identity_hash: i32) -> Option<ModuleItem> {
MODULE_MAP.lock().unwrap().get(&identity_hash).cloned()
}

相关内容

  • 没有找到相关文章

最新更新