return 如何引用互斥量内的静态哈希图中的项目?
How can return a reference to an item in a static hashmap inside a mutex?
我正在尝试访问静态哈希图以进行读写,但我总是收到错误消息:
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()
甚至什么都不用,但我无法让它工作。你能帮帮我吗?
I tried with .cloned(), .clone() or even nothing but I don't manage to get it to work. Can you help me?
所有 Option::clone
所做的就是克隆底层结构,在本例中是一个 &ModuleItem
所以它只是克隆引用,你仍然有一个引用,你不能 return 因为你只有在持有锁时才能访问 hashmap 的内容(否则它无法工作)。
Option::cloned
实际上克隆了引用持有的对象,但不在这里编译,因为无法克隆 ModuleItem。
首先你必须return一个Option<ModuleItem>
,你不能 return一个对地图内容的引用,因为锁正在运行在函数结束时被释放,并且您无法跨互斥边界处理 hashmap 内容,因为它们随时可能消失(例如,另一个线程可以移动它们,甚至完全清除映射)。
然后复制 ModuleItem,方法是在 ModuleItem
上派生 Clone
(然后调用 Option::cloned
)或创建新的 ModuleItem "by hand",例如
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
不能使用静态生命周期,因为数据不会在程序的整个生命周期 (from the Rust book) 中存在:
As a reference lifetime 'static indicates that the data pointed to by the reference lives for the entire lifetime of the running program. It can still be coerced to a shorter lifetime.
因此您必须 return 一个 none 静态引用或 HashMap
值的副本。引用是不可能的,因为 MODULE_MAP.lock().unwrap()
return 是一个 MutexGuard
,它是一个本地变量,因此是一个保存 HashMap
的临时变量。并且 get()
的 HashMap
return 是一个参考。
由于临时 MutexGuard
将在函数结束时销毁,由 get
编辑的引用 return 将指向一个临时值。
要解决此问题,您可以使 ModuleItem
可克隆并 return 值的副本:
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()
}
我正在尝试访问静态哈希图以进行读写,但我总是收到错误消息:
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()
甚至什么都不用,但我无法让它工作。你能帮帮我吗?
I tried with .cloned(), .clone() or even nothing but I don't manage to get it to work. Can you help me?
所有 Option::clone
所做的就是克隆底层结构,在本例中是一个 &ModuleItem
所以它只是克隆引用,你仍然有一个引用,你不能 return 因为你只有在持有锁时才能访问 hashmap 的内容(否则它无法工作)。
Option::cloned
实际上克隆了引用持有的对象,但不在这里编译,因为无法克隆 ModuleItem。
首先你必须return一个Option<ModuleItem>
,你不能 return一个对地图内容的引用,因为锁正在运行在函数结束时被释放,并且您无法跨互斥边界处理 hashmap 内容,因为它们随时可能消失(例如,另一个线程可以移动它们,甚至完全清除映射)。
然后复制 ModuleItem,方法是在 ModuleItem
上派生 Clone
(然后调用 Option::cloned
)或创建新的 ModuleItem "by hand",例如
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
不能使用静态生命周期,因为数据不会在程序的整个生命周期 (from the Rust book) 中存在:
As a reference lifetime 'static indicates that the data pointed to by the reference lives for the entire lifetime of the running program. It can still be coerced to a shorter lifetime.
因此您必须 return 一个 none 静态引用或 HashMap
值的副本。引用是不可能的,因为 MODULE_MAP.lock().unwrap()
return 是一个 MutexGuard
,它是一个本地变量,因此是一个保存 HashMap
的临时变量。并且 get()
的 HashMap
return 是一个参考。
由于临时 MutexGuard
将在函数结束时销毁,由 get
编辑的引用 return 将指向一个临时值。
要解决此问题,您可以使 ModuleItem
可克隆并 return 值的副本:
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()
}