我一直在努力研究最近的第一個Rust項目,但遇到了麻煩。我正在使用HashMap
映射String
s到AtomicUsize
整數。 HashMap
受RwLock
保護以允許併發訪問。我希望能夠返回值HashMap
中的引用,但是,如果我嘗試將這些引用返回給調用方,並且過了RwLockWriteGuard
的生存期,則會出現borrowed value does not live long enough
的錯誤。我已經複製了下面的一個簡單例子,並在Rust遊樂場here上放置了相同的示例。試圖從RwLock返回引用,「借來的值不夠長」錯誤
use std::collections::HashMap;
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, Ordering};
struct Bar {
val: AtomicUsize
}
impl Bar {
pub fn new() -> Self {
Bar { val: AtomicUsize::new(0) }
}
}
struct Foo {
map: RwLock<HashMap<String, Bar>>
}
impl Foo {
pub fn get(&self, key: String) -> &Bar {
self.map.write().unwrap().entry(key).or_insert(Bar::new())
}
}
fn main() {
let foo = Foo {map: RwLock::new(HashMap::new())};
let bar = foo.get("key".to_string());
}
我得到的錯誤就行發生:
self.map.write().unwrap().entry(key).or_insert(Bar::new())
而且是因爲借來的價值不活足夠長的時間。我讀過幾篇討論這個錯誤的帖子,特別是one尤其相關。讀完它後,我可以得知,互斥量返回的值必須小於互斥量,這似乎完全排除了我正在嘗試執行的操作。我可以看到爲什麼這是不可能的,因爲如果我們有一個指向Hashmap的指針,另一個將值插入互斥量中導致它被調整大小,那麼我們將有一個懸掛指針。
我的問題是雙重的。首先,我只是好奇,如果我正確地理解了這個問題,或者是否有另一個原因讓我不能做我想做的事情?而我的第二個問題是,如果沒有Box
原子整數並將那些存儲在HashMap
中,是否有另一種方法可以實現我試圖執行的操作?這樣的方法似乎應該對我有用,因爲我們可以返回一個指向Boxed
值的指針,該值始終有效。然而,這種方法似乎效率不高,因爲它需要額外的指針間接層和額外的分配。謝謝!
除了地圖大小調整之外,其他人可以簡單地刪除您持有引用的條目。 –
你完全正確!對於我的用例,我不需要永遠刪除一個密鑰,但編譯器當然不知道這一點。 – jeromefroe