From e817767670797b19acfc60721e9db106ddfa06a2 Mon Sep 17 00:00:00 2001 From: jdonszelmann Date: Sat, 16 Sep 2023 14:08:57 +0200 Subject: [PATCH] implement returning of old elements on enqueue --- src/lib.rs | 22 +++++++++++----------- src/ringbuffer_trait.rs | 14 ++++++++++---- src/with_alloc/alloc_ringbuffer.rs | 27 ++++++++++++++------------- src/with_alloc/vecdeque.rs | 3 ++- src/with_const_generics.rs | 22 ++++++++++++++-------- 5 files changed, 51 insertions(+), 37 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fa3dd17..8db0193 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,7 +64,7 @@ mod tests { const capacity: usize = 8; fn test_neg_index(mut b: impl RingBuffer) { for i in 0..capacity + 2 { - b.push(i); + let _ = b.push(i); assert_eq!(b.get_signed(-1), Some(&i)); } } @@ -114,9 +114,9 @@ mod tests { fn run_test_len() { fn test_len(mut b: impl RingBuffer) { 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()) } @@ -129,14 +129,14 @@ mod tests { fn run_test_len_wrap() { fn test_len_wrap(mut b: impl RingBuffer) { 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()); } @@ -1033,15 +1033,15 @@ mod tests { #[test] fn run_test_enqueue_dequeue_push() { fn test_enqueue_dequeue_push(mut b: impl RingBuffer) { - 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)); diff --git a/src/ringbuffer_trait.rs b/src/ringbuffer_trait.rs index ae92f09..7d718c1 100644 --- a/src/ringbuffer_trait.rs +++ b/src/ringbuffer_trait.rs @@ -76,12 +76,18 @@ pub unsafe trait RingBuffer: 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; /// dequeues the top item off the ringbuffer, and moves this item out. fn dequeue(&mut self) -> Option; diff --git a/src/with_alloc/alloc_ringbuffer.rs b/src/with_alloc/alloc_ringbuffer.rs index 730b67d..b01ddd6 100644 --- a/src/with_alloc/alloc_ringbuffer.rs +++ b/src/with_alloc/alloc_ringbuffer.rs @@ -163,7 +163,7 @@ impl Clone for AllocRingBuffer { 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 } } @@ -229,20 +229,15 @@ unsafe impl RingBuffer for AllocRingBuffer { impl_ringbuffer!(readptr, writeptr); #[inline] - fn push(&mut self, value: T) { + fn enqueue(&mut self, value: T) -> Option { + 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; } @@ -254,6 +249,8 @@ unsafe impl RingBuffer for AllocRingBuffer { } self.writeptr += 1; + + ret } fn dequeue(&mut self) -> Option { @@ -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()); @@ -420,7 +417,9 @@ mod tests { #[test] fn test_extend() { let mut buf = AllocRingBuffer::::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); @@ -437,7 +436,9 @@ mod tests { #[test] fn test_extend_with_overflow() { let mut buf = AllocRingBuffer::::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); diff --git a/src/with_alloc/vecdeque.rs b/src/with_alloc/vecdeque.rs index 23adeb1..df46a76 100644 --- a/src/with_alloc/vecdeque.rs +++ b/src/with_alloc/vecdeque.rs @@ -186,8 +186,9 @@ unsafe impl RingBuffer for GrowableAllocRingBuffer { self.pop_front() } - fn push(&mut self, value: T) { + fn enqueue(&mut self, value: T) -> Option { self.push_back(value); + None } fn fill_with T>(&mut self, mut f: F) { diff --git a/src/with_const_generics.rs b/src/with_const_generics.rs index e4b6570..026c656 100644 --- a/src/with_const_generics.rs +++ b/src/with_const_generics.rs @@ -138,7 +138,7 @@ impl Drop for ConstGenericRingBuffer { impl Clone for ConstGenericRingBuffer { fn clone(&self) -> Self { let mut new = ConstGenericRingBuffer::::new(); - self.iter().cloned().for_each(|i| new.push(i)); + new.extend(self.iter().cloned()); new } } @@ -265,7 +265,9 @@ unsafe impl RingBuffer for ConstGenericRingBuffer Option { + let mut ret = None; + if self.is_full() { let previous_value = mem::replace( &mut self.buf[crate::mask_modulo(CAP, self.readptr)], @@ -275,14 +277,14 @@ unsafe impl RingBuffer for ConstGenericRingBuffer Option { @@ -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()); @@ -387,7 +389,9 @@ mod tests { #[test] fn test_extend() { let mut buf = ConstGenericRingBuffer::::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); @@ -404,7 +408,9 @@ mod tests { #[test] fn test_extend_with_overflow() { let mut buf = ConstGenericRingBuffer::::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);