1use core::mem::MaybeUninit;
12use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
13
14use crossbeam_utils::CachePadded;
15
16use crate::{unprotected, Atomic, Guard, Owned, Shared};
17
18#[derive(Debug)]
22pub(crate) struct Queue<T> {
23 head: CachePadded<Atomic<Node<T>>>,
24 tail: CachePadded<Atomic<Node<T>>>,
25}
26
27struct Node<T> {
28 data: MaybeUninit<T>,
35
36 next: Atomic<Node<T>>,
37}
38
39unsafe impl<T: Send> Sync for Queue<T> {}
41unsafe impl<T: Send> Send for Queue<T> {}
42
43impl<T> Queue<T> {
44 pub(crate) fn new() -> Queue<T> {
46 let q = Queue {
47 head: CachePadded::new(Atomic::null()),
48 tail: CachePadded::new(Atomic::null()),
49 };
50 let sentinel = Owned::new(Node {
51 data: MaybeUninit::uninit(),
52 next: Atomic::null(),
53 });
54 unsafe {
55 let guard = unprotected();
56 let sentinel = sentinel.into_shared(guard);
57 q.head.store(sentinel, Relaxed);
58 q.tail.store(sentinel, Relaxed);
59 q
60 }
61 }
62
63 #[inline(always)]
66 fn push_internal(
67 &self,
68 onto: Shared<'_, Node<T>>,
69 new: Shared<'_, Node<T>>,
70 guard: &Guard,
71 ) -> bool {
72 let o = unsafe { onto.deref() };
74 let next = o.next.load(Acquire, guard);
75 if unsafe { next.as_ref().is_some() } {
76 let _ = self
78 .tail
79 .compare_exchange(onto, next, Release, Relaxed, guard);
80 false
81 } else {
82 let result = o
84 .next
85 .compare_exchange(Shared::null(), new, Release, Relaxed, guard)
86 .is_ok();
87 if result {
88 let _ = self
90 .tail
91 .compare_exchange(onto, new, Release, Relaxed, guard);
92 }
93 result
94 }
95 }
96
97 pub(crate) fn push(&self, t: T, guard: &Guard) {
99 let new = Owned::new(Node {
100 data: MaybeUninit::new(t),
101 next: Atomic::null(),
102 });
103 let new = Owned::into_shared(new, guard);
104
105 loop {
106 let tail = self.tail.load(Acquire, guard);
108
109 if self.push_internal(tail, new, guard) {
111 break;
112 }
113 }
114 }
115
116 #[inline(always)]
118 fn pop_internal(&self, guard: &Guard) -> Result<Option<T>, ()> {
119 let head = self.head.load(Acquire, guard);
120 let h = unsafe { head.deref() };
121 let next = h.next.load(Acquire, guard);
122 match unsafe { next.as_ref() } {
123 Some(n) => unsafe {
124 self.head
125 .compare_exchange(head, next, Release, Relaxed, guard)
126 .map(|_| {
127 let tail = self.tail.load(Relaxed, guard);
128 if head == tail {
130 let _ = self
131 .tail
132 .compare_exchange(tail, next, Release, Relaxed, guard);
133 }
134 guard.defer_destroy(head);
135 Some(n.data.assume_init_read())
136 })
137 .map_err(|_| ())
138 },
139 None => Ok(None),
140 }
141 }
142
143 #[inline(always)]
146 fn pop_if_internal<F>(&self, condition: F, guard: &Guard) -> Result<Option<T>, ()>
147 where
148 T: Sync,
149 F: Fn(&T) -> bool,
150 {
151 let head = self.head.load(Acquire, guard);
152 let h = unsafe { head.deref() };
153 let next = h.next.load(Acquire, guard);
154 match unsafe { next.as_ref() } {
155 Some(n) if condition(unsafe { &*n.data.as_ptr() }) => unsafe {
156 self.head
157 .compare_exchange(head, next, Release, Relaxed, guard)
158 .map(|_| {
159 let tail = self.tail.load(Relaxed, guard);
160 if head == tail {
162 let _ = self
163 .tail
164 .compare_exchange(tail, next, Release, Relaxed, guard);
165 }
166 guard.defer_destroy(head);
167 Some(n.data.assume_init_read())
168 })
169 .map_err(|_| ())
170 },
171 None | Some(_) => Ok(None),
172 }
173 }
174
175 pub(crate) fn try_pop(&self, guard: &Guard) -> Option<T> {
179 loop {
180 if let Ok(head) = self.pop_internal(guard) {
181 return head;
182 }
183 }
184 }
185
186 pub(crate) fn try_pop_if<F>(&self, condition: F, guard: &Guard) -> Option<T>
191 where
192 T: Sync,
193 F: Fn(&T) -> bool,
194 {
195 loop {
196 if let Ok(head) = self.pop_if_internal(&condition, guard) {
197 return head;
198 }
199 }
200 }
201}
202
203impl<T> Drop for Queue<T> {
204 fn drop(&mut self) {
205 unsafe {
206 let guard = unprotected();
207
208 while self.try_pop(guard).is_some() {}
209
210 let sentinel = self.head.load(Relaxed, guard);
212 drop(sentinel.into_owned());
213 }
214 }
215}
216
217#[cfg(all(test, not(crossbeam_loom)))]
218mod test {
219 use super::*;
220 use crate::pin;
221 use crossbeam_utils::thread;
222 use std::vec;
223
224 struct Queue<T> {
225 queue: super::Queue<T>,
226 }
227
228 impl<T> Queue<T> {
229 pub(crate) fn new() -> Queue<T> {
230 Queue {
231 queue: super::Queue::new(),
232 }
233 }
234
235 pub(crate) fn push(&self, t: T) {
236 let guard = &pin();
237 self.queue.push(t, guard);
238 }
239
240 pub(crate) fn is_empty(&self) -> bool {
241 let guard = &pin();
242 let head = self.queue.head.load(Acquire, guard);
243 let h = unsafe { head.deref() };
244 h.next.load(Acquire, guard).is_null()
245 }
246
247 pub(crate) fn try_pop(&self) -> Option<T> {
248 let guard = &pin();
249 self.queue.try_pop(guard)
250 }
251
252 pub(crate) fn pop(&self) -> T {
253 loop {
254 match self.try_pop() {
255 None => continue,
256 Some(t) => return t,
257 }
258 }
259 }
260 }
261
262 #[cfg(miri)]
263 const CONC_COUNT: i64 = 1000;
264 #[cfg(not(miri))]
265 const CONC_COUNT: i64 = 1000000;
266
267 #[test]
268 fn push_try_pop_1() {
269 let q: Queue<i64> = Queue::new();
270 assert!(q.is_empty());
271 q.push(37);
272 assert!(!q.is_empty());
273 assert_eq!(q.try_pop(), Some(37));
274 assert!(q.is_empty());
275 }
276
277 #[test]
278 fn push_try_pop_2() {
279 let q: Queue<i64> = Queue::new();
280 assert!(q.is_empty());
281 q.push(37);
282 q.push(48);
283 assert_eq!(q.try_pop(), Some(37));
284 assert!(!q.is_empty());
285 assert_eq!(q.try_pop(), Some(48));
286 assert!(q.is_empty());
287 }
288
289 #[test]
290 fn push_try_pop_many_seq() {
291 let q: Queue<i64> = Queue::new();
292 assert!(q.is_empty());
293 for i in 0..200 {
294 q.push(i)
295 }
296 assert!(!q.is_empty());
297 for i in 0..200 {
298 assert_eq!(q.try_pop(), Some(i));
299 }
300 assert!(q.is_empty());
301 }
302
303 #[test]
304 fn push_pop_1() {
305 let q: Queue<i64> = Queue::new();
306 assert!(q.is_empty());
307 q.push(37);
308 assert!(!q.is_empty());
309 assert_eq!(q.pop(), 37);
310 assert!(q.is_empty());
311 }
312
313 #[test]
314 fn push_pop_2() {
315 let q: Queue<i64> = Queue::new();
316 q.push(37);
317 q.push(48);
318 assert_eq!(q.pop(), 37);
319 assert_eq!(q.pop(), 48);
320 }
321
322 #[test]
323 fn push_pop_many_seq() {
324 let q: Queue<i64> = Queue::new();
325 assert!(q.is_empty());
326 for i in 0..200 {
327 q.push(i)
328 }
329 assert!(!q.is_empty());
330 for i in 0..200 {
331 assert_eq!(q.pop(), i);
332 }
333 assert!(q.is_empty());
334 }
335
336 #[test]
337 fn push_try_pop_many_spsc() {
338 let q: Queue<i64> = Queue::new();
339 assert!(q.is_empty());
340
341 thread::scope(|scope| {
342 scope.spawn(|_| {
343 let mut next = 0;
344
345 while next < CONC_COUNT {
346 if let Some(elem) = q.try_pop() {
347 assert_eq!(elem, next);
348 next += 1;
349 }
350 }
351 });
352
353 for i in 0..CONC_COUNT {
354 q.push(i)
355 }
356 })
357 .unwrap();
358 }
359
360 #[test]
361 fn push_try_pop_many_spmc() {
362 fn recv(_t: i32, q: &Queue<i64>) {
363 let mut cur = -1;
364 for _i in 0..CONC_COUNT {
365 if let Some(elem) = q.try_pop() {
366 assert!(elem > cur);
367 cur = elem;
368
369 if cur == CONC_COUNT - 1 {
370 break;
371 }
372 }
373 }
374 }
375
376 let q: Queue<i64> = Queue::new();
377 assert!(q.is_empty());
378 thread::scope(|scope| {
379 for i in 0..3 {
380 let q = &q;
381 scope.spawn(move |_| recv(i, q));
382 }
383
384 scope.spawn(|_| {
385 for i in 0..CONC_COUNT {
386 q.push(i);
387 }
388 });
389 })
390 .unwrap();
391 }
392
393 #[test]
394 fn push_try_pop_many_mpmc() {
395 enum LR {
396 Left(i64),
397 Right(i64),
398 }
399
400 let q: Queue<LR> = Queue::new();
401 assert!(q.is_empty());
402
403 thread::scope(|scope| {
404 for _t in 0..2 {
405 scope.spawn(|_| {
406 for i in CONC_COUNT - 1..CONC_COUNT {
407 q.push(LR::Left(i))
408 }
409 });
410 scope.spawn(|_| {
411 for i in CONC_COUNT - 1..CONC_COUNT {
412 q.push(LR::Right(i))
413 }
414 });
415 scope.spawn(|_| {
416 let mut vl = vec![];
417 let mut vr = vec![];
418 for _i in 0..CONC_COUNT {
419 match q.try_pop() {
420 Some(LR::Left(x)) => vl.push(x),
421 Some(LR::Right(x)) => vr.push(x),
422 _ => {}
423 }
424 }
425
426 let mut vl2 = vl.clone();
427 let mut vr2 = vr.clone();
428 vl2.sort_unstable();
429 vr2.sort_unstable();
430
431 assert_eq!(vl, vl2);
432 assert_eq!(vr, vr2);
433 });
434 }
435 })
436 .unwrap();
437 }
438
439 #[test]
440 fn push_pop_many_spsc() {
441 let q: Queue<i64> = Queue::new();
442
443 thread::scope(|scope| {
444 scope.spawn(|_| {
445 let mut next = 0;
446 while next < CONC_COUNT {
447 assert_eq!(q.pop(), next);
448 next += 1;
449 }
450 });
451
452 for i in 0..CONC_COUNT {
453 q.push(i)
454 }
455 })
456 .unwrap();
457 assert!(q.is_empty());
458 }
459
460 #[test]
461 fn is_empty_dont_pop() {
462 let q: Queue<i64> = Queue::new();
463 q.push(20);
464 q.push(20);
465 assert!(!q.is_empty());
466 assert!(!q.is_empty());
467 assert!(q.try_pop().is_some());
468 }
469}