在我的应用程序中,我获取大对象(昂贵的),并将它们存储在巨大的HashMap中。一旦插入Map,它们就永远不会被移除。
对象本身具有边界可变性(Mutex等),所以我从不将它们作为可变对象引用。这些对象被视为单例,一旦加载,应用程序中的任何地方都引用相同的底层对象,因此更改是全局的。
伪代码,但一般的想法是:
struct Thing {
inner: Arc<InnerThing>,
}
struct InnerThing {
field1: xxx,
field2: Vec<yyy>,
field3: Mutex<Something>,
}
struct App {
map: HashMap<key, Thing>
}
impl App {
fn get_thing(&mut self, key) -> Thing {
if let Some(val) = self.map.get(key) {
return val.clone();
}
// Load (expensive) Thing, insert into map
let thing = LoadExpensiveThing();
self.map.insert(key, thing.clone());
thing
}
}
整个应用程序中的位置都调用getThing(key)
,并且都与相同的底层Thing
交互。
我很想避免使用Arc<>,因为App.map
拥有每个Thing对象,并且由于用例,它们永远不会从Map中删除,但我不确定如何向借用检查器表示。显然我遇到了正常的“活得不够长”,因为理论上它可以从Map上删除(但不会)。我还使用了时雄,因此需要将这些引用传递给派生的任务(Sync/Send)。
我如何告诉借用检查器引用将基本上永远存在(本质上是“静态的,只要它应该关心)?
1条答案
按热度按时间jfewjypa1#
我如何告诉借用检查器引用将基本上永远存在(本质上是“静态的,只要它应该关心)?
你不知道,因为它们不是
'static
。向编译器谎报生存期是导致未定义行为的一种奇妙方式。(你可以用unsafe
来做,但在这种情况下绝对不应该这样做。仅仅因为这些项不会从Map中删除并不意味着它们将始终存在于内存中的同一位置。向Map中添加项可以触发重新分配,从而重新定位现有值,这将使对它们的所有现有引用无效。
拉斯特在保护你其他一些语言会允许你这样做,在以后的某个时候会导致未定义的行为。
使用
Arc
。提前优化这一点是一个坏主意;Arc
的开销极不可能成为瓶颈。