#cell #atomic #thread-safe #no-std #data-access

no-std ptr_cell

基于原子指针的安全线程细胞

10 个稳定版本

2.2.1 2024 年 6 月 16 日
2.2.0 2024 年 4 月 14 日
1.2.1 2024 年 3 月 24 日

#294并发

Download history 5/week @ 2024-05-21 1/week @ 2024-05-28 130/week @ 2024-06-11 35/week @ 2024-06-18 26/week @ 2024-07-02 40/week @ 2024-07-23 21/week @ 2024-07-30

61 每月下载量

CC0 许可证

29KB
186

Rust 的简单线程安全细胞

PtrCell 是一种原子细胞类型,允许安全、并发访问共享数据。无需 std、无数据竞争、无 未知行为(未定义的行为),最重要的是,无锁

此类型仅在需要通过进出它来更新共享值的情况下有用。如果您想通过可变引用并发更新值,并且不需要对 no_std 的支持,请查看标准 MutexRwLock

提供

  • 熟悉度PtrCell 的 API 是模仿 stdCell

  • 易于并发:不再需要 Arc<Mutex<T>>Arc::clone()Mutex::lock().expect()!在需要时将数据保持静态,并指向它。在大多数现代平台上这是一条 单指令

限制

  • 堆分配:每个插入到 PtrCell 的值都必须首先使用 Box 分配。在堆上分配在计算上是一个相对昂贵的操作。为了解决这个问题,细胞公开了一个指针 API,可以用来避免多次分配相同的值。未来的版本将主要依赖于堆栈

目录

安装

只需使用Cargo添加crate

cargo add ptr_cell

使用

use ptr_cell::{PtrCell, Semantics::Relaxed};

let cell: PtrCell<u16> = 0x81D.into();

assert_eq!(cell.replace(Some(2047), Relaxed), Some(0x81D));
assert_eq!(cell.is_empty(Relaxed), false);
assert_eq!(cell.take(Relaxed), Some(2047))

语义

PtrCell 允许您通过 Semantics 枚举指定其内部原子操作的记忆顺序语义。每个变体在同步和性能之间的平衡方式都不同。以下是可用语义的比较

变体 开销 同步
宽松 可忽略不计
耦合 可接受 直观
有序 明显 严格

Coupled 是您通常会用到的。然而,其他顺序也有其用例。例如,Relaxed 语义可能在操作已经通过其他方式同步(如 fences)时很有用。就像往常一样,每个项目的文档包含更多详细信息

示例

下面的代码通过并发处理序列的一半来找到序列的最大值。注意代码没有读取共享值。相反,它使用移动操作,并在新数据到来时纠正先前的操作

use ptr_cell::{PtrCell, Semantics};
use std::sync::Arc;

fn main() {
    const VALUES: [u8; 11] = [47, 12, 88, 45, 67, 34, 78, 90, 11, 77, 33];

    let cell = PtrCell::default();
    let maximum = Arc::new(cell);

    let (left, right) = VALUES.split_at(VALUES.len() / 2);

    let handles = [left, right].map(|half| {
        let maximum = Arc::clone(&maximum);

        std::thread::spawn(move || maximize_in(half, &maximum))
    });

    for worker in handles {
        if let Err(payload) = worker.join() {
            std::panic::resume_unwind(payload)
        }
    }

    assert_eq!(maximum.take(), Some(90))
}

fn maximize_in<T>(sequence: &[T], buffer: &PtrCell<T>)
where
    T: Ord + Copy,
{
    for &item in sequence {
        let mut slot = Some(item);

        loop {
            let previous = buffer.replace(slot, Semantics::Relaxed);

            match slot < previous {
                true => slot = previous,
                false => break,
            }
        }
    }
}

贡献

是的,请!参见 CONTRIBUTING.md

合并的pull请求的作者将获得零食作为奖励

许可证

版权所有 2024 Nikolay Levkovsky

个人贡献由各自的贡献者享有版权


本项目根据 Creative Commons CC0 1.0 Universal (CC0 1.0) 许可证授权,如 LICENSE.txt 中所示。CC0 是 Creative Commons 提供的公共领域奉献工具

无运行时依赖