Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ringbuffer"
version = "1.0.0"
version = "0.4.0"
authors = ["Victor Roest <victor@xirion.net>", "Jonathan Dönszelmann <jonabent@gmail.com>"]
edition = "2018"
description = "A fixed-size circular buffer"
Expand All @@ -16,6 +16,7 @@ lto = true
[dependencies]
generic-array = {version = "0.14.4", optional=true}
array-init = {git = "https://github.com/manishearth/array-init", version = "0.1.1", optional=true}
spin = {version="0.5.2", optional=true}

[dev-dependencies]
criterion = "0.1.2"
Expand All @@ -25,6 +26,8 @@ default = ["alloc", "generic-array"]
# disable the alloc based ringbuffer, to make RingBuffers work in no_alloc environments
alloc = []

threads = ["spin"]

# enable the version of RingBuffer which uses the experimental const_generics feature of rust
const_generics = ["array-init", "array-init/const-generics"]

Expand Down
43 changes: 23 additions & 20 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,55 +3,58 @@ extern crate criterion;

use criterion::{black_box, Bencher, Criterion};
use ringbuffer::typenum::*;
use ringbuffer::{AllocRingBuffer, ConstGenericRingBuffer, GenericRingBuffer, RingBuffer};
use ringbuffer::{
AllocRingBuffer, ConstGenericRingBuffer, GenericRingBuffer, ReadableRingbuffer, RingBuffer,
RingBufferExt, WritableRingbuffer,
};

fn benchmark_push<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
fn benchmark_push<T: RingBufferExt<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
b.iter(|| {
let mut rb = new();

for i in 0..1_000_000 {
rb.push(i)
rb.push_force(i);
}

rb
})
}

fn benchmark_push_dequeue<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
fn benchmark_push_dequeue<T: RingBufferExt<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
b.iter(|| {
let mut rb = new();

for i in 0..100_000 {
rb.push(1);
rb.push(2);
rb.push_force(1);
rb.push_force(2);

assert_eq!(rb.dequeue(), Some(1));
assert_eq!(rb.dequeue(), Some(2));
assert_eq!(rb.pop(), Some(1));
assert_eq!(rb.pop(), Some(2));

rb.push(1);
rb.push(2);
rb.push_force(1);
rb.push_force(2);

assert_eq!(rb.dequeue(), Some(1));
assert_eq!(rb.dequeue(), Some(2));
assert_eq!(rb.pop(), Some(1));
assert_eq!(rb.pop(), Some(2));

rb.push(1);
rb.push(2);
rb.push_force(1);
rb.push_force(2);

assert_eq!(rb.get(-1), Some(&2));
assert_eq!(rb.get(-2), Some(&1));
assert_eq!(rb.get(0), Some(&1));
assert_eq!(rb.get(1), Some(&2));
}

rb
})
}

fn benchmark_various<T: RingBuffer<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
fn benchmark_various<T: RingBufferExt<i32>, F: Fn() -> T>(b: &mut Bencher, new: F) {
b.iter(|| {
let mut rb = new();

for i in 0..100_000 {
rb.push(i);
black_box(rb.get(-1));
rb.push_force(i);
black_box(rb.get(0));
}

rb
Expand Down Expand Up @@ -153,7 +156,7 @@ fn criterion_benchmark(c: &mut Criterion) {
U8192
];

generate_benches![
generate_benche![
called,
c,
AllocRingBuffer,
Expand Down
66 changes: 66 additions & 0 deletions doc/interface.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

The ringbuffer crate provides four traits. In this document their methods are described.

# DEFINITIONS

In this document, `front` refers to the item last pushed to the queue. `back` refers to the
item pushed longest ago and thus the item that will be dequeud next.

Relative indexing (like with get and get_mut) works from the `back` and counts towards the front.
`get(0)` == `back` and `get(1)` will be dequeued right after `get(0)`

# RingBuffer

This trait must be implemented for any ringbuffer. It's the "base" trait.
With it you can't actually do anything really useful, but it provides some
basic methods.

| function | description |
| --- | ---|
| `len()` | number of items in the ringbuffer |
| `is_empty()` | returns true if the length is zero |
| `is_full()` | returns true if the length equals the capacity |
| `clear` | sets the length back to zero and removes all items from the ringbuffer |
| `capacity` | the maximum number of items in the ringbuffer |


# ReadableRingbuffer

With this trait it's possible to use the ringbuffer as the read end of a queue.

| function | description |
| --- | ---|
| `skip()` | Like dequeue but drops the items it removes from the ringbuffer |
| `dequeue()` | Removes the item pushed longest ago (fifo) from the ringbuffer and returns it. |

# WritableRingbuffer

With this trait it's possible to use the ringbuffer as the write end of a queue.

| function | description |
| --- | ---|
| `push(item)` | Adds an item to the ringbuffer. Overwrites the item pushed longest ago from the ringbuffer when it was full. |

# RingBufferExt

Provides general purpose methods to modify the ringbuffer as if it was an array.
This trait is not implemented for Ringbuffers which can purely be used as a queue.

| function | description |
| --- | ---|
| `contains(item)` | returns true if item is in the buffer |
| `front()` | Returns a reference to the item pushed most recently |
| `back()` | Returns a reference to the item which would be dequeued next |
| `back_mut()` | Like back but mutable |
| `front_mut()` | Like front but mutable |
| `iter()` | Returns an immutable iterator over the elements in the ringbuffer |
| `iter_mut()` | Like iter but mutable. Not actually an iterator due to lifetime constraints. |
| `to_vec()` | Converts the Ringbuffer to a vec. |
| `get(n)` | Returns a reference to the nth item from the readhead. This means that get(0) returns what will be dequeued next, and get(1) will be dequeued after that. |
| `get_absolute(n)` | Returns a reference to nth item relative to the start of the underlying non-circular buffer. |
| `get_mut(n)` | Like get but mutable |
| `get_absolute(n)` | Like get_absolute but mutable |




Loading