1use std::fmt;
2use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
3
4use super::{OverflowPolicy, QueueError, QueueResult, QueueStatsSnapshot, RtQueueBase};
5use crate::buffer::AtomicCell;
6
7#[repr(C, align(64))]
16pub struct SpscQueue<T: Copy, const CAP: usize> {
17 buffer: [AtomicCell<T>; CAP],
19 head: AtomicUsize,
21 tail: AtomicUsize,
23 full: AtomicBool,
25 mask: usize,
27 overflow_policy: OverflowPolicy,
29 default_value: Option<T>,
31}
32
33impl<T: Copy + Default, const CAP: usize> SpscQueue<T, CAP> {
34 pub fn new() -> Self {
41 assert!(CAP.is_power_of_two(), "CAP must be a power of two");
42
43 let buffer = std::array::from_fn(|_| AtomicCell::new(T::default()));
44
45 Self {
46 buffer,
47 head: AtomicUsize::new(0),
48 tail: AtomicUsize::new(0),
49 full: AtomicBool::new(false),
50 mask: CAP - 1,
51 overflow_policy: OverflowPolicy::OverwriteOldest,
52 default_value: None,
53 }
54 }
55
56 pub fn with_policies(overflow_policy: OverflowPolicy, default_value: Option<T>) -> Self {
58 let mut queue = Self::new();
59 queue.overflow_policy = overflow_policy;
60 queue.default_value = default_value;
61 queue
62 }
63
64 pub fn push(&self, value: T) -> QueueResult<()> {
75 let head = self.head.load(Ordering::Relaxed);
76 let next_head = (head + 1) & self.mask;
77
78 if self.full.load(Ordering::Acquire) {
79 match self.overflow_policy {
80 OverflowPolicy::OverwriteOldest => {
81 self.tail.store(
82 (self.tail.load(Ordering::Relaxed) + 1) & self.mask,
83 Ordering::Release,
84 );
85 self.full.store(false, Ordering::Release);
86 }
87
88 OverflowPolicy::DropNewest => {
89 return Err(QueueError::QueueFull);
90 }
91
92 OverflowPolicy::Panic => {
93 panic!("SpscQueue overflow (capacity: {})", CAP);
94 }
95
96 OverflowPolicy::Block => {
97 return Err(QueueError::QueueFull);
98 }
99 }
100 }
101
102 self.buffer[head].store(value);
103
104 self.head.store(next_head, Ordering::Release);
105
106 if next_head == self.tail.load(Ordering::Acquire) {
107 self.full.store(true, Ordering::Release);
108 }
109
110 Ok(())
111 }
112
113 pub fn pop(&self) -> Option<T> {
115 if self.is_empty() {
116 return self.default_value;
117 }
118
119 let tail = self.tail.load(Ordering::Relaxed) & self.mask;
120 let value = self.buffer[tail].load();
121
122 let next_tail = (tail + 1) & self.mask;
123 self.tail.store(next_tail, Ordering::Release);
124
125 self.full.store(false, Ordering::Release);
126
127 Some(value)
128 }
129
130 pub fn peek(&self) -> Option<T> {
132 if self.is_empty() {
133 None
134 } else {
135 let tail = self.tail.load(Ordering::Acquire);
136 Some(self.buffer[tail].load())
137 }
138 }
139
140 pub fn len(&self) -> usize {
142 if self.full.load(Ordering::Acquire) {
143 CAP
144 } else {
145 let head = self.head.load(Ordering::Acquire);
146 let tail = self.tail.load(Ordering::Acquire);
147
148 if head >= tail {
149 head - tail
150 } else {
151 CAP - tail + head
152 }
153 }
154 }
155
156 pub const fn capacity(&self) -> usize {
158 CAP
159 }
160
161 pub fn is_empty(&self) -> bool {
163 !self.full.load(Ordering::Acquire)
164 && self.head.load(Ordering::Acquire) == self.tail.load(Ordering::Acquire)
165 }
166
167 pub fn is_full(&self) -> bool {
169 self.full.load(Ordering::Acquire)
170 }
171
172 pub fn clear(&self) {
174 self.head.store(0, Ordering::Relaxed);
175 self.tail.store(0, Ordering::Relaxed);
176 self.full.store(false, Ordering::Relaxed);
177 }
178
179 pub fn stats(&self) -> QueueStatsSnapshot {
181 QueueStatsSnapshot::default()
182 }
183
184 pub fn set_default(&mut self, value: T) {
186 self.default_value = Some(value);
187 }
188
189 pub fn overflow_policy(&self) -> OverflowPolicy {
191 self.overflow_policy
192 }
193
194 pub fn set_overflow_policy(&mut self, policy: OverflowPolicy) {
196 self.overflow_policy = policy;
197 }
198}
199
200impl<T: Copy + Default + Send + Sync, const CAP: usize> RtQueueBase<T> for SpscQueue<T, CAP> {
201 fn push(&self, value: T) -> QueueResult<()> {
202 self.push(value)
203 }
204
205 fn pop(&self) -> Option<T> {
206 self.pop()
207 }
208
209 fn len(&self) -> usize {
210 self.len()
211 }
212
213 fn capacity(&self) -> usize {
214 CAP
215 }
216
217 fn clear(&self) {
218 self.clear();
219 }
220}
221
222impl<T: Copy + Default + fmt::Debug, const CAP: usize> fmt::Debug for SpscQueue<T, CAP> {
223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224 f.debug_struct("SpscQueue")
225 .field("head", &self.head.load(Ordering::Relaxed))
226 .field("tail", &self.tail.load(Ordering::Relaxed))
227 .field("capacity", &CAP)
228 .field("len", &self.len())
229 .field("overflow_policy", &self.overflow_policy)
230 .field("default_value", &self.default_value)
231 .finish()
232 }
233}
234
235impl<T: Copy + Default, const CAP: usize> Default for SpscQueue<T, CAP> {
236 fn default() -> Self {
237 Self::new()
238 }
239}
240#[allow(unsafe_code)]
241unsafe impl<T: Copy + Send, const CAP: usize> Send for SpscQueue<T, CAP> {}
242#[allow(unsafe_code)]
243unsafe impl<T: Copy + Sync, const CAP: usize> Sync for SpscQueue<T, CAP> {}
244
245#[cfg(test)]
250mod tests {
251 use super::*;
252
253 #[test]
254 fn test_spsc_basic() {
255 let queue = SpscQueue::<i32, 4>::new();
256
257 assert!(queue.is_empty());
258 assert_eq!(queue.capacity(), 4);
259 assert_eq!(queue.len(), 0);
260
261 queue.push(1).unwrap();
262 assert_eq!(queue.len(), 1);
263 assert!(!queue.is_empty());
264 assert!(!queue.is_full()); queue.push(2).unwrap();
267 queue.push(3).unwrap();
268 queue.push(4).unwrap();
269
270 assert!(queue.is_full()); assert_eq!(queue.len(), 4);
272
273 assert_eq!(queue.pop(), Some(1));
274 assert_eq!(queue.pop(), Some(2));
275 assert_eq!(queue.pop(), Some(3));
276 assert_eq!(queue.pop(), Some(4));
277 assert_eq!(queue.pop(), None);
278 assert!(queue.is_empty());
279 }
280
281 #[test]
282 fn test_spsc_overwrite_policy() {
283 let queue = SpscQueue::<i32, 2>::new(); queue.push(1).unwrap();
286 queue.push(2).unwrap();
287 assert!(queue.is_full());
288
289 queue.push(3).unwrap();
291 assert_eq!(queue.len(), 2);
292
293 assert_eq!(queue.pop(), Some(2));
295 assert_eq!(queue.pop(), Some(3));
296 assert_eq!(queue.pop(), None);
297 }
298
299 #[test]
300 fn test_spsc_drop_newest_policy() {
301 let queue = SpscQueue::<i32, 2>::with_policies(OverflowPolicy::DropNewest, None);
302
303 queue.push(1).unwrap();
304 queue.push(2).unwrap();
305 assert!(queue.is_full());
306
307 assert!(queue.push(3).is_err());
309
310 assert_eq!(queue.pop(), Some(1));
312 assert_eq!(queue.pop(), Some(2));
313 assert_eq!(queue.pop(), None);
314 }
315
316 #[test]
317 fn test_spsc_wraparound() {
318 let queue = SpscQueue::<i32, 4>::new();
319
320 queue.push(0).unwrap();
322 queue.push(1).unwrap();
323 queue.push(2).unwrap();
324 queue.push(3).unwrap();
325 assert!(queue.is_full());
326
327 assert_eq!(queue.pop(), Some(0));
329 assert_eq!(queue.pop(), Some(1));
330
331 queue.push(4).unwrap();
333 queue.push(5).unwrap();
334 assert!(queue.is_full());
335
336 assert_eq!(queue.pop(), Some(2));
338 assert_eq!(queue.pop(), Some(3));
339 assert_eq!(queue.pop(), Some(4));
340 assert_eq!(queue.pop(), Some(5));
341 assert_eq!(queue.pop(), None);
342 }
343
344 #[test]
345 fn test_spsc_peek() {
346 let queue = SpscQueue::<i32, 4>::new();
347
348 assert_eq!(queue.peek(), None);
349
350 queue.push(42).unwrap();
351 assert_eq!(queue.peek(), Some(42));
352 assert_eq!(queue.len(), 1);
353 assert_eq!(queue.pop(), Some(42));
354 assert_eq!(queue.peek(), None);
355 }
356
357 #[test]
358 fn test_spsc_clear() {
359 let queue = SpscQueue::<i32, 4>::new();
360
361 queue.push(1).unwrap();
362 queue.push(2).unwrap();
363 queue.push(3).unwrap();
364
365 assert_eq!(queue.len(), 3);
366
367 queue.clear();
368 assert_eq!(queue.len(), 0);
369 assert!(queue.is_empty());
370 }
371
372 #[test]
373 fn test_spsc_default_value() {
374 let queue = SpscQueue::<i32, 4>::with_policies(OverflowPolicy::OverwriteOldest, Some(-1));
375
376 assert_eq!(queue.pop(), Some(-1));
377
378 queue.push(42).unwrap();
379 assert_eq!(queue.pop(), Some(42));
380 assert_eq!(queue.pop(), Some(-1));
381 }
382
383 #[test]
384 fn test_spsc_policy_change() {
385 let mut queue = SpscQueue::<i32, 2>::new();
386 assert_eq!(queue.overflow_policy(), OverflowPolicy::OverwriteOldest);
387
388 queue.set_overflow_policy(OverflowPolicy::DropNewest);
389 assert_eq!(queue.overflow_policy(), OverflowPolicy::DropNewest);
390 }
391
392 #[test]
393 #[should_panic(expected = "CAP must be a power of two")]
394 fn test_spsc_invalid_capacity() {
395 let _ = SpscQueue::<i32, 3>::new();
396 }
397}