私は最初のRustプロジェクトで最近作業していましたが、私はHashMap
String
s〜AtomicUsize
の整数を使用しています。 HashMap
は、同時アクセスを可能にするためにRwLock
によって保護されています。私はAtomicUsize
の値を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が特に関係していた。それを読んだら、ミューテックスから返された値はミューテックスよりも寿命が短くなければならないことを知ることができます。これは私がやろうとしていることを完全に排除するようです。これが不可能である理由を知ることができます。なぜなら、ハッシュマップへのポインタを持っていて、それがサイズ変更されるミューテックスに値を挿入すると、ぶら下がりポインタがあるからです。
私の質問は2倍です。まず、私が問題を正しく理解しているのか、私がやろうとしたことをやってもいけない理由がもう一つあるのか不思議です。そして、私の第二の質問は、Box
原子の整数とそれらをHashMap
に保存せずに、私がやろうとしていることを達成するための別の方法があるかどうかです。そのようなアプローチは私にとってはうまくいくようですが、常に有効な値Boxed
へのポインタを返すことができるからです。しかし、このアプローチはポインタ間接指定と余分な割り当ての余分なレイヤーを必要とするため、非効率的であるようです。ありがとう!
地図のサイズ変更に加えて、他の誰かが参照を保持しているエントリを単に削除することができます。 –
あなたはまさに正しいです!私の使用例では、キーを削除する必要はありませんが、もちろんコンパイラはそのことを認識しません。 – jeromefroe