37个版本 (19个稳定版本)
1.2.9 | 2021年10月30日 |
---|---|
1.2.8 | 2021年3月26日 |
1.2.7 | 2020年12月14日 |
1.2.6 | 2020年11月7日 |
0.5.6 | 2018年5月19日 |
#273 在 并发 中
每月下载量940 次
60KB
815 行
AtomicRingBuffer / AtomicRingQueue
一个固定大小的几乎无锁的并发环形缓冲区
优点
- 快速,try_push 和 try_pop 是 O(1)
- 即使在重并发期间也能很好地扩展
- AtomicRingBuffer 只有 4 个字的内存开销(AtomicRingQueue 有 6 个字的开销)
- 通过 AtomicRingQueue 支持阻塞弹出
- 初始创建后不再进行内存分配
缺点
- 不支持增长/缩小
- 最大容量为 (usize >> 16) 个条目
- 容量向上舍入到下一个2的幂
这个队列的性能应该与 mpmc 类似,但内存开销更低。如果您不关注内存开销,应运行基准测试以决定使用哪个。
实现细节
这个实现使用两个原子操作来存储 read_index/write_index
Read index atomic
+63------------------------------------------------16+15-----8+7------0+
| read_index | r_done | r_pend |
+----------------------------------------------------+--------+--------+
Write index atomic
+63------------------------------------------------16+15-----8+7------0+
| write_index | w_done | w_pend |
+----------------------------------------------------+--------+--------+
- write_index/read_index (32位架构上的16位,64位架构上的48位):环形缓冲区中当前读/写位置(头和尾)。
- r_pend/w_pend (8位):挂起的并发读/写次数
- r_done/w_done (8位):完成的读/写次数。
读取时,首先增加 r_pend,然后从内存中读取环形缓冲区的内容。读取完成后,增加 r_done。只有当 r_done 等于 r_pend 时才增加 read_index。
写入时,首先增加 w_pend,然后更新环形缓冲区的内容。写入完成后,增加 w_done。如果 w_done 等于 w_pend,则两者都设置为0,并增加 write_index。
在罕见的情况下,这可能导致多个线程轮流增加 r_pend,而 r_done 永远达不到 r_pend 的竞争。如果 r_pend == 255 或 w_pend == 255,则自旋循环等待它变为 <255 以继续。这在实践中很少发生,这就是为什么它被称为几乎无锁。
结构体
此包提供了不带阻塞弹出支持的 AtomicRingBuffer
和带阻塞弹出支持的 AtomicRingQueue
。
依赖项
此包依赖于 parking_lot 在 AtomicRingQueue 中提供阻塞支持
使用方法
要使用 AtomicRingBuffer,请将以下内容添加到您的 Cargo.toml
[dependencies]
atomicring = "1.2.9"
并在您的代码中添加类似以下内容
// create an AtomicRingBuffer with capacity of 1024 elements
let ring = ::atomicring::AtomicRingBuffer::with_capacity(900);
// try_pop removes an element of the buffer and returns None if the buffer is empty
assert_eq!(None, ring.try_pop());
// push_overwrite adds an element to the buffer, overwriting the oldest element if the buffer is full:
ring.push_overwrite(1);
assert_eq!(Some(1), ring.try_pop());
assert_eq!(None, ring.try_pop());
许可证
根据MIT许可证和Apache许可证(版本2.0)授权。
请参阅LICENSE-MIT和LICENSE-APACHE获取详细信息。
依赖项
~480–790KB
~13K SLoC