use crate::{Consumer, Producer, SpscRingBuffer};
pub struct MpscFanIn;
impl MpscFanIn {
pub fn with_capacity<T: Send + 'static>(
producer_count: usize,
per_ring_capacity: usize,
) -> (Vec<MpscFanInProducer<T>>, MpscFanInConsumer<T>) {
assert!(producer_count >= 1, "need at least one producer");
let mut producers = Vec::with_capacity(producer_count);
let mut consumers = Vec::with_capacity(producer_count);
for _ in 0..producer_count {
let (p, c) = SpscRingBuffer::with_capacity::<T>(per_ring_capacity);
producers.push(MpscFanInProducer { inner: p });
consumers.push(c);
}
(
producers,
MpscFanInConsumer {
rings: consumers,
cursor: 0,
},
)
}
}
pub struct MpscFanInProducer<T> {
inner: Producer<T>,
}
impl<T> MpscFanInProducer<T> {
pub fn try_push(&mut self, value: T) -> Result<(), T> {
self.inner.try_push(value)
}
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
}
pub struct MpscFanInConsumer<T> {
rings: Vec<Consumer<T>>,
cursor: usize,
}
impl<T> MpscFanInConsumer<T> {
pub fn try_pop(&mut self) -> Option<T> {
let n = self.rings.len();
for offset in 0..n {
let idx = (self.cursor + offset) % n;
if let Some(v) = self.rings[idx].try_pop() {
self.cursor = (idx + 1) % n;
return Some(v);
}
}
None
}
pub fn producer_count(&self) -> usize {
self.rings.len()
}
}
#[cfg(test)]
#[path = "mpsc_fan_in_tests.rs"]
mod tests;