如何在Rust中使用长期(接近静态)借用?

jvlzgdj9  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(107)

在我的应用程序中,我获取大对象(昂贵的),并将它们存储在巨大的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)。
我如何告诉借用检查器引用将基本上永远存在(本质上是“静态的,只要它应该关心)?

jfewjypa

jfewjypa1#

我如何告诉借用检查器引用将基本上永远存在(本质上是“静态的,只要它应该关心)?
你不知道,因为它们不是'static。向编译器谎报生存期是导致未定义行为的一种奇妙方式。(你可以用unsafe来做,但在这种情况下绝对不应该这样做。
仅仅因为这些项不会从Map中删除并不意味着它们将始终存在于内存中的同一位置。向Map中添加项可以触发重新分配,从而重新定位现有值,这将使对它们的所有现有引用无效。
拉斯特在保护你其他一些语言会允许你这样做,在以后的某个时候会导致未定义的行为。
使用Arc。提前优化这一点是一个坏主意; Arc的开销极不可能成为瓶颈。

相关问题