1 个不稳定版本
0.1.0 | 2021 年 11 月 12 日 |
---|
#1050 在 并发
被 2 crate 使用
54KB
1.5K SLoC
重型 Cell - 原子 refcell 和引用计数的原子 refcell 和借用
AtomicRefCell
和 ArcCell
类型以及相关的守卫/借用类型。基于 atomic_refcell
crate。
许可证
根据以下任一许可证授权
- Apache 许可证第 2 版 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您提交的任何有意包含在作品中的贡献,都将根据上述条款双重许可,而不附加任何额外的条款或条件。
lib.rs
:
一个 no_std
的 atomic_refcell
crate 的端口,增加了对 Arc
包装的 AtomicRefCell
的功能。
实现一个容器类型,为跨线程共享的对象提供类似于 RefCell 的语义。
RwLock 传统上被认为是 RefCell 的 |Sync| 类比。然而,对于可以保证它们将永远不会与不可变借用同时进行可变借用的消费者来说,RwLock 是多余的,并且存在一些主要缺点
- 性能:即使是最快的现有 RwLock 实现(parking_lot 的实现)在不可变借用期间也至少执行两次原子操作。这使得可变借用比不可变借用便宜得多,在编写性能关键代码时会导致奇怪的激励措施。
- 功能:在 RwLock 之上实现 AtomicRefCell 使其无法实现像 AtomicRef{,Mut}::map 这样的有用功能。
因此,我们从零开始重新实现具有单个原子引用计数的RefCell语义。这种方案的主要复杂之处在于当某个线程执行非法借用并引发恐慌时,如何保持数据的一致状态。由于AtomicRefCell可由多个线程访问,并且恐慌是可以恢复的,我们需要确保一个线程的非法(恐慌)访问不会导致其他仍在运行的线程产生未定义的行为。
因此,我们按照以下方式表示事物:
- 任何高位设置为1的值(因此占用了总引用计数空间的一半)表示可变借用。
- 可变借用执行原子比较和交换操作,如果当前值为零,则交换进高位。如果当前值非零,线程将引发恐慌,并且值保持不变。
- 不可变借用执行原子增量。如果新的值具有高位设置为1,线程将引发恐慌。增加后的引用计数保持不变,因为它仍然代表一个有效的可变借用。当可变借用释放时,引用计数无条件地设置为零,清除由恐慌线程产生的任何意外的增量。
处理溢出有一些额外的纯学术性复杂问题,这些在实现中有详细说明。
本模块的其余部分主要通过对RefCell的实现进行复制粘贴并适当修复而来。已删除某些非线程安全的方法。我们将并发逻辑从其余代码中分离出来,以保持复杂部分小且易于审计。
依赖关系
~29KB