14 个版本

0.1.13 2023 年 10 月 10 日
0.1.11 2023 年 8 月 14 日
0.1.10 2023 年 4 月 24 日
0.1.9 2023 年 1 月 3 日
0.1.0 2017 年 1 月 3 日

#27 in 并发

Download history 37078/week @ 2024-03-14 32832/week @ 2024-03-21 48112/week @ 2024-03-28 33248/week @ 2024-04-04 35827/week @ 2024-04-11 33464/week @ 2024-04-18 29796/week @ 2024-04-25 30300/week @ 2024-05-02 30812/week @ 2024-05-09 29507/week @ 2024-05-16 29642/week @ 2024-05-23 27839/week @ 2024-05-30 25001/week @ 2024-06-06 27407/week @ 2024-06-13 29353/week @ 2024-06-20 24496/week @ 2024-06-27

110,884 每月下载量
510 个 crates 中使用 (直接使用 64 个)

Apache-2.0/MIT

21KB
365

atomic_refcell

Rust 的线程安全 RefCell。


lib.rs:

实现了一个容器类型,为跨线程共享的对象提供类似 RefCell 的语义。

RwLock 一直被认为是 RefCell 的 |Sync| 类比。然而,对于可以保证它们永远不会与不可变借用同时进行可变借用的消费者来说,RwLock 是过度的,并且存在关键缺点

  • 性能:即使是现有的最快 RwLock 实现(parking_lot)在不可变借用期间也至少执行了两次原子操作。这使得可变借用比不可变借用便宜得多,导致编写性能关键代码时出现奇怪的激励。
  • 特性:在 RwLock 上实现 AtomicRefCell 使得无法实现有用的功能,如 AtomicRef{,Mut}::map。

因此,我们从零开始重新实现了 RefCell 语义,使用单个原子引用计数。此方案的主要复杂性在于当一个线程执行非法借用并崩溃时保持事物的一致状态。由于 AtomicRefCell 可被多个线程访问,并且由于崩溃是可恢复的,我们需要确保一个线程的非法(崩溃)访问不会导致其他仍在运行的线程上的未定义行为。

因此,我们按以下方式表示事物

  • 任何高比特位被设置(因此是总引用计数空间的一半)的值表示可变借用。
  • 可变借用执行原子比较并交换,如果当前值是零,则交换高比特位。如果当前值非零,则线程崩溃,值保持不变。
  • 不可变借用执行原子递增。如果新值具有高比特位,则线程崩溃。递增的引用计数保持不变,因为它仍然表示一个有效的可变借用。当释放可变借用时,引用计数无条件地设置为零,清除崩溃线程的任何意外递增。

还有几个纯粹学术上的复杂性来处理溢出,这些在实现中有文档记录。

此模块的其余部分主要通过对 RefCell 的实现进行复制粘贴并相应地进行修复而得来。已删除某些非线程安全的方法。我们将并发逻辑从其余代码中分离出来,以保持复杂部分较小且易于审计。

依赖关系

~175KB