use crate::iterators::sync_iterators::detached::Detached;
use crate::ring_buffer::OneRB;
use crate::ring_buffer::iters_components::PIterComponent;
use crate::ring_buffer::storage_components::{PStorageComponent, StorageComponent};
pub trait ORBIterator: PrivateORBIterator<_Buffer = Self::Buffer> {
type Item;
type Buffer: OneRB<Item = Self::Item>;
#[inline]
fn detach(self) -> Detached<Self>
where
Self: Sized,
{
Detached::from_iter(self)
}
#[inline]
unsafe fn advance(&mut self, count: usize) {
unsafe { self._advance(count) };
}
#[inline]
fn available(&mut self) -> usize {
self._available()
}
fn wait_for(&mut self, count: usize) {
while self.available() < count {}
}
#[inline]
fn index(&self) -> usize {
self._index()
}
#[inline]
fn buf_len(&self) -> usize {
self.buffer().len()
}
fn alive_iters(&self) -> u8 {
self.buffer().iters().alive_iters()
}
#[inline(always)]
fn prod_index(&self) -> usize {
self.buffer().iters().prod_index()
}
#[inline(always)]
fn work_index(&self) -> usize {
self.buffer().iters().work_index()
}
#[inline(always)]
fn cons_index(&self) -> usize {
self.buffer().iters().cons_index()
}
#[inline]
fn get_mut<'a>(&mut self) -> Option<&'a mut Self::Item> {
self.next_ref_mut()
}
#[inline]
fn get_mut_slice_exact<'a>(
&mut self,
count: usize,
) -> Option<<<Self::Buffer as OneRB>::Storage as StorageComponent>::SliceOutputMut<'a>> {
self.check(count).then(|| {
self.buffer()
.storage_mut()
.next_chunk_mut(self._index(), count)
})
}
#[inline]
fn get_mut_slice_avail<'a>(
&mut self,
) -> Option<<<Self::Buffer as OneRB>::Storage as StorageComponent>::SliceOutputMut<'a>> {
match self.available() {
0 => None,
avail => self.get_mut_slice_exact(avail),
}
}
#[inline]
fn get_mut_slice_multiple_of<'a>(
&mut self,
rhs: usize,
) -> Option<<<Self::Buffer as OneRB>::Storage as StorageComponent>::SliceOutputMut<'a>> {
let avail = self.available();
unsafe {
match avail.unchecked_sub(avail % rhs) {
0 => None,
avail => self.get_mut_slice_exact(avail),
}
}
}
}
pub(crate) trait PrivateORBIterator {
type _Buffer: OneRB;
fn buffer(&self) -> &Self::_Buffer;
fn _available(&mut self) -> usize;
fn cached_avail(&self) -> usize;
fn set_cached_avail(&mut self, avail: usize);
fn _index(&self) -> usize;
fn set_local_index(&mut self, index: usize);
fn set_atomic_index(&self, index: usize);
fn succ_index(&self) -> usize;
#[inline]
unsafe fn _advance(&mut self, count: usize) {
unsafe { self.advance_local(count) };
self.set_atomic_index(self._index());
}
#[inline]
unsafe fn advance_local(&mut self, count: usize) {
self.set_local_index(unsafe { self._index().unchecked_add(count) });
if self._index() >= self.buffer().len() {
self.set_local_index(unsafe { self._index().unchecked_sub(self.buffer().len()) });
}
self.set_cached_avail(self.cached_avail().saturating_sub(count));
}
#[inline]
fn check(&mut self, count: usize) -> bool {
self.cached_avail() >= count || self._available() >= count
}
#[inline]
fn next(&mut self) -> Option<<Self::_Buffer as OneRB>::Item> {
self.check(1).then(|| unsafe {
let ret = self.buffer().storage()._index(self._index()).take_inner();
self._advance(1);
ret
})
}
#[inline]
fn next_duplicate(&mut self) -> Option<<Self::_Buffer as OneRB>::Item> {
self.check(1).then(|| unsafe {
let ret = self
.buffer()
.storage()
._index(self._index())
.inner_duplicate();
self._advance(1);
ret
})
}
#[inline]
fn next_ref<'a>(&mut self) -> Option<&'a <Self::_Buffer as OneRB>::Item> {
unsafe {
self.check(1)
.then(|| self.buffer().storage()._index(self._index()).inner_ref())
}
}
#[inline]
fn next_ref_mut<'a>(&mut self) -> Option<&'a mut <Self::_Buffer as OneRB>::Item> {
unsafe {
self.check(1).then(|| {
self.buffer()
.storage()
._index(self._index())
.inner_ref_mut()
})
}
}
#[inline]
fn next_ref_mut_init(&mut self) -> Option<*mut <Self::_Buffer as OneRB>::Item> {
self.check(1)
.then(|| self.buffer().storage()._index(self._index()).as_mut_ptr())
}
}
pub(crate) mod iter_macros {
macro_rules! private_impl {
() => {
#[inline]
#[allow(refining_impl_trait)]
fn buffer(&self) -> &B {
&self.inner.buffer
}
#[inline]
fn _index(&self) -> usize {
self.inner.index
}
#[inline]
fn set_local_index(&mut self, index: usize) {
self.inner.index = index;
}
#[inline]
fn cached_avail(&self) -> usize {
self.inner.cached_avail
}
#[inline]
fn set_cached_avail(&mut self, avail: usize) {
self.inner.cached_avail = avail;
}
};
}
pub(crate) use private_impl;
}