18 个版本 (2 个稳定版本)
1.1.0 | 2023年11月26日 |
---|---|
1.0.0 | 2022年11月22日 |
0.7.0 | 2021年11月10日 |
0.6.2 | 2021年1月25日 |
0.1.1 | 2019年5月26日 |
#42 in 并发
2,799,334 每月下载量
在 3,803 个 Crates 中使用 (直接使用 3 个)
51KB
1.5K SLoC
镭为需要共享可变性但不一定需要硬件级别原子性的代码提供统一的抽象和优雅降级。
主要导出是 Radium
特性。它在标准库的 atomic
模块中的所有类型以及 Cell
包装器(用于 bool、整数和可变指针)上实现。您的代码可以泛型化 Radium
特性并使用稳定且一致的 API,并允许客户端代码提供原子或非原子类型,取决于它们的能力。
此外,Radium提供了三种具有不同原子行为保证的类型家族:Atom<T>
包装了标准库的原子操作,仅接受具有 AtomicT
类型的目标的 T
参数;Isotope<T>
接受任何可能是原子的类型,并在存在原子操作的地方包装它们,不存在的地方则静默地转换为 Cell<T>
;Radon<T>
包装 Cell<T>
。这三种类型都没有API,除了实现 Radium
、Debug
、Default
和 From<T>
,因此您的代码可以在它们之间切换而无需担心使用方式的改变。
最后,Radium提供了与标准库中所有 AtomicT
类型名称匹配的 RadiumT
类型别名。这些别名在存在原子变体时指向其原子变体,不存在时指向 Cell<T>
。您的代码可以使用这些名称在不同的原子支持水平的目标之间实现可移植性,无需担心 AtomicT
符号在没有必要原子指令的目标上消失。
Rust编译器在版本1.60中稳定了 cfg(target_has_atomic)
测试。这现在是Radium 1.0的MSRV。版本-0系列将无限期地保持支持,以便允许1.60之前的项目继续使用它。版本-0的 radium::if_atomic!
宏允许项目在版本-0中模拟 #![cfg(target_has_atomic)]
,但在版本-1中已被移除。
此crate与#![no_std]
兼容,因为它仅依赖于 core::sync::atomic
和 core::cell
模块。
版本
根据定义,Radium与Rust标准库相关联。随着原子API的演变,Radium将跟随它。MSRV的提升始终至少是一个小版本的增加。
截至Rust 1.60版本,对128位原子操作的支持仍然是不稳定的。由于Radium致力于在稳定发布系列中使用,因此它不支持128位原子操作。作为一个折衷方案,Cell<{i,u}128>
已集成到Radium中,以备未来稳定化使用。
如果在不稳定化的情况下从标准库中删除了128位原子操作,那么在主要版本升级时,Radium将移除对Cell<{i,u}128>
的支持。
非标准实现者
除了Rust标准库中的 Cell
和 Atomic
类型外,我们还为 portable-atomic
包提供了一种实现方式。然而,portable-atomic
的实现无法在一些特定的目标上编译。截至1.60版本,它们是:
thumbv6m-none-eabi
riscv32i-unknown-none-elf
riscv32imc-unknown-none-elf
这些目标具有32位原子加载和存储指令,但没有读取/修改/写入指令。由于 Radium
需要RMU行为,而 portable-atomic
即使在软件中也不提供这种行为(所有的 .fetch_action
方法都缺失),因此我们不会尝试优雅地处理这些目标,而是简单地允许编译失败。
编译这些目标时,不要使用 portable-atomic
功能。
我们禁用了所有 portable-atomic
功能,包括默认启用的 fallback
功能。这导致 portable-atomic
只生成与目标上标准库提供的相匹配的符号。如果您在自己的包中启用了 portable-atomic/fallback
,那么这些符号将存在,但 radium
将无法看到它们,因为 #[cfg(feature = "...")]
无法查询 其他 包启用的功能集。您需要设置 Radium 的 portable-atomic-fallback
功能来获取比目标指令集支持的更宽的原子操作实现。
1.60版本之前的目标发现
由于编译器没有使原子支持在目标上对库可访问,Radium 使用构建脚本来检测目标架构并发出自己的指令,以标记原子整数的存在或不存在。我们通过读取编译器的目标信息记录并将信息直接复制到我们的构建脚本中来实现这一点。
如果 Radium v0 不可用于您的架构,请更新构建脚本来处理您的目标字符串,并将 pull request 提交给 v0 分支。我们根据需要编写构建脚本;它不会被积极填充编译器中列出的所有信息。
注意:构建脚本通过两个环境变量接收信息:TARGET
和CARGO_CFG_TARGET_ARCH
。后者相当于cfg(target_arch)
中的值;然而,这个值并不包含足够的信息来完全区分目标。构建脚本尝试对env!(TARGET)
字符串进行初步解析;如果这不适合您的目标,请考虑使用TARGET_ARCH
匹配器,或者匹配完整的TARGET
字符串,而不是尝试解析。
项目起源
@kneecaw - https://twitter.com/kneecaw/status/1132695060812849154
感觉有点懒:有没有人为通用的代码(可能不关心原子性)抽象过
AtomicUsize
和Cell<usize>
的操作编写一个辅助特质?
@ManishEarth - https://twitter.com/ManishEarth/status/1132706585300496384
没有,但把这个crate叫做radium
(因为人们不在乎它是放射性的,所以用它来处理一切)
依赖项
~220KB