use std::marker::PhantomData;
use crossbeam_utils::CachePadded;
use crate::mem::Allocator;
use crate::shim::cell::Cell;
use crate::shim::sync::Arc;
use crate::shim::sync::atomic::AtomicUsize;
use crate::spsc::queue::Queue;
pub(super) type ConsumerState = CachePadded<ConsumerStateInner>;
#[derive(Default)]
pub(super) struct ConsumerStateInner {
pub head: AtomicUsize,
pub cached_tail: Cell<usize>,
}
pub struct Consumer<T, const CAPACITY: usize, A>
where
A: Allocator,
{
inner: Arc<Queue<T, CAPACITY, A>>,
_not_sync: PhantomData<*const ()>,
}
impl<T, const CAPACITY: usize, A> std::fmt::Debug for Consumer<T, CAPACITY, A>
where
A: Allocator,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Consumer")
.field("capacity", &CAPACITY)
.finish_non_exhaustive()
}
}
unsafe impl<T, const CAPACITY: usize, A> Send for Consumer<T, CAPACITY, A>
where
T: Send,
A: Allocator,
A::Allocation<T>: Send,
{
}
impl<T, const CAPACITY: usize, A> Consumer<T, CAPACITY, A>
where
A: Allocator,
{
pub(super) fn new(queue: Arc<Queue<T, CAPACITY, A>>) -> Self {
Self {
inner: queue,
_not_sync: PhantomData,
}
}
#[inline]
#[must_use = "ignoring the popped item silently drops it"]
pub fn pop(&self) -> Option<T> {
self.inner.pop()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::mem::test_util::NeverAllocator;
static_assertions::assert_not_impl_any!(Consumer<u32, 0, NeverAllocator>: Sync);
}