low_latency_data_structures/spsc/
producer.rs1use std::marker::PhantomData;
2
3use crossbeam_utils::CachePadded;
4
5use crate::mem::Allocator;
6use crate::shim::cell::Cell;
7use crate::shim::sync::Arc;
8use crate::shim::sync::atomic::AtomicUsize;
9use crate::spsc::queue::Queue;
10
11pub(super) type ProducerState = CachePadded<ProducerStateInner>;
12
13#[derive(Default)]
14pub(super) struct ProducerStateInner {
15 pub tail: AtomicUsize,
16 pub cached_head: Cell<usize>,
17}
18
19pub struct Producer<T, const CAPACITY: usize, A>
26where
27 A: Allocator,
28{
29 inner: Arc<Queue<T, CAPACITY, A>>,
30 _not_sync: PhantomData<*const ()>,
31}
32
33impl<T, const CAPACITY: usize, A> std::fmt::Debug for Producer<T, CAPACITY, A>
34where
35 A: Allocator,
36{
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.debug_struct("Producer")
39 .field("capacity", &CAPACITY)
40 .finish_non_exhaustive()
41 }
42}
43
44unsafe impl<T, const CAPACITY: usize, A> Send for Producer<T, CAPACITY, A>
47where
48 T: Send,
49 A: Allocator,
50 A::Allocation<T>: Send,
51{
52}
53
54impl<T, const CAPACITY: usize, A> Producer<T, CAPACITY, A>
55where
56 A: Allocator,
57{
58 pub(super) fn new(queue: Arc<Queue<T, CAPACITY, A>>) -> Self {
59 Self {
60 inner: queue,
61 _not_sync: PhantomData,
62 }
63 }
64
65 #[inline]
87 #[must_use = "if the queue is full, the returned item must be handled (e.g. retried) or it is silently dropped"]
88 pub fn push(&self, item: T) -> Option<T> {
89 self.inner.push(item)
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 use crate::mem::test_util::NeverAllocator;
97
98 static_assertions::assert_not_impl_any!(Producer<u32, 0, NeverAllocator>: Sync);
101}