1 个不稳定版本
使用旧的 Rust 2015
0.2.0 | 2021年3月17日 |
---|
#2513 在 Rust 模式
71 每月下载量
在 4 个crate(3个直接) 中使用
18KB
324 行
atomic_refcell
Rust 的线程安全 RefCell。
lib.rs
:
实现了一个容器类型,为跨线程共享的对象提供了类似于 RefCell 的语义。
RwLock 传统上被认为是 RefCell 的 |Sync| 类似物。然而,对于可以保证它们永远不会与不可变借用同时进行可变借用的消费者来说,RwLock 是过度的,并且具有关键缺点
- 性能:即使是现有最快的 RwLock 实现(parking_lot)在不可变借用期间也至少执行两次原子操作。这使得可变借用的成本显著低于不可变借用,导致在编写性能关键代码时出现奇怪的动力。
- 功能:在 RwLock 上实现 AtomicRefCell 使得无法实现如 AtomicRef{,Mut}::map 等有用的功能。
因此,我们从头开始重新实现 RefCell 语义,使用单个原子引用计数。此方案的主要复杂性与当一个线程执行非法借用并崩溃时保持事物的一致状态有关。由于 AtomicRefCell 可以被多个线程访问,并且由于崩溃是可以恢复的,我们需要确保一个线程的非法(崩溃)访问不会导致其他仍在运行的线程上的未定义行为。
因此,我们表示如下
- 任何高位设置为 1 的值(因此是总引用计数字空间的二分之一)表示可变借用。
- 可变借用执行原子比较并交换,如果当前值为零则交换进高位。如果当前值非零,则线程崩溃,值保持不变。
- 不可变借用执行原子递增。如果新值的高位设置为 1,则线程崩溃。递增的引用计数字段保持不变,因为它仍然表示一个有效的可变借用。当可变借用释放时,引用计数字段无条件设置为 0,清除崩溃线程造成的任何意外递增。
有关处理溢出的几个纯粹学术上的复杂性,已在实现中进行说明。
此模块的其余部分主要通过对 RefCell 的实现进行复制粘贴并适当修复而得来。已删除某些非线程安全的方法。我们将并发逻辑与代码的其他部分分开,以保持复杂部分较小且易于审计。