1个不稳定版本
0.1.0 | 2022年11月20日 |
---|
#972 in 异步
用于 paxakos
45KB
935 代码行
snarc
Snarc提供了一种可发送的非原子引用计数智能指针。
工作原理
为了同时实现可发送性和非原子引用计数,必须做出权衡。这些权衡如下。
-
只有一个强/拥有引用和任意多个弱引用。通过调用强/拥有引用的
enter
方法,其值可以临时绑定到当前线程。 -
弱引用只能在与强/拥有引用的
enter
上下文中创建和丢弃。这确保了所需的计数器增量和减量是竞争自由的。 -
在强引用的
enter
上下文中调用弱引用的get
方法返回一个Option<&T>
,即如果从强引用的enter
上下文中调用,则为Some(&t)
。
它有什么好处?
snarc实现所启发的用例非常特殊。它看起来像以下这样。
// We have an async task.
let task = async {
// This task is creating and executing subtasks.
let subtasks = FuturesUnordered::new();
// `x.method()` is returning 'static Futures that share mutable state
subtasks.push(x.method());
subtasks.push(x.method());
// Somewhere within the same task, the subtasks are executed.
subtasks.for_each(|x| async { /* ... */ });
};
由于x.method()
返回的未来共享可变状态,因此该状态必须被包装在RefCell
中。由于未来也有'static
生命周期,因此该RefCell
必须被引用计数智能指针包装。
替代方案
根据上述问题说明,这里有一些替代解决方案。
最终还是使用&RefCell<T>
这并不是真正解决问题的方案,但也许你可以放宽要求?也许你不需要返回的未来拥有 'static
生命周期?
优点
- 无开销/最大效率
缺点
task
将是!Send
- 解决不同的问题
使用 Rc<RefCell<T>>
优点
- 高度高效,有轻微的引用计数开销
缺点
task
将是!Send
使用 Arc<Mutex<T>>
优点
task
将是Send
- 高度人体工程学
- 子任务甚至可以变成自己的任务并在不同的线程上执行
缺点
- 由于锁定开销而不高效
使用 Snarc<RefCell<T>
和 SnarcRef<RefCell<T>>
优点
- 高度高效,有轻微的引用计数开销
task
可以是Send
缺点
- 人体工程学效果不佳
许可: MIT
依赖
~34KB