Skip to content

Commit

Permalink
IntoIter and PopIter now associated types
Browse files Browse the repository at this point in the history
  • Loading branch information
agerasev committed Aug 1, 2023
1 parent fa3af6d commit 2df5e2c
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 66 deletions.
15 changes: 14 additions & 1 deletion src/halves/cached.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use super::{
};
use crate::{
impl_consumer_traits, impl_producer_traits,
rb::traits::{RbRef, ToRbRef},
rb::{
iter::PopIter,
traits::{RbRef, ToRbRef},
},
traits::{Consumer, Observe, Observer, Producer},
};
use core::{mem::MaybeUninit, num::NonZeroUsize};
Expand Down Expand Up @@ -142,6 +145,16 @@ impl<R: RbRef> Consumer for CachingCons<R> {
}
r
}

type IntoIter = PopIter<R>;
fn into_iter(self) -> Self::IntoIter {
unsafe { PopIter::new(self.frozen.into_rb_ref()) }
}

type PopIter<'a> = PopIter<&'a R::Target> where R:'a, R::Target: 'a;
fn pop_iter(&mut self) -> Self::PopIter<'_> {
unsafe { PopIter::new(self.frozen.rb_ref().deref()) }
}
}

impl_producer_traits!(CachingProd<R: RbRef>);
Expand Down
17 changes: 15 additions & 2 deletions src/halves/direct.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::{
delegate_observer, impl_consumer_traits, impl_producer_traits,
rb::traits::{RbRef, ToRbRef},
traits::{Consumer, Observe, Observer, Producer},
rb::{
iter::PopIter,
traits::{RbRef, ToRbRef},
},
traits::{Consumer, Observe, Observer, Producer, RingBuffer},
};

/// Observer of ring buffer.
Expand Down Expand Up @@ -91,6 +94,16 @@ impl<R: RbRef> Consumer for Cons<R> {
unsafe fn set_read_index(&self, value: usize) {
self.rb().set_read_index(value)
}

type IntoIter = PopIter<R>;
fn into_iter(self) -> Self::IntoIter {
unsafe { PopIter::new(self.rb) }
}

type PopIter<'a> = PopIter<&'a R::Target> where R:'a, R::Target: 'a;
fn pop_iter(&mut self) -> Self::PopIter<'_> {
unsafe { PopIter::new(&self.rb.deref()) }
}
}

impl_producer_traits!(Prod<R: RbRef>);
Expand Down
15 changes: 14 additions & 1 deletion src/halves/frozen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

use super::direct::{Cons, Obs, Prod};
use crate::{
rb::traits::{RbRef, ToRbRef},
rb::{
iter::PopIter,
traits::{RbRef, ToRbRef},
},
traits::{Consumer, Observe, Observer, Producer},
};
use core::{
Expand Down Expand Up @@ -81,6 +84,16 @@ impl<R: RbRef> Consumer for FrozenCons<R> {
unsafe fn set_read_index(&self, value: usize) {
self.read.set(value);
}

type IntoIter = PopIter<R>;
fn into_iter(self) -> Self::IntoIter {
unsafe { PopIter::new(self.into_rb_ref()) }
}

type PopIter<'a> = PopIter<&'a R::Target> where R:'a, R::Target: 'a;
fn pop_iter(&mut self) -> Self::PopIter<'_> {
unsafe { PopIter::new(&self.rb.deref()) }
}
}

impl<R: RbRef> Producer for FrozenProd<R> {
Expand Down
12 changes: 11 additions & 1 deletion src/rb/local.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{macros::rb_impl_init, traits::RbRef, utils::ranges};
use super::{iter::PopIter, macros::rb_impl_init, traits::RbRef, utils::ranges};
#[cfg(feature = "alloc")]
use crate::traits::Split;
use crate::{
Expand Down Expand Up @@ -83,6 +83,16 @@ impl<S: Storage> Consumer for LocalRb<S> {
unsafe fn set_read_index(&self, value: usize) {
self.read.set(value);
}

type IntoIter = PopIter<Self>;
fn into_iter(self) -> Self::IntoIter {
unsafe { PopIter::new(self) }
}

type PopIter<'a> = PopIter<&'a Self> where S: 'a;
fn pop_iter(&mut self) -> Self::PopIter<'_> {
unsafe { PopIter::new(self) }
}
}

impl<S: Storage> RingBuffer for LocalRb<S> {}
Expand Down
12 changes: 11 additions & 1 deletion src/rb/shared.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{macros::rb_impl_init, traits::RbRef, utils::ranges};
use super::{iter::PopIter, macros::rb_impl_init, traits::RbRef, utils::ranges};
#[cfg(feature = "alloc")]
use crate::traits::Split;
use crate::{
Expand Down Expand Up @@ -111,6 +111,16 @@ impl<S: Storage> Consumer for SharedRb<S> {
unsafe fn set_read_index(&self, value: usize) {
self.read.store(value, Ordering::Release);
}

type IntoIter = PopIter<Self>;
fn into_iter(self) -> Self::IntoIter {
unsafe { PopIter::new(self) }
}

type PopIter<'a> = PopIter<&'a Self> where S: 'a;
fn pop_iter(&mut self) -> Self::PopIter<'_> {
unsafe { PopIter::new(self) }
}
}

impl<S: Storage> RingBuffer for SharedRb<S> {}
Expand Down
5 changes: 1 addition & 4 deletions src/rb/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ pub unsafe trait RbRef: AsRef<Self::Target> {
}
}

