3个版本
0.1.2 | 2020年7月25日 |
---|---|
0.1.1 | 2020年7月25日 |
0.1.0 | 2020年7月25日 |
#17 in #zero-allocation
用于 2 crates
28KB
551 行
CircularBuffer
一个零依赖、零运行时分配的循环缓冲区。
这个crate提供了一个简单的循环缓冲区,在运行时不会进行任何分配。这个crate的主要关注点是正确性和性能。
循环缓冲区从不等待,如果缓冲区已满,它会覆盖第一个元素。
API非常简单,你创建缓冲区并指定缓冲区可以容纳多少个元素。然后你可以开始向其中推送元素。
use rbl_circular_buffer::*;
let mut buffer = CircularBuffer::new(3);
assert_eq!(0, buffer.len());
buffer.push(1);
assert_eq!(1, buffer.len());
buffer.push(2);
assert_eq!(2, buffer.len());
buffer.push(3);
assert_eq!(3, buffer.len());
// now the buffer is full, we can insert the next element, but it will overwrite the first one
buffer.push(4);
assert_eq!(3, buffer.len());
let v: Vec<u32> = buffer.collect();
assert_eq!(vec![2,3,4], v);
从缓冲区中读取元素有两种方式。
CircularBuffer
实现了Iterator
特性,你可以遍历它。CircularBuffer
提供了.fill()
方法。
使用迭代器
迭代器会消耗缓冲区中的元素。
use rbl_circular_buffer::*;
let mut buffer = CircularBuffer::new(3);
buffer.push(1);
buffer.push(2);
buffer.push(3);
let mut sum = 0;
for element in &mut buffer {
sum += element;
}
assert_eq!(1 + 2 + 3, sum);
assert_eq!(0, buffer.len());
填充向量
在性能要求高的应用中,迭代器可能不是一个好选择。
考虑线程之间的通信,每个线程都可以有一个 CircularBuffer
的引用,并在读取时获取锁。如果读取操作不够快,或者简单地元素太多,锁将被保持很长时间。另一种选择是填充一个向量。
use rbl_circular_buffer::*;
// let's make a bigger vector
let mut buffer = CircularBuffer::new(5);
for i in 1..=5 {
buffer.push(i);
}
// with this vector we will remove the first 3 elements
let mut v = Vec::with_capacity(3);
buffer.fill(&mut v);
assert_eq!(vec![1, 2, 3], v);
// in the vector there are still 4 and 5
assert_eq!(2, buffer.len());
buffer.push(6);
buffer.push(7);
buffer.push(8);
// the fill avoid any allocation even in the vector to fill.
// if we remove one element, and refill, we will push only one element.
// this because `.fill()` does not allocate any memory.
v.remove(0);
buffer.fill(&mut v);
assert_eq!(vec![2, 3, 4], v);
assert_eq!(4, buffer.len())