Skip to content

Commit

Permalink
implement returning of old elements on enqueue
Browse files Browse the repository at this point in the history
  • Loading branch information
jdonszelmann committed Sep 16, 2023
1 parent 05b4975 commit e817767
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 37 deletions.
22 changes: 11 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ mod tests {
const capacity: usize = 8;
fn test_neg_index(mut b: impl RingBuffer<usize>) {
for i in 0..capacity + 2 {
b.push(i);
let _ = b.push(i);
assert_eq!(b.get_signed(-1), Some(&i));
}
}
Expand Down Expand Up @@ -114,9 +114,9 @@ mod tests {
fn run_test_len() {
fn test_len(mut b: impl RingBuffer<i32>) {
assert_eq!(0, b.len());
b.push(1);
let _ = b.push(1);
assert_eq!(1, b.len());
b.push(2);
let _ = b.push(2);
assert_eq!(2, b.len())
}

Expand All @@ -129,14 +129,14 @@ mod tests {
fn run_test_len_wrap() {
fn test_len_wrap(mut b: impl RingBuffer<i32>) {
assert_eq!(0, b.len());
b.push(1);
let _ = b.push(1);
assert_eq!(1, b.len());
b.push(2);
let _ = b.push(2);
assert_eq!(2, b.len());
// Now we are wrapping
b.push(3);
let _ = b.push(3);
assert_eq!(2, b.len());
b.push(4);
let _ = b.push(4);
assert_eq!(2, b.len());
}

Expand Down Expand Up @@ -1033,15 +1033,15 @@ mod tests {
#[test]
fn run_test_enqueue_dequeue_push() {
fn test_enqueue_dequeue_push(mut b: impl RingBuffer<i32>) {
b.enqueue(0);
b.enqueue(1);
b.push(0);
b.push(1);

assert_eq!(b.dequeue(), Some(0));
assert_eq!(b.dequeue(), Some(1));
assert_eq!(b.dequeue(), None);

b.enqueue(0);
b.enqueue(1);
b.push(0);
b.push(1);

assert_eq!(b.dequeue(), Some(0));
assert_eq!(b.dequeue(), Some(1));
Expand Down
14 changes: 10 additions & 4 deletions src/ringbuffer_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,18 @@ pub unsafe trait RingBuffer<T>:
unsafe fn ptr_buffer_size(rb: *const Self) -> usize;

/// Pushes a value onto the buffer. Cycles around if capacity is reached.
fn push(&mut self, value: T);
///
/// Does not return the oldest item in the buffer if the buffer is full, to more closely match the api of `push` on `Vec` and `VecDeque`.
/// If that property is desired, use [`dequeue`](RingBuffer::dequeue)
#[inline]
fn push(&mut self, value: T) {
let _ = self.enqueue(value);
}

/// alias for [`push`](RingBuffer::push), forming a more natural counterpart to [`dequeue`](RingBuffer::dequeue)
fn enqueue(&mut self, value: T) {
self.push(value);
}
///
/// If the buffer is full, returns the oldest item in the buffer that was just removed to make room for the pushed value.
fn enqueue(&mut self, value: T) -> Option<T>;

/// dequeues the top item off the ringbuffer, and moves this item out.
fn dequeue(&mut self) -> Option<T>;
Expand Down
27 changes: 14 additions & 13 deletions src/with_alloc/alloc_ringbuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl<T: Clone> Clone for AllocRingBuffer<T> {
debug_assert_ne!(self.capacity, 0);

let mut new = Self::new(self.capacity);
self.iter().cloned().for_each(|i| new.push(i));
new.extend(self.iter().cloned());
new
}
}
Expand Down Expand Up @@ -229,20 +229,15 @@ unsafe impl<T> RingBuffer<T> for AllocRingBuffer<T> {
impl_ringbuffer!(readptr, writeptr);

#[inline]
fn push(&mut self, value: T) {
fn enqueue(&mut self, value: T) -> Option<T> {
let mut ret = None;

if self.is_full() {
// mask with and is allowed here because size is always a power of two
let previous_value =
unsafe { ptr::read(get_unchecked_mut(self, mask_and(self.size, self.readptr))) };

// make sure we drop whatever is being overwritten
// SAFETY: the buffer is full, so this must be initialized
// : also, index has been masked
// make sure we drop because it won't happen automatically
unsafe {
drop(previous_value);
}

ret = Some(previous_value);
self.readptr += 1;
}

Expand All @@ -254,6 +249,8 @@ unsafe impl<T> RingBuffer<T> for AllocRingBuffer<T> {
}

self.writeptr += 1;

ret
}

fn dequeue(&mut self) -> Option<T> {
Expand Down Expand Up @@ -392,7 +389,7 @@ mod tests {
// messes up
for _ in 0..100 {
for i in 0..NUM_VALS {
rb.enqueue(i);
let _ = rb.enqueue(i);
}
assert!(rb.is_full());

Expand Down Expand Up @@ -420,7 +417,9 @@ mod tests {
#[test]
fn test_extend() {
let mut buf = AllocRingBuffer::<u8>::new(4);
(0..4).for_each(|_| buf.push(0));
(0..4).for_each(|_| {
let _ = buf.push(0);
});

let new_data = [0, 1, 2];
buf.extend(new_data);
Expand All @@ -437,7 +436,9 @@ mod tests {
#[test]
fn test_extend_with_overflow() {
let mut buf = AllocRingBuffer::<u8>::new(8);
(0..8).for_each(|_| buf.push(0));
(0..8).for_each(|_| {
let _ = buf.push(0);
});

let new_data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
buf.extend(new_data);
Expand Down
3 changes: 2 additions & 1 deletion src/with_alloc/vecdeque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,9 @@ unsafe impl<T> RingBuffer<T> for GrowableAllocRingBuffer<T> {
self.pop_front()
}

fn push(&mut self, value: T) {
fn enqueue(&mut self, value: T) -> Option<T> {
self.push_back(value);
None
}

fn fill_with<F: FnMut() -> T>(&mut self, mut f: F) {
Expand Down
22 changes: 14 additions & 8 deletions src/with_const_generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ impl<T, const CAP: usize> Drop for ConstGenericRingBuffer<T, CAP> {
impl<T: Clone, const CAP: usize> Clone for ConstGenericRingBuffer<T, CAP> {
fn clone(&self) -> Self {
let mut new = ConstGenericRingBuffer::<T, CAP>::new();
self.iter().cloned().for_each(|i| new.push(i));
new.extend(self.iter().cloned());
new
}
}
Expand Down Expand Up @@ -265,7 +265,9 @@ unsafe impl<T, const CAP: usize> RingBuffer<T> for ConstGenericRingBuffer<T, CAP
impl_ringbuffer!(readptr, writeptr);

#[inline]
fn push(&mut self, value: T) {
fn enqueue(&mut self, value: T) -> Option<T> {
let mut ret = None;

if self.is_full() {
let previous_value = mem::replace(
&mut self.buf[crate::mask_modulo(CAP, self.readptr)],
Expand All @@ -275,14 +277,14 @@ unsafe impl<T, const CAP: usize> RingBuffer<T> for ConstGenericRingBuffer<T, CAP
// SAFETY: the buffer is full, so this must be initialized
// : also, index has been masked
// make sure we drop because it won't happen automatically
unsafe {
drop(previous_value.assume_init());
}
ret = Some(unsafe { previous_value.assume_init() });
self.readptr += 1;
}
let index = crate::mask_modulo(CAP, self.writeptr);
self.buf[index] = MaybeUninit::new(value);
self.writeptr += 1;

ret
}

fn dequeue(&mut self) -> Option<T> {
Expand Down Expand Up @@ -365,7 +367,7 @@ mod tests {
// messes up
for _ in 0..100 {
for i in 0..NUM_VALS {
rb.enqueue(i);
let _ = rb.enqueue(i);
}
assert!(rb.is_full());

Expand All @@ -387,7 +389,9 @@ mod tests {
#[test]
fn test_extend() {
let mut buf = ConstGenericRingBuffer::<u8, 4>::new();
(0..4).for_each(|_| buf.push(0));
(0..4).for_each(|_| {
let _ = buf.push(0);
});

let new_data = [0, 1, 2];
buf.extend(new_data);
Expand All @@ -404,7 +408,9 @@ mod tests {
#[test]
fn test_extend_with_overflow() {
let mut buf = ConstGenericRingBuffer::<u8, 8>::new();
(0..8).for_each(|_| buf.push(0));
(0..8).for_each(|_| {
let _ = buf.push(0);
});

let new_data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
buf.extend(new_data);
Expand Down

1 comment on commit e817767

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.