异步友好的 RefCell 中防止跨等待点借用的描述是对问题的错误陈述。
我想要这样的东西:
struct Foo {
inner: SingleThreadedAsyncCell<Inner>
}
impl Foo {
pub async fn do_something(&self) {
self.inner.borrow().really_do_something().await;
}
pub async fn do_something_else(&self) {
self.inner.borrow_mut().really_do_something_else().await;
}
}
async fn do_many_somethings(f: &Foo) {
join!(f.do_something(), f.do_something_else(), f.do_something_else());
}
即使在等待时,同时借用和borrow_mut也应该是安全的,因为内部是为了在挂起时处理并发mut而编写的。我想确保在轮询时保留借用,但在等待时释放借用。话虽这么说,我并不受这个特定的类似 RefCell 的 API 的束缚。如果有其他方式来制定解决方案,我愿意听取想法。
或者在这种情况下,我是否只是退回到将所有可变状态存储在 UnsafeCell 后面?
struct Foo {
inner: SingleThreadedAsyncCell<Vec<String>>,
}
impl Foo {
pub async fn do_something(&self) {
let inner = self.inner.borrow();
let item = inner.get(0).unwrap();
something().await;
println!("{item}");
}
pub async fn do_something_else(&self) {
self.inner.borrow_mut().clear();
}
}
async fn do_many_somethings(f: &Foo) {
join!(f.do_something(), f.do_something_else(), f.do_something_else());
}
do_something
返回的未来正在引用一个项目,但
do_something_else
清除了
Vec
,这意味着
do_something
现在持有对无效值的引用。这是一个经典的释放后使用,并且是为什么不能仅仅因为持有它们的线程/任务/未来当前没有运行而忽略引用的一个例子。