0

我正在使用 leveldb 板条箱,我正在尝试获取一个 Snapshot 结构并将其移动到我的结构中,但是我遇到了问题,因为我无法将引用的值移出函数。

这是来自 crate 的结构和特征的代码。我没有在这里包含它,但是 Database 类型实现了 Snapshots 特征以返回一个快照:

pub trait Snapshots<K: Key> {
    fn snapshot<'a>(&'a self) -> Snapshot<'a, K>;
}

pub struct Snapshot<'a, K: Key + 'a> {
    raw: RawSnapshot,
    database: &'a Database<K>,
}

这是我的代码:

pub struct Cache {
  ldb: RwLock<Database<i32>>
  //other fields omitted
}

pub struct MySnapshot<'a> {
  snapshot: Snapshot<'a, i32>
  //other fields omitted
}

impl Cache {
  pub fn snapshot<'a>(&'a self) -> MySnapshot<'a> {
    let snapshot = self.ldb.read().unwrap().snapshot();
    MySnapshot { snapshot }
  }
}

我认为我不能这样做的原因(如果我错了,请纠正我)是使用 RwLock,当我获得对包装数据(在我的情况下为数据库)的引用时,该引用的生命周期不是 self 和所以当 RwLock 超出范围时它会被丢弃。我能想到的一种可能的解决方法是删除数据库上的 RwLock 并添加另一个字段:

pub struct Cache {
  ldb: Database<i32>
  //The wrapped type isn't important, just need this to make the function block
  ldb_rwlock: RwLock<u8>
  //other fields omitted
}

impl Cache {
  pub fn snapshot<'a>(&'a self) -> MySnapshot<'a> {
    self.ldb_rwlock.read();
    let snapshot = self.ldb.snapshot();
    MySnapshot { snapshot }
  }
}

这将让我安全地获得快照,因为它会阻塞直到任何写锁被释放,并且最终用户除了通过我实现的 API 之外无法改变 ldb,只要我总是在尝试读/写之前使用 ldb_rwlock对 ldb 来说应该是安全的。但是,我觉得这会使 rust 打算使用 RwLock 的方式无效,并且感觉不是很惯用。有没有办法解决这个问题?

另外我不将 ldb 包装在 Arc 中的原因是因为 Cache 结构将被包装在 Arc 中并跨线程共享,我只想要锁定 ldb 字段,以便只有读/写数据库需要锁。不过,总的来说,我对生锈和并发性还是很陌生,所以我不确定我正在做的事情是否是解决这个问题的最佳方法。

4

0 回答 0