unsafe impl<'a, B: RingBuffer> RbRef for &'a B
where
B: RbRef<Target = B>,
{
unsafe impl<'a, B: RingBuffer> RbRef for &'a B {
type Target = B;
fn deref(&self) -> &Self::Target {
self
Expand Down
63 changes: 8 additions & 55 deletions src/traits/consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,16 @@ pub trait Consumer: Observer {
count
}

fn into_iter(self) -> IntoIter<Self> {
IntoIter::new(self)
}
type IntoIter: Iterator<Item = <Self as Observer>::Item>;

fn into_iter(self) -> Self::IntoIter;

type PopIter<'a>: Iterator<Item = <Self as Observer>::Item> + 'a
where
Self: 'a;

/// Returns an iterator that removes items one by one from the ring buffer.
fn pop_iter(&mut self) -> PopIter<'_, Self> {
PopIter::new(self)
}
fn pop_iter(&mut self) -> Self::PopIter<'_>;

/// Returns a front-to-back iterator containing references to items in the ring buffer.
///
Expand Down Expand Up @@ -232,55 +234,6 @@ impl<C: Consumer> Iterator for IntoIter<C> {
}
}

/// An iterator that removes items from the ring buffer.
pub struct PopIter<'a, C: Consumer> {
target: &'a C,
slices: (&'a [MaybeUninit<C::Item>], &'a [MaybeUninit<C::Item>]),
len: usize,
}
impl<'a, C: Consumer> PopIter<'a, C> {
pub fn new(target: &'a mut C) -> Self {
let slices = target.occupied_slices();
Self {
len: slices.0.len() + slices.1.len(),
slices,
target,
}
}
}
impl<'a, C: Consumer> Iterator for PopIter<'a, C> {
type Item = C::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.slices.0.len() {
0 => None,
n => {
let item = unsafe { self.slices.0.get_unchecked(0).assume_init_read() };
if n == 1 {
(self.slices.0, self.slices.1) = (self.slices.1, &[]);
} else {
self.slices.0 = unsafe { self.slices.0.get_unchecked(1..n) };
}
Some(item)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len(), Some(self.len()))
}
}
impl<'a, C: Consumer> ExactSizeIterator for PopIter<'a, C> {
fn len(&self) -> usize {
self.slices.0.len() + self.slices.1.len()
}
}
impl<'a, C: Consumer> Drop for PopIter<'a, C> {
fn drop(&mut self) {
unsafe { self.target.advance_read_index(self.len - self.len()) };
}
}

/// Iterator over ring buffer contents.
///
/// *Please do not rely on actual type, it may change in future.*
Expand Down
2 changes: 1 addition & 1 deletion src/traits/ring_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::{Consumer, Observer, Producer};
/// It allows us to distinguish situations when the buffer is empty (`read == write`) and when the buffer is full (`write - read` modulo `2 * capacity` equals to `capacity`)
/// without using the space for an extra element in container.
/// And obviously we cannot store more than `capacity` items in the buffer, so `write - read` modulo `2 * capacity` is not allowed to be greater than `capacity`.
pub trait RingBuffer: Observer + Consumer + Producer {
pub trait RingBuffer: Observer + Consumer + Producer + AsRef<Self> {
/// Pushes an item to the ring buffer overwriting the latest item if the buffer is full.
///
/// Returns overwritten item if overwriting took place.
Expand Down

0 comments on commit 2df5e2c

Please sign in to comment.