use thiserror::Error;
pub mod multi;
pub mod single;
use crate::{barrier::Barrier, ringbuffer::RingBuffer, Sequence};
use std::sync::{atomic::AtomicI64, Arc};
#[doc(hidden)]
pub trait ProducerBarrier: Barrier {
fn publish(&self, sequence: Sequence);
}
#[derive(Debug, Error, PartialEq)]
#[error("Ring Buffer is full.")]
pub struct RingBufferFull;
#[derive(Debug, Error, PartialEq)]
#[error("Missing free slots in Ring Buffer: {0}")]
pub struct MissingFreeSlots(pub u64);
pub struct MutBatchIter<'a, E> {
ring_buffer: &'a RingBuffer<E>,
current: Sequence, last: Sequence, }
impl<'a, E> MutBatchIter<'a, E> {
#[inline]
fn new(start: Sequence, end: Sequence, ring_buffer: &'a RingBuffer<E>) -> Self {
Self {
ring_buffer,
current: start,
last: end,
}
}
#[inline]
fn remaining(&self) -> usize {
if self.current > self.last {
0
} else {
(self.last - self.current + 1) as usize
}
}
}
impl<'a, E> Iterator for MutBatchIter<'a, E> {
type Item = &'a mut E;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.current > self.last {
None
} else {
let event_ptr = unsafe { self.ring_buffer.get(self.current).as_ptr() };
let event = unsafe { &mut *event_ptr };
self.current += 1;
Some(event)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.remaining();
(remaining, Some(remaining))
}
}
impl<E> ExactSizeIterator for MutBatchIter<'_, E> {
#[inline]
fn len(&self) -> usize {
self.remaining()
}
}
impl<E> std::iter::FusedIterator for MutBatchIter<'_, E> {}
pub trait Producer<E> {
fn try_publish<F>(&mut self, update: F) -> Result<Sequence, RingBufferFull>
where
F: FnOnce(&mut E);
fn try_batch_publish<F>(&mut self, n: usize, update: F) -> Result<Sequence, MissingFreeSlots>
where
F: for<'a> FnOnce(MutBatchIter<'a, E>);
fn publish<F>(&mut self, update: F)
where
F: FnOnce(&mut E);
fn batch_publish<F>(&mut self, n: usize, update: F)
where
F: for<'a> FnOnce(MutBatchIter<'a, E>);
}