单线程异步友好的 RefCell 在等待时释放借用?

问题描述 投票:0回答:1

异步友好的 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 后面?

rust async-await single-threaded
1个回答
0
投票
你问的根本不合理。未来无法运行并不意味着它的借款可以被简单地忽略。这是一个反例来证明原因:

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
现在持有对无效值的引用。这是一个经典的释放后使用,并且是为什么不能仅仅因为持有它们的线程/任务/未来当前没有运行而忽略引用的一个例子。

© www.soinside.com 2019 - 2024. All rights reserved.