是否有任何方法可以创建类似 RefCell 的数据结构,以防止在等待点上发生借用?我有一个单线程异步运行时,并且我的对象的内部状态可以在单个线程内安全地发生变化。然而,RefCell 是危险的,因为如果我不小心在等待点上持有借用,那么调用者对实际上安全的变异 API 进行重叠调用就不再安全了(他们会因为重复借用而恐慌)。
我想互斥锁+工作窃取运行时一定存在类似的问题。
我猜我可以拥有一个仅公开基于闭包的接口的 RefCell 包装器:
fn guarded_mut<F: FnOnce(&mut T)>(&self, cb: F)
但是如果我希望能够轻松地从中转发返回值,我不知道如何安全地防范期货:
fn guarded_mut<R, F: FnOnce(&mut T) -> R>(&self, cb: F) -> R
guarded_mut(|interior| async move {
}).await;
也许受保护的 API 只是为了防止这种情况发生,因为内部的生命周期比 R 的生命周期短?
在多线程运行时,这会自动发生,因为
RefCell
的借用值(Ref
和 RefMut
)不是 Send
。因此,在等待点持有一个将使未来变得不Send
。
如果您使用单线程运行时,则没有
Send
约束,因此没有机制可以阻止在等待点上持有 Ref
/RefMut
。 Rust 没有“等待安全”作为一流概念,因此无法静态检查。