use std::marker::PhantomData;
use crate::mem::Allocation;
use crate::shim::cell::Cell;
use crate::shim::sync::Arc;
use crate::shim::sync::atomic::AtomicUsize;
use crate::spsc::queue::Queue;
#[repr(C, align(128))]
pub(super) struct ProducerState {
pub tail: AtomicUsize,
pub cached_head: Cell<usize>,
}
pub struct Producer<T, const CAPACITY: usize, AllocT: Allocation<T>> {
inner: Arc<Queue<T, CAPACITY, AllocT>>,
_not_sync: PhantomData<*const ()>,
}
impl<T, const CAPACITY: usize, AllocT: Allocation<T>> std::fmt::Debug
for Producer<T, CAPACITY, AllocT>
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Producer")
.field("capacity", &CAPACITY)
.finish_non_exhaustive()
}
}
unsafe impl<T: Send, const CAPACITY: usize, AllocT: Allocation<T> + Send> Send
for Producer<T, CAPACITY, AllocT>
{
}
impl<T, const CAPACITY: usize, AllocT: Allocation<T>> Producer<T, CAPACITY, AllocT> {
pub(super) fn new(queue: Arc<Queue<T, CAPACITY, AllocT>>) -> Self {
Self {
inner: queue,
_not_sync: PhantomData,
}
}
#[inline]
#[must_use = "if the queue is full, the returned item must be handled (e.g. retried) or it is silently dropped"]
pub fn push(&self, item: T) -> Option<T> {
self.inner.push(item)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::shim::cell::UnsafeCell;
struct NeverAlloc;
impl<T> Allocation<T> for NeverAlloc {
fn ptr(&self) -> *mut UnsafeCell<std::mem::MaybeUninit<T>> {
unreachable!("it's just a stub")
}
}
static_assertions::assert_not_impl_any!(Producer<u32, 0, NeverAlloc>: Sync);
}