Skip to main content

crossbeam_deque/
deque.rs

1use std::alloc::{alloc_zeroed, handle_alloc_error, Layout};
2use std::boxed::Box;
3use std::cell::{Cell, UnsafeCell};
4use std::cmp;
5use std::fmt;
6use std::marker::PhantomData;
7use std::mem::{self, MaybeUninit};
8use std::ptr;
9use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
10use std::sync::Arc;
11
12use crossbeam_epoch::{self as epoch, Atomic, Owned};
13use crossbeam_utils::{Backoff, CachePadded};
14
15// Ideally, we want to always use AtomicU64/AtomicI64, but since they are not available on all platforms,
16// we only use them when they are available for now.
17// TODO: On platforms where AtomicU64/AtomicI64 is unavailable, we may want to use AtomicCell instead of
18// AtomicUsize/AtomicIsize. (https://github.com/crossbeam-rs/crossbeam/issues/433)
19#[cfg(target_has_atomic = "64")]
20type AtomicIndex = core::sync::atomic::AtomicU64;
21#[cfg(target_has_atomic = "64")]
22type AtomicWorkerIndex = core::sync::atomic::AtomicI64;
23#[cfg(target_has_atomic = "64")]
24type Index = u64;
25#[cfg(target_has_atomic = "64")]
26type WorkerIndex = i64;
27#[cfg(not(target_has_atomic = "64"))]
28type AtomicIndex = core::sync::atomic::AtomicUsize;
29#[cfg(not(target_has_atomic = "64"))]
30type AtomicWorkerIndex = core::sync::atomic::AtomicIsize;
31#[cfg(not(target_has_atomic = "64"))]
32type Index = usize;
33#[cfg(not(target_has_atomic = "64"))]
34type WorkerIndex = isize;
35
36// Minimum buffer capacity.
37const MIN_CAP: usize = 64;
38// Maximum number of tasks that can be stolen in `steal_batch()` and `steal_batch_and_pop()`.
39const MAX_BATCH: usize = 32;
40// If a buffer of at least this size is retired, thread-local garbage is flushed so that it gets
41// deallocated as soon as possible.
42const FLUSH_THRESHOLD_BYTES: usize = 1 << 10;
43
44/// A buffer that holds tasks in a worker queue.
45///
46/// This is just a pointer to the buffer and its length - dropping an instance of this struct will
47/// *not* deallocate the buffer.
48struct Buffer<T> {
49    /// Pointer to the allocated memory.
50    ptr: *mut T,
51
52    /// Capacity of the buffer. Always a power of two.
53    cap: usize,
54}
55
56unsafe impl<T> Send for Buffer<T> {}
57
58impl<T> Buffer<T> {
59    /// Allocates a new buffer with the specified capacity.
60    fn alloc(cap: usize) -> Buffer<T> {
61        debug_assert_eq!(cap, cap.next_power_of_two());
62
63        let ptr = Box::into_raw(
64            (0..cap)
65                .map(|_| MaybeUninit::<T>::uninit())
66                .collect::<Box<[_]>>(),
67        )
68        .cast::<T>();
69
70        Buffer { ptr, cap }
71    }
72
73    /// Deallocates the buffer.
74    unsafe fn dealloc(self) {
75        drop(Box::from_raw(ptr::slice_from_raw_parts_mut(
76            self.ptr.cast::<MaybeUninit<T>>(),
77            self.cap,
78        )));
79    }
80
81    /// Returns a pointer to the task at the specified `index`.
82    unsafe fn at(&self, index: WorkerIndex) -> *mut T {
83        // `self.cap` is always a power of two.
84        // We do all the loads at `MaybeUninit` because we might realize, after loading, that we
85        // don't actually have the right to access this memory.
86        self.ptr
87            .offset((index & (self.cap - 1) as WorkerIndex) as isize)
88    }
89
90    /// Writes `task` into the specified `index`.
91    ///
92    /// This method might be concurrently called with another `read` at the same index, which is
93    /// technically speaking a data race and therefore UB. We should use an atomic store here, but
94    /// that would be more expensive and difficult to implement generically for all types `T`.
95    /// Hence, as a hack, we use a volatile write instead.
96    unsafe fn write(&self, index: WorkerIndex, task: MaybeUninit<T>) {
97        ptr::write_volatile(self.at(index).cast::<MaybeUninit<T>>(), task)
98    }
99
100    /// Reads a task from the specified `index`.
101    ///
102    /// This method might be concurrently called with another `write` at the same index, which is
103    /// technically speaking a data race and therefore UB. We should use an atomic load here, but
104    /// that would be more expensive and difficult to implement generically for all types `T`.
105    /// Hence, as a hack, we use a volatile load instead.
106    unsafe fn read(&self, index: WorkerIndex) -> MaybeUninit<T> {
107        ptr::read_volatile(self.at(index).cast::<MaybeUninit<T>>())
108    }
109}
110
111impl<T> Clone for Buffer<T> {
112    fn clone(&self) -> Buffer<T> {
113        *self
114    }
115}
116
117impl<T> Copy for Buffer<T> {}
118
119/// Internal queue data shared between the worker and stealers.
120///
121/// The implementation is based on the following work:
122///
123/// 1. [Chase and Lev. Dynamic circular work-stealing deque. SPAA 2005.][chase-lev]
124/// 2. [Le, Pop, Cohen, and Nardelli. Correct and efficient work-stealing for weak memory models.
125///    PPoPP 2013.][weak-mem]
126/// 3. [Norris and Demsky. CDSchecker: checking concurrent data structures written with C/C++
127///    atomics. OOPSLA 2013.][checker]
128///
129/// [chase-lev]: https://dl.acm.org/citation.cfm?id=1073974
130/// [weak-mem]: https://dl.acm.org/citation.cfm?id=2442524
131/// [checker]: https://dl.acm.org/citation.cfm?id=2509514
132struct Inner<T> {
133    /// The front index.
134    front: AtomicWorkerIndex,
135
136    /// The back index.
137    back: AtomicWorkerIndex,
138
139    /// The underlying buffer.
140    buffer: CachePadded<Atomic<Buffer<T>>>,
141}
142
143impl<T> Drop for Inner<T> {
144    fn drop(&mut self) {
145        // Load the back index, front index, and buffer.
146        let b = *self.back.get_mut();
147        let f = *self.front.get_mut();
148
149        unsafe {
150            let buffer = self.buffer.load(Ordering::Relaxed, epoch::unprotected());
151
152            // Go through the buffer from front to back and drop all tasks in the queue.
153            let mut i = f;
154            while i != b {
155                buffer.deref().at(i).drop_in_place();
156                i = i.wrapping_add(1);
157            }
158
159            // Free the memory allocated by the buffer.
160            buffer.into_owned().into_box().dealloc();
161        }
162    }
163}
164
165/// Worker queue flavor: FIFO or LIFO.
166#[derive(Clone, Copy, Debug, Eq, PartialEq)]
167enum Flavor {
168    /// The first-in first-out flavor.
169    Fifo,
170
171    /// The last-in first-out flavor.
172    Lifo,
173}
174
175/// A worker queue.
176///
177/// This is a FIFO or LIFO queue that is owned by a single thread, but other threads may steal
178/// tasks from it. Task schedulers typically create a single worker queue per thread.
179///
180/// # Examples
181///
182/// A FIFO worker:
183///
184/// ```
185/// use crossbeam_deque::{Steal, Worker};
186///
187/// let w = Worker::new_fifo();
188/// let s = w.stealer();
189///
190/// w.push(1);
191/// w.push(2);
192/// w.push(3);
193///
194/// assert_eq!(s.steal(), Steal::Success(1));
195/// assert_eq!(w.pop(), Some(2));
196/// assert_eq!(w.pop(), Some(3));
197/// ```
198///
199/// A LIFO worker:
200///
201/// ```
202/// use crossbeam_deque::{Steal, Worker};
203///
204/// let w = Worker::new_lifo();
205/// let s = w.stealer();
206///
207/// w.push(1);
208/// w.push(2);
209/// w.push(3);
210///
211/// assert_eq!(s.steal(), Steal::Success(1));
212/// assert_eq!(w.pop(), Some(3));
213/// assert_eq!(w.pop(), Some(2));
214/// ```
215pub struct Worker<T> {
216    /// A reference to the inner representation of the queue.
217    inner: Arc<CachePadded<Inner<T>>>,
218
219    /// A copy of `inner.buffer` for quick access.
220    buffer: Cell<Buffer<T>>,
221
222    /// The flavor of the queue.
223    flavor: Flavor,
224
225    /// Indicates that the worker cannot be shared among threads.
226    _marker: PhantomData<*mut ()>, // !Send + !Sync
227}
228
229unsafe impl<T: Send> Send for Worker<T> {}
230
231impl<T> Worker<T> {
232    /// Creates a FIFO worker queue.
233    ///
234    /// Tasks are pushed and popped from opposite ends.
235    ///
236    /// # Examples
237    ///
238    /// ```
239    /// use crossbeam_deque::Worker;
240    ///
241    /// let w = Worker::<i32>::new_fifo();
242    /// ```
243    pub fn new_fifo() -> Worker<T> {
244        let buffer = Buffer::alloc(MIN_CAP);
245
246        let inner = Arc::new(CachePadded::new(Inner {
247            front: AtomicWorkerIndex::new(0),
248            back: AtomicWorkerIndex::new(0),
249            buffer: CachePadded::new(Atomic::new(buffer)),
250        }));
251
252        Worker {
253            inner,
254            buffer: Cell::new(buffer),
255            flavor: Flavor::Fifo,
256            _marker: PhantomData,
257        }
258    }
259
260    /// Creates a LIFO worker queue.
261    ///
262    /// Tasks are pushed and popped from the same end.
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use crossbeam_deque::Worker;
268    ///
269    /// let w = Worker::<i32>::new_lifo();
270    /// ```
271    pub fn new_lifo() -> Worker<T> {
272        let buffer = Buffer::alloc(MIN_CAP);
273
274        let inner = Arc::new(CachePadded::new(Inner {
275            front: AtomicWorkerIndex::new(0),
276            back: AtomicWorkerIndex::new(0),
277            buffer: CachePadded::new(Atomic::new(buffer)),
278        }));
279
280        Worker {
281            inner,
282            buffer: Cell::new(buffer),
283            flavor: Flavor::Lifo,
284            _marker: PhantomData,
285        }
286    }
287
288    /// Creates a stealer for this queue.
289    ///
290    /// The returned stealer can be shared among threads and cloned.
291    ///
292    /// # Examples
293    ///
294    /// ```
295    /// use crossbeam_deque::Worker;
296    ///
297    /// let w = Worker::<i32>::new_lifo();
298    /// let s = w.stealer();
299    /// ```
300    pub fn stealer(&self) -> Stealer<T> {
301        Stealer {
302            inner: self.inner.clone(),
303            flavor: self.flavor,
304        }
305    }
306
307    /// Resizes the internal buffer to the new capacity of `new_cap`.
308    #[cold]
309    unsafe fn resize(&self, new_cap: usize) {
310        // Load the back index, front index, and buffer.
311        let b = self.inner.back.load(Ordering::Relaxed);
312        let f = self.inner.front.load(Ordering::Relaxed);
313        let buffer = self.buffer.get();
314
315        // Allocate a new buffer and copy data from the old buffer to the new one.
316        let new = Buffer::alloc(new_cap);
317        let mut i = f;
318        while i != b {
319            ptr::copy_nonoverlapping(buffer.at(i), new.at(i), 1);
320            i = i.wrapping_add(1);
321        }
322
323        let guard = &epoch::pin();
324
325        // Replace the old buffer with the new one.
326        self.buffer.replace(new);
327        let old =
328            self.inner
329                .buffer
330                .swap(Owned::new(new).into_shared(guard), Ordering::Release, guard);
331
332        // Destroy the old buffer later.
333        guard.defer_unchecked(move || old.into_owned().into_box().dealloc());
334
335        // If the buffer is very large, then flush the thread-local garbage in order to deallocate
336        // it as soon as possible.
337        if mem::size_of::<T>() * new_cap >= FLUSH_THRESHOLD_BYTES {
338            guard.flush();
339        }
340    }
341
342    /// Reserves enough capacity so that `reserve_cap` tasks can be pushed without growing the
343    /// buffer.
344    fn reserve(&self, reserve_cap: usize) {
345        if reserve_cap > 0 {
346            // Compute the current length.
347            let b = self.inner.back.load(Ordering::Relaxed);
348            let f = self.inner.front.load(Ordering::SeqCst);
349            let len = b.wrapping_sub(f) as usize;
350
351            // The current capacity.
352            let cap = self.buffer.get().cap;
353
354            // Is there enough capacity to push `reserve_cap` tasks?
355            if cap - len < reserve_cap {
356                // Ensure capacity for reserve_cap + len, rounded up to the next power of 2
357                let new_cap = (reserve_cap + len).next_power_of_two();
358
359                // Resize the buffer.
360                unsafe {
361                    self.resize(new_cap);
362                }
363            }
364        }
365    }
366
367    /// Returns `true` if the queue is empty.
368    ///
369    /// ```
370    /// use crossbeam_deque::Worker;
371    ///
372    /// let w = Worker::new_lifo();
373    ///
374    /// assert!(w.is_empty());
375    /// w.push(1);
376    /// assert!(!w.is_empty());
377    /// ```
378    pub fn is_empty(&self) -> bool {
379        let b = self.inner.back.load(Ordering::Relaxed);
380        let f = self.inner.front.load(Ordering::SeqCst);
381        b.wrapping_sub(f) <= 0
382    }
383
384    /// Returns the number of tasks in the deque.
385    ///
386    /// ```
387    /// use crossbeam_deque::Worker;
388    ///
389    /// let w = Worker::new_lifo();
390    ///
391    /// assert_eq!(w.len(), 0);
392    /// w.push(1);
393    /// assert_eq!(w.len(), 1);
394    /// w.push(1);
395    /// assert_eq!(w.len(), 2);
396    /// ```
397    pub fn len(&self) -> usize {
398        let b = self.inner.back.load(Ordering::Relaxed);
399        let f = self.inner.front.load(Ordering::SeqCst);
400        b.wrapping_sub(f).max(0) as usize
401    }
402
403    /// Pushes a task into the queue.
404    ///
405    /// # Examples
406    ///
407    /// ```
408    /// use crossbeam_deque::Worker;
409    ///
410    /// let w = Worker::new_lifo();
411    /// w.push(1);
412    /// w.push(2);
413    /// ```
414    pub fn push(&self, task: T) {
415        // Load the back index, front index, and buffer.
416        let b = self.inner.back.load(Ordering::Relaxed);
417        let f = self.inner.front.load(Ordering::Acquire);
418        let mut buffer = self.buffer.get();
419
420        // Calculate the length of the queue.
421        let len = b.wrapping_sub(f);
422
423        // Is the queue full?
424        if len >= buffer.cap as WorkerIndex {
425            // Yes. Grow the underlying buffer.
426            unsafe {
427                self.resize(2 * buffer.cap);
428            }
429            buffer = self.buffer.get();
430        }
431
432        // Write `task` into the slot.
433        unsafe {
434            buffer.write(b, MaybeUninit::new(task));
435        }
436
437        // ThreadSanitizer does not understand fences, so we omit fence and do store with Release ordering.
438        #[cfg(not(crossbeam_sanitize_thread))]
439        atomic::fence(Ordering::Release);
440        let store_order = if cfg!(crossbeam_sanitize_thread) {
441            Ordering::Release
442        } else {
443            Ordering::Relaxed
444        };
445
446        // Increment the back index.
447        self.inner.back.store(b.wrapping_add(1), store_order);
448    }
449
450    /// Pops a task from the queue.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// use crossbeam_deque::Worker;
456    ///
457    /// let w = Worker::new_fifo();
458    /// w.push(1);
459    /// w.push(2);
460    ///
461    /// assert_eq!(w.pop(), Some(1));
462    /// assert_eq!(w.pop(), Some(2));
463    /// assert_eq!(w.pop(), None);
464    /// ```
465    pub fn pop(&self) -> Option<T> {
466        // Load the back and front index.
467        let b = self.inner.back.load(Ordering::Relaxed);
468        let f = self.inner.front.load(Ordering::Relaxed);
469
470        // Calculate the length of the queue.
471        let len = b.wrapping_sub(f);
472
473        // Is the queue empty?
474        if len <= 0 {
475            return None;
476        }
477
478        match self.flavor {
479            // Pop from the front of the queue.
480            Flavor::Fifo => {
481                // Try incrementing the front index to pop the task.
482                let f = self.inner.front.fetch_add(1, Ordering::SeqCst);
483                let new_f = f.wrapping_add(1);
484
485                if b.wrapping_sub(new_f) < 0 {
486                    self.inner.front.store(f, Ordering::Relaxed);
487                    return None;
488                }
489
490                unsafe {
491                    // Read the popped task.
492                    let buffer = self.buffer.get();
493                    let task = buffer.read(f).assume_init();
494
495                    // Shrink the buffer if `len - 1` is less than one fourth of the capacity.
496                    if buffer.cap > MIN_CAP && len <= buffer.cap as WorkerIndex / 4 {
497                        self.resize(buffer.cap / 2);
498                    }
499
500                    Some(task)
501                }
502            }
503
504            // Pop from the back of the queue.
505            Flavor::Lifo => {
506                // Decrement the back index.
507                let b = b.wrapping_sub(1);
508                self.inner.back.store(b, Ordering::Relaxed);
509
510                atomic::fence(Ordering::SeqCst);
511
512                // Load the front index.
513                let f = self.inner.front.load(Ordering::Relaxed);
514
515                // Compute the length after the back index was decremented.
516                let len = b.wrapping_sub(f);
517
518                if len < 0 {
519                    // The queue is empty. Restore the back index to the original task.
520                    self.inner.back.store(b.wrapping_add(1), Ordering::Relaxed);
521                    None
522                } else {
523                    // Read the task to be popped.
524                    let buffer = self.buffer.get();
525                    let mut task = unsafe { Some(buffer.read(b)) };
526
527                    // Are we popping the last task from the queue?
528                    if len == 0 {
529                        // Try incrementing the front index.
530                        if self
531                            .inner
532                            .front
533                            .compare_exchange(
534                                f,
535                                f.wrapping_add(1),
536                                Ordering::SeqCst,
537                                Ordering::Relaxed,
538                            )
539                            .is_err()
540                        {
541                            // Failed. We didn't pop anything. Reset to `None`.
542                            task.take();
543                        }
544
545                        // Restore the back index to the original task.
546                        self.inner.back.store(b.wrapping_add(1), Ordering::Relaxed);
547                    } else {
548                        // Shrink the buffer if `len` is less than one fourth of the capacity.
549                        if buffer.cap > MIN_CAP && len < buffer.cap as WorkerIndex / 4 {
550                            unsafe {
551                                self.resize(buffer.cap / 2);
552                            }
553                        }
554                    }
555
556                    task.map(|t| unsafe { t.assume_init() })
557                }
558            }
559        }
560    }
561}
562
563impl<T> fmt::Debug for Worker<T> {
564    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565        f.pad("Worker { .. }")
566    }
567}
568
569/// A stealer handle of a worker queue.
570///
571/// Stealers can be shared among threads.
572///
573/// Task schedulers typically have a single worker queue per worker thread.
574///
575/// # Examples
576///
577/// ```
578/// use crossbeam_deque::{Steal, Worker};
579///
580/// let w = Worker::new_lifo();
581/// w.push(1);
582/// w.push(2);
583///
584/// let s = w.stealer();
585/// assert_eq!(s.steal(), Steal::Success(1));
586/// assert_eq!(s.steal(), Steal::Success(2));
587/// assert_eq!(s.steal(), Steal::Empty);
588/// ```
589pub struct Stealer<T> {
590    /// A reference to the inner representation of the queue.
591    inner: Arc<CachePadded<Inner<T>>>,
592
593    /// The flavor of the queue.
594    flavor: Flavor,
595}
596
597unsafe impl<T: Send> Send for Stealer<T> {}
598unsafe impl<T: Send> Sync for Stealer<T> {}
599
600impl<T> Stealer<T> {
601    /// Returns `true` if the queue is empty.
602    ///
603    /// ```
604    /// use crossbeam_deque::Worker;
605    ///
606    /// let w = Worker::new_lifo();
607    /// let s = w.stealer();
608    ///
609    /// assert!(s.is_empty());
610    /// w.push(1);
611    /// assert!(!s.is_empty());
612    /// ```
613    pub fn is_empty(&self) -> bool {
614        let f = self.inner.front.load(Ordering::Acquire);
615        atomic::fence(Ordering::SeqCst);
616        let b = self.inner.back.load(Ordering::Acquire);
617        b.wrapping_sub(f) <= 0
618    }
619
620    /// Returns the number of tasks in the deque.
621    ///
622    /// ```
623    /// use crossbeam_deque::Worker;
624    ///
625    /// let w = Worker::new_lifo();
626    /// let s = w.stealer();
627    ///
628    /// assert_eq!(s.len(), 0);
629    /// w.push(1);
630    /// assert_eq!(s.len(), 1);
631    /// w.push(2);
632    /// assert_eq!(s.len(), 2);
633    /// ```
634    pub fn len(&self) -> usize {
635        let f = self.inner.front.load(Ordering::Acquire);
636        atomic::fence(Ordering::SeqCst);
637        let b = self.inner.back.load(Ordering::Acquire);
638        b.wrapping_sub(f).max(0) as usize
639    }
640
641    /// Steals a task from the queue.
642    ///
643    /// # Examples
644    ///
645    /// ```
646    /// use crossbeam_deque::{Steal, Worker};
647    ///
648    /// let w = Worker::new_lifo();
649    /// w.push(1);
650    /// w.push(2);
651    ///
652    /// let s = w.stealer();
653    /// assert_eq!(s.steal(), Steal::Success(1));
654    /// assert_eq!(s.steal(), Steal::Success(2));
655    /// ```
656    pub fn steal(&self) -> Steal<T> {
657        // Load the front index.
658        let f = self.inner.front.load(Ordering::Acquire);
659
660        // A SeqCst fence is needed here.
661        //
662        // If the current thread is already pinned (reentrantly), we must manually issue the
663        // fence. Otherwise, the following pinning will issue the fence anyway, so we don't
664        // have to.
665        if epoch::is_pinned() {
666            atomic::fence(Ordering::SeqCst);
667        }
668
669        let guard = &epoch::pin();
670
671        // Load the back index.
672        let b = self.inner.back.load(Ordering::Acquire);
673
674        // Is the queue empty?
675        if b.wrapping_sub(f) <= 0 {
676            return Steal::Empty;
677        }
678
679        // Load the buffer and read the task at the front.
680        let buffer = self.inner.buffer.load(Ordering::Acquire, guard);
681        let task = unsafe { buffer.deref().read(f) };
682
683        // Try incrementing the front index to steal the task.
684        // If the buffer has been swapped or the increment fails, we retry.
685        if self.inner.buffer.load(Ordering::Acquire, guard) != buffer
686            || self
687                .inner
688                .front
689                .compare_exchange(f, f.wrapping_add(1), Ordering::SeqCst, Ordering::Relaxed)
690                .is_err()
691        {
692            // We didn't steal this task, forget it.
693            return Steal::Retry;
694        }
695
696        // Return the stolen task.
697        Steal::Success(unsafe { task.assume_init() })
698    }
699
700    /// Steals a batch of tasks and pushes them into another worker.
701    ///
702    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
703    /// steal around half of the tasks in the queue, but also not more than some constant limit.
704    ///
705    /// # Examples
706    ///
707    /// ```
708    /// use crossbeam_deque::Worker;
709    ///
710    /// let w1 = Worker::new_fifo();
711    /// w1.push(1);
712    /// w1.push(2);
713    /// w1.push(3);
714    /// w1.push(4);
715    ///
716    /// let s = w1.stealer();
717    /// let w2 = Worker::new_fifo();
718    ///
719    /// let _ = s.steal_batch(&w2);
720    /// assert_eq!(w2.pop(), Some(1));
721    /// assert_eq!(w2.pop(), Some(2));
722    /// ```
723    pub fn steal_batch(&self, dest: &Worker<T>) -> Steal<()> {
724        self.steal_batch_with_limit(dest, MAX_BATCH)
725    }
726
727    /// Steals no more than `limit` of tasks and pushes them into another worker.
728    ///
729    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
730    /// steal around half of the tasks in the queue, but also not more than the given limit.
731    ///
732    /// # Examples
733    ///
734    /// ```
735    /// use crossbeam_deque::Worker;
736    ///
737    /// let w1 = Worker::new_fifo();
738    /// w1.push(1);
739    /// w1.push(2);
740    /// w1.push(3);
741    /// w1.push(4);
742    /// w1.push(5);
743    /// w1.push(6);
744    ///
745    /// let s = w1.stealer();
746    /// let w2 = Worker::new_fifo();
747    ///
748    /// let _ = s.steal_batch_with_limit(&w2, 2);
749    /// assert_eq!(w2.pop(), Some(1));
750    /// assert_eq!(w2.pop(), Some(2));
751    /// assert_eq!(w2.pop(), None);
752    ///
753    /// w1.push(7);
754    /// w1.push(8);
755    /// // Setting a large limit does not guarantee that all elements will be popped. In this case,
756    /// // half of the elements are currently popped, but the number of popped elements is considered
757    /// // an implementation detail that may be changed in the future.
758    /// let _ = s.steal_batch_with_limit(&w2, usize::MAX);
759    /// assert_eq!(w2.len(), 3);
760    /// ```
761    pub fn steal_batch_with_limit(&self, dest: &Worker<T>, limit: usize) -> Steal<()> {
762        assert!(limit > 0);
763        if Arc::ptr_eq(&self.inner, &dest.inner) {
764            if dest.is_empty() {
765                return Steal::Empty;
766            } else {
767                return Steal::Success(());
768            }
769        }
770
771        // Load the front index.
772        let mut f = self.inner.front.load(Ordering::Acquire);
773
774        // A SeqCst fence is needed here.
775        //
776        // If the current thread is already pinned (reentrantly), we must manually issue the
777        // fence. Otherwise, the following pinning will issue the fence anyway, so we don't
778        // have to.
779        if epoch::is_pinned() {
780            atomic::fence(Ordering::SeqCst);
781        }
782
783        let guard = &epoch::pin();
784
785        // Load the back index.
786        let b = self.inner.back.load(Ordering::Acquire);
787
788        // Is the queue empty?
789        let len = b.wrapping_sub(f);
790        if len <= 0 {
791            return Steal::Empty;
792        }
793
794        // Reserve capacity for the stolen batch.
795        let batch_size = cmp::min((len as usize + 1) / 2, limit);
796        dest.reserve(batch_size);
797        let mut batch_size = batch_size as WorkerIndex;
798
799        // Get the destination buffer and back index.
800        let dest_buffer = dest.buffer.get();
801        let mut dest_b = dest.inner.back.load(Ordering::Relaxed);
802
803        // Load the buffer.
804        let buffer = self.inner.buffer.load(Ordering::Acquire, guard);
805
806        match self.flavor {
807            // Steal a batch of tasks from the front at once.
808            Flavor::Fifo => {
809                // Copy the batch from the source to the destination buffer.
810                match dest.flavor {
811                    Flavor::Fifo => {
812                        for i in 0..batch_size {
813                            unsafe {
814                                let task = buffer.deref().read(f.wrapping_add(i));
815                                dest_buffer.write(dest_b.wrapping_add(i), task);
816                            }
817                        }
818                    }
819                    Flavor::Lifo => {
820                        for i in 0..batch_size {
821                            unsafe {
822                                let task = buffer.deref().read(f.wrapping_add(i));
823                                dest_buffer.write(dest_b.wrapping_add(batch_size - 1 - i), task);
824                            }
825                        }
826                    }
827                }
828
829                // Try incrementing the front index to steal the batch.
830                // If the buffer has been swapped or the increment fails, we retry.
831                if self.inner.buffer.load(Ordering::Acquire, guard) != buffer
832                    || self
833                        .inner
834                        .front
835                        .compare_exchange(
836                            f,
837                            f.wrapping_add(batch_size),
838                            Ordering::SeqCst,
839                            Ordering::Relaxed,
840                        )
841                        .is_err()
842                {
843                    return Steal::Retry;
844                }
845
846                dest_b = dest_b.wrapping_add(batch_size);
847            }
848
849            // Steal a batch of tasks from the front one by one.
850            Flavor::Lifo => {
851                // This loop may modify the batch_size, which triggers a clippy lint warning.
852                // Use a new variable to avoid the warning, and to make it clear we aren't
853                // modifying the loop exit condition during iteration.
854                let original_batch_size = batch_size;
855
856                for i in 0..original_batch_size {
857                    // If this is not the first steal, check whether the queue is empty.
858                    if i > 0 {
859                        // We've already got the current front index. Now execute the fence to
860                        // synchronize with other threads.
861                        atomic::fence(Ordering::SeqCst);
862
863                        // Load the back index.
864                        let b = self.inner.back.load(Ordering::Acquire);
865
866                        // Is the queue empty?
867                        if b.wrapping_sub(f) <= 0 {
868                            batch_size = i;
869                            break;
870                        }
871                    }
872
873                    // Read the task at the front.
874                    let task = unsafe { buffer.deref().read(f) };
875
876                    // Try incrementing the front index to steal the task.
877                    // If the buffer has been swapped or the increment fails, we retry.
878                    if self.inner.buffer.load(Ordering::Acquire, guard) != buffer
879                        || self
880                            .inner
881                            .front
882                            .compare_exchange(
883                                f,
884                                f.wrapping_add(1),
885                                Ordering::SeqCst,
886                                Ordering::Relaxed,
887                            )
888                            .is_err()
889                    {
890                        // We didn't steal this task, forget it and break from the loop.
891                        batch_size = i;
892                        break;
893                    }
894
895                    // Write the stolen task into the destination buffer.
896                    unsafe {
897                        dest_buffer.write(dest_b, task);
898                    }
899
900                    // Move the source front index and the destination back index one step forward.
901                    f = f.wrapping_add(1);
902                    dest_b = dest_b.wrapping_add(1);
903                }
904
905                // If we didn't steal anything, the operation needs to be retried.
906                if batch_size == 0 {
907                    return Steal::Retry;
908                }
909
910                // If stealing into a FIFO queue, stolen tasks need to be reversed.
911                if dest.flavor == Flavor::Fifo {
912                    for i in 0..batch_size / 2 {
913                        unsafe {
914                            let i1 = dest_b.wrapping_sub(batch_size - i);
915                            let i2 = dest_b.wrapping_sub(i + 1);
916                            let t1 = dest_buffer.read(i1);
917                            let t2 = dest_buffer.read(i2);
918                            dest_buffer.write(i1, t2);
919                            dest_buffer.write(i2, t1);
920                        }
921                    }
922                }
923            }
924        }
925
926        // ThreadSanitizer does not understand fences, so we omit fence and do store with Release ordering.
927        #[cfg(not(crossbeam_sanitize_thread))]
928        atomic::fence(Ordering::Release);
929        let store_order = if cfg!(crossbeam_sanitize_thread) {
930            Ordering::Release
931        } else {
932            Ordering::Relaxed
933        };
934
935        // Update the back index in the destination queue.
936        dest.inner.back.store(dest_b, store_order);
937
938        // Return with success.
939        Steal::Success(())
940    }
941
942    /// Steals a batch of tasks, pushes them into another worker, and pops a task from that worker.
943    ///
944    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
945    /// steal around half of the tasks in the queue, but also not more than some constant limit.
946    ///
947    /// # Examples
948    ///
949    /// ```
950    /// use crossbeam_deque::{Steal, Worker};
951    ///
952    /// let w1 = Worker::new_fifo();
953    /// w1.push(1);
954    /// w1.push(2);
955    /// w1.push(3);
956    /// w1.push(4);
957    ///
958    /// let s = w1.stealer();
959    /// let w2 = Worker::new_fifo();
960    ///
961    /// assert_eq!(s.steal_batch_and_pop(&w2), Steal::Success(1));
962    /// assert_eq!(w2.pop(), Some(2));
963    /// ```
964    pub fn steal_batch_and_pop(&self, dest: &Worker<T>) -> Steal<T> {
965        self.steal_batch_with_limit_and_pop(dest, MAX_BATCH)
966    }
967
968    /// Steals no more than `limit` of tasks, pushes them into another worker, and pops a task from
969    /// that worker.
970    ///
971    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
972    /// steal around half of the tasks in the queue, but also not more than the given limit.
973    ///
974    /// # Examples
975    ///
976    /// ```
977    /// use crossbeam_deque::{Steal, Worker};
978    ///
979    /// let w1 = Worker::new_fifo();
980    /// w1.push(1);
981    /// w1.push(2);
982    /// w1.push(3);
983    /// w1.push(4);
984    /// w1.push(5);
985    /// w1.push(6);
986    ///
987    /// let s = w1.stealer();
988    /// let w2 = Worker::new_fifo();
989    ///
990    /// assert_eq!(s.steal_batch_with_limit_and_pop(&w2, 2), Steal::Success(1));
991    /// assert_eq!(w2.pop(), Some(2));
992    /// assert_eq!(w2.pop(), None);
993    ///
994    /// w1.push(7);
995    /// w1.push(8);
996    /// // Setting a large limit does not guarantee that all elements will be popped. In this case,
997    /// // half of the elements are currently popped, but the number of popped elements is considered
998    /// // an implementation detail that may be changed in the future.
999    /// assert_eq!(s.steal_batch_with_limit_and_pop(&w2, usize::MAX), Steal::Success(3));
1000    /// assert_eq!(w2.pop(), Some(4));
1001    /// assert_eq!(w2.pop(), Some(5));
1002    /// assert_eq!(w2.pop(), None);
1003    /// ```
1004    pub fn steal_batch_with_limit_and_pop(&self, dest: &Worker<T>, limit: usize) -> Steal<T> {
1005        assert!(limit > 0);
1006        if Arc::ptr_eq(&self.inner, &dest.inner) {
1007            match dest.pop() {
1008                None => return Steal::Empty,
1009                Some(task) => return Steal::Success(task),
1010            }
1011        }
1012
1013        // Load the front index.
1014        let mut f = self.inner.front.load(Ordering::Acquire);
1015
1016        // A SeqCst fence is needed here.
1017        //
1018        // If the current thread is already pinned (reentrantly), we must manually issue the
1019        // fence. Otherwise, the following pinning will issue the fence anyway, so we don't
1020        // have to.
1021        if epoch::is_pinned() {
1022            atomic::fence(Ordering::SeqCst);
1023        }
1024
1025        let guard = &epoch::pin();
1026
1027        // Load the back index.
1028        let b = self.inner.back.load(Ordering::Acquire);
1029
1030        // Is the queue empty?
1031        let len = b.wrapping_sub(f);
1032        if len <= 0 {
1033            return Steal::Empty;
1034        }
1035
1036        // Reserve capacity for the stolen batch.
1037        let batch_size = cmp::min((len as usize - 1) / 2, limit - 1);
1038        dest.reserve(batch_size);
1039        let mut batch_size = batch_size as WorkerIndex;
1040
1041        // Get the destination buffer and back index.
1042        let dest_buffer = dest.buffer.get();
1043        let mut dest_b = dest.inner.back.load(Ordering::Relaxed);
1044
1045        // Load the buffer
1046        let buffer = self.inner.buffer.load(Ordering::Acquire, guard);
1047
1048        // Read the task at the front.
1049        let mut task = unsafe { buffer.deref().read(f) };
1050
1051        match self.flavor {
1052            // Steal a batch of tasks from the front at once.
1053            Flavor::Fifo => {
1054                // Copy the batch from the source to the destination buffer.
1055                match dest.flavor {
1056                    Flavor::Fifo => {
1057                        for i in 0..batch_size {
1058                            unsafe {
1059                                let task = buffer.deref().read(f.wrapping_add(i + 1));
1060                                dest_buffer.write(dest_b.wrapping_add(i), task);
1061                            }
1062                        }
1063                    }
1064                    Flavor::Lifo => {
1065                        for i in 0..batch_size {
1066                            unsafe {
1067                                let task = buffer.deref().read(f.wrapping_add(i + 1));
1068                                dest_buffer.write(dest_b.wrapping_add(batch_size - 1 - i), task);
1069                            }
1070                        }
1071                    }
1072                }
1073
1074                // Try incrementing the front index to steal the task.
1075                // If the buffer has been swapped or the increment fails, we retry.
1076                if self.inner.buffer.load(Ordering::Acquire, guard) != buffer
1077                    || self
1078                        .inner
1079                        .front
1080                        .compare_exchange(
1081                            f,
1082                            f.wrapping_add(batch_size + 1),
1083                            Ordering::SeqCst,
1084                            Ordering::Relaxed,
1085                        )
1086                        .is_err()
1087                {
1088                    // We didn't steal this task, forget it.
1089                    return Steal::Retry;
1090                }
1091
1092                dest_b = dest_b.wrapping_add(batch_size);
1093            }
1094
1095            // Steal a batch of tasks from the front one by one.
1096            Flavor::Lifo => {
1097                // Try incrementing the front index to steal the task.
1098                if self
1099                    .inner
1100                    .front
1101                    .compare_exchange(f, f.wrapping_add(1), Ordering::SeqCst, Ordering::Relaxed)
1102                    .is_err()
1103                {
1104                    // We didn't steal this task, forget it.
1105                    return Steal::Retry;
1106                }
1107
1108                // Move the front index one step forward.
1109                f = f.wrapping_add(1);
1110
1111                // Repeat the same procedure for the batch steals.
1112                //
1113                // This loop may modify the batch_size, which triggers a clippy lint warning.
1114                // Use a new variable to avoid the warning, and to make it clear we aren't
1115                // modifying the loop exit condition during iteration.
1116                let original_batch_size = batch_size;
1117                for i in 0..original_batch_size {
1118                    // We've already got the current front index. Now execute the fence to
1119                    // synchronize with other threads.
1120                    atomic::fence(Ordering::SeqCst);
1121
1122                    // Load the back index.
1123                    let b = self.inner.back.load(Ordering::Acquire);
1124
1125                    // Is the queue empty?
1126                    if b.wrapping_sub(f) <= 0 {
1127                        batch_size = i;
1128                        break;
1129                    }
1130
1131                    // Read the task at the front.
1132                    let tmp = unsafe { buffer.deref().read(f) };
1133
1134                    // Try incrementing the front index to steal the task.
1135                    // If the buffer has been swapped or the increment fails, we retry.
1136                    if self.inner.buffer.load(Ordering::Acquire, guard) != buffer
1137                        || self
1138                            .inner
1139                            .front
1140                            .compare_exchange(
1141                                f,
1142                                f.wrapping_add(1),
1143                                Ordering::SeqCst,
1144                                Ordering::Relaxed,
1145                            )
1146                            .is_err()
1147                    {
1148                        // We didn't steal this task, forget it and break from the loop.
1149                        batch_size = i;
1150                        break;
1151                    }
1152
1153                    // Write the previously stolen task into the destination buffer.
1154                    unsafe {
1155                        dest_buffer.write(dest_b, mem::replace(&mut task, tmp));
1156                    }
1157
1158                    // Move the source front index and the destination back index one step forward.
1159                    f = f.wrapping_add(1);
1160                    dest_b = dest_b.wrapping_add(1);
1161                }
1162
1163                // If stealing into a FIFO queue, stolen tasks need to be reversed.
1164                if dest.flavor == Flavor::Fifo {
1165                    for i in 0..batch_size / 2 {
1166                        unsafe {
1167                            let i1 = dest_b.wrapping_sub(batch_size - i);
1168                            let i2 = dest_b.wrapping_sub(i + 1);
1169                            let t1 = dest_buffer.read(i1);
1170                            let t2 = dest_buffer.read(i2);
1171                            dest_buffer.write(i1, t2);
1172                            dest_buffer.write(i2, t1);
1173                        }
1174                    }
1175                }
1176            }
1177        }
1178
1179        // ThreadSanitizer does not understand fences, so we omit fence and do store with Release ordering.
1180        #[cfg(not(crossbeam_sanitize_thread))]
1181        atomic::fence(Ordering::Release);
1182        let store_order = if cfg!(crossbeam_sanitize_thread) {
1183            Ordering::Release
1184        } else {
1185            Ordering::Relaxed
1186        };
1187
1188        // Update the back index in the destination queue.
1189        dest.inner.back.store(dest_b, store_order);
1190
1191        // Return with success.
1192        Steal::Success(unsafe { task.assume_init() })
1193    }
1194}
1195
1196impl<T> Clone for Stealer<T> {
1197    fn clone(&self) -> Stealer<T> {
1198        Stealer {
1199            inner: self.inner.clone(),
1200            flavor: self.flavor,
1201        }
1202    }
1203}
1204
1205impl<T> fmt::Debug for Stealer<T> {
1206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1207        f.pad("Stealer { .. }")
1208    }
1209}
1210
1211// Bits indicating the state of a slot:
1212// * If a task has been written into the slot, `WRITE` is set.
1213// * If a task has been read from the slot, `READ` is set.
1214// * If the block is being destroyed, `DESTROY` is set.
1215const WRITE: usize = 1;
1216const READ: usize = 2;
1217const DESTROY: usize = 4;
1218
1219// Each block covers one "lap" of indices.
1220const LAP: Index = 64;
1221// The maximum number of values a block can hold.
1222const BLOCK_CAP: usize = LAP as usize - 1;
1223// How many lower bits are reserved for metadata.
1224const SHIFT: usize = 1;
1225// Indicates that the block is not the last one.
1226const HAS_NEXT: Index = 1;
1227
1228/// A slot in a block.
1229struct Slot<T> {
1230    /// The task.
1231    task: UnsafeCell<MaybeUninit<T>>,
1232
1233    /// The state of the slot.
1234    state: AtomicUsize,
1235}
1236
1237impl<T> Slot<T> {
1238    /// Waits until a task is written into the slot.
1239    fn wait_write(&self) {
1240        let backoff = Backoff::new();
1241        while self.state.load(Ordering::Acquire) & WRITE == 0 {
1242            backoff.snooze();
1243        }
1244    }
1245}
1246
1247/// A block in a linked list.
1248///
1249/// Each block in the list can hold up to `BLOCK_CAP` values.
1250struct Block<T> {
1251    /// The next block in the linked list.
1252    next: AtomicPtr<Block<T>>,
1253
1254    /// Slots for values.
1255    slots: [Slot<T>; BLOCK_CAP],
1256}
1257
1258impl<T> Block<T> {
1259    const LAYOUT: Layout = {
1260        let layout = Layout::new::<Self>();
1261        assert!(
1262            layout.size() != 0,
1263            "Block should never be zero-sized, as it has an AtomicPtr field"
1264        );
1265        layout
1266    };
1267
1268    /// Creates an empty block.
1269    fn new() -> Box<Self> {
1270        // SAFETY: layout is not zero-sized
1271        let ptr = unsafe { alloc_zeroed(Self::LAYOUT) };
1272        // Handle allocation failure
1273        if ptr.is_null() {
1274            handle_alloc_error(Self::LAYOUT)
1275        }
1276        // SAFETY: This is safe because:
1277        //  [1] `Block::next` (AtomicPtr) may be safely zero initialized.
1278        //  [2] `Block::slots` (Array) may be safely zero initialized because of [3, 4].
1279        //  [3] `Slot::task` (UnsafeCell) may be safely zero initialized because it
1280        //       holds a MaybeUninit.
1281        //  [4] `Slot::state` (AtomicUsize) may be safely zero initialized.
1282        // TODO: unsafe { Box::new_zeroed().assume_init() }
1283        unsafe { Box::from_raw(ptr.cast()) }
1284    }
1285
1286    /// Waits until the next pointer is set.
1287    fn wait_next(&self) -> *mut Block<T> {
1288        let backoff = Backoff::new();
1289        loop {
1290            let next = self.next.load(Ordering::Acquire);
1291            if !next.is_null() {
1292                return next;
1293            }
1294            backoff.snooze();
1295        }
1296    }
1297
1298    /// Sets the `DESTROY` bit in slots starting from `start` and destroys the block.
1299    unsafe fn destroy(this: *mut Block<T>, count: usize) {
1300        // It is not necessary to set the `DESTROY` bit in the last slot because that slot has
1301        // begun destruction of the block.
1302        for i in (0..count).rev() {
1303            let slot = (*this).slots.get_unchecked(i);
1304
1305            // Mark the `DESTROY` bit if a thread is still using the slot.
1306            if slot.state.load(Ordering::Acquire) & READ == 0
1307                && slot.state.fetch_or(DESTROY, Ordering::AcqRel) & READ == 0
1308            {
1309                // If a thread is still using the slot, it will continue destruction of the block.
1310                return;
1311            }
1312        }
1313
1314        // No thread is using the block, now it is safe to destroy it.
1315        drop(Box::from_raw(this));
1316    }
1317}
1318
1319/// A position in a queue.
1320struct Position<T> {
1321    /// The index in the queue.
1322    index: AtomicIndex,
1323
1324    /// The block in the linked list.
1325    block: AtomicPtr<Block<T>>,
1326}
1327
1328/// An injector queue.
1329///
1330/// This is a FIFO queue that can be shared among multiple threads. Task schedulers typically have
1331/// a single injector queue, which is the entry point for new tasks.
1332///
1333/// # Examples
1334///
1335/// ```
1336/// use crossbeam_deque::{Injector, Steal};
1337///
1338/// let q = Injector::new();
1339/// q.push(1);
1340/// q.push(2);
1341///
1342/// assert_eq!(q.steal(), Steal::Success(1));
1343/// assert_eq!(q.steal(), Steal::Success(2));
1344/// assert_eq!(q.steal(), Steal::Empty);
1345/// ```
1346pub struct Injector<T> {
1347    /// The head of the queue.
1348    head: CachePadded<Position<T>>,
1349
1350    /// The tail of the queue.
1351    tail: CachePadded<Position<T>>,
1352
1353    /// Indicates that dropping a `Injector<T>` may drop values of type `T`.
1354    _marker: PhantomData<T>,
1355}
1356
1357unsafe impl<T: Send> Send for Injector<T> {}
1358unsafe impl<T: Send> Sync for Injector<T> {}
1359
1360impl<T> Default for Injector<T> {
1361    fn default() -> Self {
1362        let block = Box::into_raw(Block::<T>::new());
1363        Self {
1364            head: CachePadded::new(Position {
1365                block: AtomicPtr::new(block),
1366                index: AtomicIndex::new(0),
1367            }),
1368            tail: CachePadded::new(Position {
1369                block: AtomicPtr::new(block),
1370                index: AtomicIndex::new(0),
1371            }),
1372            _marker: PhantomData,
1373        }
1374    }
1375}
1376
1377impl<T> Injector<T> {
1378    /// Creates a new injector queue.
1379    ///
1380    /// # Examples
1381    ///
1382    /// ```
1383    /// use crossbeam_deque::Injector;
1384    ///
1385    /// let q = Injector::<i32>::new();
1386    /// ```
1387    pub fn new() -> Injector<T> {
1388        Self::default()
1389    }
1390
1391    /// Pushes a task into the queue.
1392    ///
1393    /// # Examples
1394    ///
1395    /// ```
1396    /// use crossbeam_deque::Injector;
1397    ///
1398    /// let w = Injector::new();
1399    /// w.push(1);
1400    /// w.push(2);
1401    /// ```
1402    pub fn push(&self, task: T) {
1403        let backoff = Backoff::new();
1404        let mut tail = self.tail.index.load(Ordering::Acquire);
1405        let mut block = self.tail.block.load(Ordering::Acquire);
1406        let mut next_block = None;
1407
1408        loop {
1409            // Calculate the offset of the index into the block.
1410            let offset = ((tail >> SHIFT) % LAP) as usize;
1411
1412            // If we reached the end of the block, wait until the next one is installed.
1413            if offset == BLOCK_CAP {
1414                backoff.snooze();
1415                tail = self.tail.index.load(Ordering::Acquire);
1416                block = self.tail.block.load(Ordering::Acquire);
1417                continue;
1418            }
1419
1420            // If we're going to have to install the next block, allocate it in advance in order to
1421            // make the wait for other threads as short as possible.
1422            if offset + 1 == BLOCK_CAP && next_block.is_none() {
1423                next_block = Some(Block::<T>::new());
1424            }
1425
1426            let new_tail = tail + (1 << SHIFT);
1427
1428            // Try advancing the tail forward.
1429            match self.tail.index.compare_exchange_weak(
1430                tail,
1431                new_tail,
1432                Ordering::SeqCst,
1433                Ordering::Acquire,
1434            ) {
1435                Ok(_) => unsafe {
1436                    // If we've reached the end of the block, install the next one.
1437                    if offset + 1 == BLOCK_CAP {
1438                        let next_block = Box::into_raw(next_block.unwrap());
1439                        let next_index = new_tail.wrapping_add(1 << SHIFT);
1440
1441                        self.tail.block.store(next_block, Ordering::Release);
1442                        self.tail.index.store(next_index, Ordering::Release);
1443                        (*block).next.store(next_block, Ordering::Release);
1444                    }
1445
1446                    // Write the task into the slot.
1447                    let slot = (*block).slots.get_unchecked(offset);
1448                    slot.task.get().write(MaybeUninit::new(task));
1449                    slot.state.fetch_or(WRITE, Ordering::Release);
1450
1451                    return;
1452                },
1453                Err(t) => {
1454                    tail = t;
1455                    block = self.tail.block.load(Ordering::Acquire);
1456                    backoff.spin();
1457                }
1458            }
1459        }
1460    }
1461
1462    /// Steals a task from the queue.
1463    ///
1464    /// # Examples
1465    ///
1466    /// ```
1467    /// use crossbeam_deque::{Injector, Steal};
1468    ///
1469    /// let q = Injector::new();
1470    /// q.push(1);
1471    /// q.push(2);
1472    ///
1473    /// assert_eq!(q.steal(), Steal::Success(1));
1474    /// assert_eq!(q.steal(), Steal::Success(2));
1475    /// assert_eq!(q.steal(), Steal::Empty);
1476    /// ```
1477    pub fn steal(&self) -> Steal<T> {
1478        let mut head;
1479        let mut block;
1480        let mut offset;
1481
1482        let backoff = Backoff::new();
1483        loop {
1484            head = self.head.index.load(Ordering::Acquire);
1485            block = self.head.block.load(Ordering::Acquire);
1486
1487            // Calculate the offset of the index into the block.
1488            offset = ((head >> SHIFT) % LAP) as usize;
1489
1490            // If we reached the end of the block, wait until the next one is installed.
1491            if offset == BLOCK_CAP {
1492                backoff.snooze();
1493            } else {
1494                break;
1495            }
1496        }
1497
1498        let mut new_head = head + (1 << SHIFT);
1499
1500        if new_head & HAS_NEXT == 0 {
1501            atomic::fence(Ordering::SeqCst);
1502            let tail = self.tail.index.load(Ordering::Relaxed);
1503
1504            // If the tail equals the head, that means the queue is empty.
1505            if head >> SHIFT == tail >> SHIFT {
1506                return Steal::Empty;
1507            }
1508
1509            // If head and tail are not in the same block, set `HAS_NEXT` in head.
1510            if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP {
1511                new_head |= HAS_NEXT;
1512            }
1513        }
1514
1515        // Try moving the head index forward.
1516        if self
1517            .head
1518            .index
1519            .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire)
1520            .is_err()
1521        {
1522            return Steal::Retry;
1523        }
1524
1525        unsafe {
1526            // If we've reached the end of the block, move to the next one.
1527            if offset + 1 == BLOCK_CAP {
1528                let next = (*block).wait_next();
1529                let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT);
1530                if !(*next).next.load(Ordering::Relaxed).is_null() {
1531                    next_index |= HAS_NEXT;
1532                }
1533
1534                self.head.block.store(next, Ordering::Release);
1535                self.head.index.store(next_index, Ordering::Release);
1536            }
1537
1538            // Read the task.
1539            let slot = (*block).slots.get_unchecked(offset);
1540            slot.wait_write();
1541            let task = slot.task.get().read().assume_init();
1542
1543            // Destroy the block if we've reached the end, or if another thread wanted to destroy
1544            // but couldn't because we were busy reading from the slot.
1545            if (offset + 1 == BLOCK_CAP)
1546                || (slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0)
1547            {
1548                Block::destroy(block, offset);
1549            }
1550
1551            Steal::Success(task)
1552        }
1553    }
1554
1555    /// Steals a batch of tasks and pushes them into a worker.
1556    ///
1557    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
1558    /// steal around half of the tasks in the queue, but also not more than some constant limit.
1559    ///
1560    /// # Examples
1561    ///
1562    /// ```
1563    /// use crossbeam_deque::{Injector, Worker};
1564    ///
1565    /// let q = Injector::new();
1566    /// q.push(1);
1567    /// q.push(2);
1568    /// q.push(3);
1569    /// q.push(4);
1570    ///
1571    /// let w = Worker::new_fifo();
1572    /// let _ = q.steal_batch(&w);
1573    /// assert_eq!(w.pop(), Some(1));
1574    /// assert_eq!(w.pop(), Some(2));
1575    /// ```
1576    pub fn steal_batch(&self, dest: &Worker<T>) -> Steal<()> {
1577        self.steal_batch_with_limit(dest, MAX_BATCH)
1578    }
1579
1580    /// Steals no more than `limit` of tasks and pushes them into a worker.
1581    ///
1582    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
1583    /// steal around half of the tasks in the queue, but also not more than some constant limit.
1584    ///
1585    /// # Examples
1586    ///
1587    /// ```
1588    /// use crossbeam_deque::{Injector, Worker};
1589    ///
1590    /// let q = Injector::new();
1591    /// q.push(1);
1592    /// q.push(2);
1593    /// q.push(3);
1594    /// q.push(4);
1595    /// q.push(5);
1596    /// q.push(6);
1597    ///
1598    /// let w = Worker::new_fifo();
1599    /// let _ = q.steal_batch_with_limit(&w, 2);
1600    /// assert_eq!(w.pop(), Some(1));
1601    /// assert_eq!(w.pop(), Some(2));
1602    /// assert_eq!(w.pop(), None);
1603    ///
1604    /// q.push(7);
1605    /// q.push(8);
1606    /// // Setting a large limit does not guarantee that all elements will be popped. In this case,
1607    /// // half of the elements are currently popped, but the number of popped elements is considered
1608    /// // an implementation detail that may be changed in the future.
1609    /// let _ = q.steal_batch_with_limit(&w, usize::MAX);
1610    /// assert_eq!(w.len(), 3);
1611    /// ```
1612    pub fn steal_batch_with_limit(&self, dest: &Worker<T>, limit: usize) -> Steal<()> {
1613        assert!(limit > 0);
1614        let mut head;
1615        let mut block;
1616        let mut offset;
1617
1618        let backoff = Backoff::new();
1619        loop {
1620            head = self.head.index.load(Ordering::Acquire);
1621            block = self.head.block.load(Ordering::Acquire);
1622
1623            // Calculate the offset of the index into the block.
1624            offset = ((head >> SHIFT) % LAP) as usize;
1625
1626            // If we reached the end of the block, wait until the next one is installed.
1627            if offset == BLOCK_CAP {
1628                backoff.snooze();
1629            } else {
1630                break;
1631            }
1632        }
1633
1634        let mut new_head = head;
1635        let advance;
1636
1637        if new_head & HAS_NEXT == 0 {
1638            atomic::fence(Ordering::SeqCst);
1639            let tail = self.tail.index.load(Ordering::Relaxed);
1640
1641            // If the tail equals the head, that means the queue is empty.
1642            if head >> SHIFT == tail >> SHIFT {
1643                return Steal::Empty;
1644            }
1645
1646            // If head and tail are not in the same block, set `HAS_NEXT` in head. Also, calculate
1647            // the right batch size to steal.
1648            if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP {
1649                new_head |= HAS_NEXT;
1650                // We can steal all tasks till the end of the block.
1651                advance = (BLOCK_CAP - offset).min(limit);
1652            } else {
1653                let len = ((tail - head) >> SHIFT) as usize;
1654                // Steal half of the available tasks.
1655                advance = ((len + 1) / 2).min(limit);
1656            }
1657        } else {
1658            // We can steal all tasks till the end of the block.
1659            advance = (BLOCK_CAP - offset).min(limit);
1660        }
1661
1662        new_head += (advance as Index) << SHIFT;
1663        let new_offset = offset + advance;
1664
1665        // Try moving the head index forward.
1666        if self
1667            .head
1668            .index
1669            .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire)
1670            .is_err()
1671        {
1672            return Steal::Retry;
1673        }
1674
1675        // Reserve capacity for the stolen batch.
1676        let batch_size = new_offset - offset;
1677        dest.reserve(batch_size);
1678
1679        // Get the destination buffer and back index.
1680        let dest_buffer = dest.buffer.get();
1681        let dest_b = dest.inner.back.load(Ordering::Relaxed);
1682
1683        unsafe {
1684            // If we've reached the end of the block, move to the next one.
1685            if new_offset == BLOCK_CAP {
1686                let next = (*block).wait_next();
1687                let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT);
1688                if !(*next).next.load(Ordering::Relaxed).is_null() {
1689                    next_index |= HAS_NEXT;
1690                }
1691
1692                self.head.block.store(next, Ordering::Release);
1693                self.head.index.store(next_index, Ordering::Release);
1694            }
1695
1696            // Copy values from the injector into the destination queue.
1697            match dest.flavor {
1698                Flavor::Fifo => {
1699                    for i in 0..batch_size {
1700                        // Read the task.
1701                        let slot = (*block).slots.get_unchecked(offset + i);
1702                        slot.wait_write();
1703                        let task = slot.task.get().read();
1704
1705                        // Write it into the destination queue.
1706                        dest_buffer.write(dest_b.wrapping_add(i as WorkerIndex), task);
1707                    }
1708                }
1709
1710                Flavor::Lifo => {
1711                    for i in 0..batch_size {
1712                        // Read the task.
1713                        let slot = (*block).slots.get_unchecked(offset + i);
1714                        slot.wait_write();
1715                        let task = slot.task.get().read();
1716
1717                        // Write it into the destination queue.
1718                        dest_buffer.write(
1719                            dest_b.wrapping_add((batch_size - 1 - i) as WorkerIndex),
1720                            task,
1721                        );
1722                    }
1723                }
1724            }
1725
1726            // ThreadSanitizer does not understand fences, so we omit fence and do store with Release ordering.
1727            #[cfg(not(crossbeam_sanitize_thread))]
1728            atomic::fence(Ordering::Release);
1729            let store_order = if cfg!(crossbeam_sanitize_thread) {
1730                Ordering::Release
1731            } else {
1732                Ordering::Relaxed
1733            };
1734
1735            // Update the back index in the destination queue.
1736            dest.inner
1737                .back
1738                .store(dest_b.wrapping_add(batch_size as WorkerIndex), store_order);
1739
1740            // Destroy the block if we've reached the end, or if another thread wanted to destroy
1741            // but couldn't because we were busy reading from the slot.
1742            if new_offset == BLOCK_CAP {
1743                Block::destroy(block, offset);
1744            } else {
1745                for i in offset..new_offset {
1746                    let slot = (*block).slots.get_unchecked(i);
1747
1748                    if slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0 {
1749                        Block::destroy(block, offset);
1750                        break;
1751                    }
1752                }
1753            }
1754
1755            Steal::Success(())
1756        }
1757    }
1758
1759    /// Steals a batch of tasks, pushes them into a worker, and pops a task from that worker.
1760    ///
1761    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
1762    /// steal around half of the tasks in the queue, but also not more than some constant limit.
1763    ///
1764    /// # Examples
1765    ///
1766    /// ```
1767    /// use crossbeam_deque::{Injector, Steal, Worker};
1768    ///
1769    /// let q = Injector::new();
1770    /// q.push(1);
1771    /// q.push(2);
1772    /// q.push(3);
1773    /// q.push(4);
1774    ///
1775    /// let w = Worker::new_fifo();
1776    /// assert_eq!(q.steal_batch_and_pop(&w), Steal::Success(1));
1777    /// assert_eq!(w.pop(), Some(2));
1778    /// ```
1779    pub fn steal_batch_and_pop(&self, dest: &Worker<T>) -> Steal<T> {
1780        // TODO: we use `MAX_BATCH + 1` as the hard limit for Injecter as the performance is slightly
1781        // better, but we may change it in the future to be compatible with the same method in Stealer.
1782        self.steal_batch_with_limit_and_pop(dest, MAX_BATCH + 1)
1783    }
1784
1785    /// Steals no more than `limit` of tasks, pushes them into a worker, and pops a task from that worker.
1786    ///
1787    /// How many tasks exactly will be stolen is not specified. That said, this method will try to
1788    /// steal around half of the tasks in the queue, but also not more than the given limit.
1789    ///
1790    /// # Examples
1791    ///
1792    /// ```
1793    /// use crossbeam_deque::{Injector, Steal, Worker};
1794    ///
1795    /// let q = Injector::new();
1796    /// q.push(1);
1797    /// q.push(2);
1798    /// q.push(3);
1799    /// q.push(4);
1800    /// q.push(5);
1801    /// q.push(6);
1802    ///
1803    /// let w = Worker::new_fifo();
1804    /// assert_eq!(q.steal_batch_with_limit_and_pop(&w, 2), Steal::Success(1));
1805    /// assert_eq!(w.pop(), Some(2));
1806    /// assert_eq!(w.pop(), None);
1807    ///
1808    /// q.push(7);
1809    /// // Setting a large limit does not guarantee that all elements will be popped. In this case,
1810    /// // half of the elements are currently popped, but the number of popped elements is considered
1811    /// // an implementation detail that may be changed in the future.
1812    /// assert_eq!(q.steal_batch_with_limit_and_pop(&w, usize::MAX), Steal::Success(3));
1813    /// assert_eq!(w.pop(), Some(4));
1814    /// assert_eq!(w.pop(), Some(5));
1815    /// assert_eq!(w.pop(), None);
1816    /// ```
1817    pub fn steal_batch_with_limit_and_pop(&self, dest: &Worker<T>, limit: usize) -> Steal<T> {
1818        assert!(limit > 0);
1819        let mut head;
1820        let mut block;
1821        let mut offset;
1822
1823        let backoff = Backoff::new();
1824        loop {
1825            head = self.head.index.load(Ordering::Acquire);
1826            block = self.head.block.load(Ordering::Acquire);
1827
1828            // Calculate the offset of the index into the block.
1829            offset = ((head >> SHIFT) % LAP) as usize;
1830
1831            // If we reached the end of the block, wait until the next one is installed.
1832            if offset == BLOCK_CAP {
1833                backoff.snooze();
1834            } else {
1835                break;
1836            }
1837        }
1838
1839        let mut new_head = head;
1840        let advance;
1841
1842        if new_head & HAS_NEXT == 0 {
1843            atomic::fence(Ordering::SeqCst);
1844            let tail = self.tail.index.load(Ordering::Relaxed);
1845
1846            // If the tail equals the head, that means the queue is empty.
1847            if head >> SHIFT == tail >> SHIFT {
1848                return Steal::Empty;
1849            }
1850
1851            // If head and tail are not in the same block, set `HAS_NEXT` in head.
1852            if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP {
1853                new_head |= HAS_NEXT;
1854                // We can steal all tasks till the end of the block.
1855                advance = (BLOCK_CAP - offset).min(limit);
1856            } else {
1857                let len = ((tail - head) >> SHIFT) as usize;
1858                // Steal half of the available tasks.
1859                advance = ((len + 1) / 2).min(limit);
1860            }
1861        } else {
1862            // We can steal all tasks till the end of the block.
1863            advance = (BLOCK_CAP - offset).min(limit);
1864        }
1865
1866        new_head += (advance as Index) << SHIFT;
1867        let new_offset = offset + advance;
1868
1869        // Try moving the head index forward.
1870        if self
1871            .head
1872            .index
1873            .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire)
1874            .is_err()
1875        {
1876            return Steal::Retry;
1877        }
1878
1879        // Reserve capacity for the stolen batch.
1880        let batch_size = new_offset - offset - 1;
1881        dest.reserve(batch_size);
1882
1883        // Get the destination buffer and back index.
1884        let dest_buffer = dest.buffer.get();
1885        let dest_b = dest.inner.back.load(Ordering::Relaxed);
1886
1887        unsafe {
1888            // If we've reached the end of the block, move to the next one.
1889            if new_offset == BLOCK_CAP {
1890                let next = (*block).wait_next();
1891                let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT);
1892                if !(*next).next.load(Ordering::Relaxed).is_null() {
1893                    next_index |= HAS_NEXT;
1894                }
1895
1896                self.head.block.store(next, Ordering::Release);
1897                self.head.index.store(next_index, Ordering::Release);
1898            }
1899
1900            // Read the task.
1901            let slot = (*block).slots.get_unchecked(offset);
1902            slot.wait_write();
1903            let task = slot.task.get().read();
1904
1905            match dest.flavor {
1906                Flavor::Fifo => {
1907                    // Copy values from the injector into the destination queue.
1908                    for i in 0..batch_size {
1909                        // Read the task.
1910                        let slot = (*block).slots.get_unchecked(offset + i + 1);
1911                        slot.wait_write();
1912                        let task = slot.task.get().read();
1913
1914                        // Write it into the destination queue.
1915                        dest_buffer.write(dest_b.wrapping_add(i as WorkerIndex), task);
1916                    }
1917                }
1918
1919                Flavor::Lifo => {
1920                    // Copy values from the injector into the destination queue.
1921                    for i in 0..batch_size {
1922                        // Read the task.
1923                        let slot = (*block).slots.get_unchecked(offset + i + 1);
1924                        slot.wait_write();
1925                        let task = slot.task.get().read();
1926
1927                        // Write it into the destination queue.
1928                        dest_buffer.write(
1929                            dest_b.wrapping_add((batch_size - 1 - i) as WorkerIndex),
1930                            task,
1931                        );
1932                    }
1933                }
1934            }
1935
1936            // ThreadSanitizer does not understand fences, so we omit fence and do store with Release ordering.
1937            #[cfg(not(crossbeam_sanitize_thread))]
1938            atomic::fence(Ordering::Release);
1939            let store_order = if cfg!(crossbeam_sanitize_thread) {
1940                Ordering::Release
1941            } else {
1942                Ordering::Relaxed
1943            };
1944
1945            // Update the back index in the destination queue.
1946            dest.inner
1947                .back
1948                .store(dest_b.wrapping_add(batch_size as WorkerIndex), store_order);
1949
1950            // Destroy the block if we've reached the end, or if another thread wanted to destroy
1951            // but couldn't because we were busy reading from the slot.
1952            if new_offset == BLOCK_CAP {
1953                Block::destroy(block, offset);
1954            } else {
1955                for i in offset..new_offset {
1956                    let slot = (*block).slots.get_unchecked(i);
1957
1958                    if slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0 {
1959                        Block::destroy(block, offset);
1960                        break;
1961                    }
1962                }
1963            }
1964
1965            Steal::Success(task.assume_init())
1966        }
1967    }
1968
1969    /// Returns `true` if the queue is empty.
1970    ///
1971    /// # Examples
1972    ///
1973    /// ```
1974    /// use crossbeam_deque::Injector;
1975    ///
1976    /// let q = Injector::new();
1977    ///
1978    /// assert!(q.is_empty());
1979    /// q.push(1);
1980    /// assert!(!q.is_empty());
1981    /// ```
1982    pub fn is_empty(&self) -> bool {
1983        let head = self.head.index.load(Ordering::SeqCst);
1984        let tail = self.tail.index.load(Ordering::SeqCst);
1985        head >> SHIFT == tail >> SHIFT
1986    }
1987
1988    /// Returns the number of tasks in the queue.
1989    ///
1990    /// # Examples
1991    ///
1992    /// ```
1993    /// use crossbeam_deque::Injector;
1994    ///
1995    /// let q = Injector::new();
1996    ///
1997    /// assert_eq!(q.len(), 0);
1998    /// q.push(1);
1999    /// assert_eq!(q.len(), 1);
2000    /// q.push(1);
2001    /// assert_eq!(q.len(), 2);
2002    /// ```
2003    pub fn len(&self) -> usize {
2004        loop {
2005            // Load the tail index, then load the head index.
2006            let mut tail = self.tail.index.load(Ordering::SeqCst);
2007            let mut head = self.head.index.load(Ordering::SeqCst);
2008
2009            // If the tail index didn't change, we've got consistent indices to work with.
2010            if self.tail.index.load(Ordering::SeqCst) == tail {
2011                // Erase the lower bits.
2012                tail &= !((1 << SHIFT) - 1);
2013                head &= !((1 << SHIFT) - 1);
2014
2015                // Fix up indices if they fall onto block ends.
2016                if (tail >> SHIFT) & (LAP - 1) == LAP - 1 {
2017                    tail = tail.wrapping_add(1 << SHIFT);
2018                }
2019                if (head >> SHIFT) & (LAP - 1) == LAP - 1 {
2020                    head = head.wrapping_add(1 << SHIFT);
2021                }
2022
2023                // Rotate indices so that head falls into the first block.
2024                let lap = (head >> SHIFT) / LAP;
2025                tail = tail.wrapping_sub((lap * LAP) << SHIFT);
2026                head = head.wrapping_sub((lap * LAP) << SHIFT);
2027
2028                // Remove the lower bits.
2029                tail >>= SHIFT;
2030                head >>= SHIFT;
2031
2032                // Return the difference minus the number of blocks between tail and head.
2033                return (tail - head - tail / LAP) as usize;
2034            }
2035        }
2036    }
2037}
2038
2039impl<T> Drop for Injector<T> {
2040    fn drop(&mut self) {
2041        let mut head = *self.head.index.get_mut();
2042        let mut tail = *self.tail.index.get_mut();
2043        let mut block = *self.head.block.get_mut();
2044
2045        // Erase the lower bits.
2046        head &= !((1 << SHIFT) - 1);
2047        tail &= !((1 << SHIFT) - 1);
2048
2049        unsafe {
2050            // Drop all values between `head` and `tail` and deallocate the heap-allocated blocks.
2051            while head != tail {
2052                let offset = ((head >> SHIFT) % LAP) as usize;
2053
2054                if offset < BLOCK_CAP {
2055                    // Drop the task in the slot.
2056                    let slot = (*block).slots.get_unchecked(offset);
2057                    (*slot.task.get()).assume_init_drop();
2058                } else {
2059                    // Deallocate the block and move to the next one.
2060                    let next = *(*block).next.get_mut();
2061                    drop(Box::from_raw(block));
2062                    block = next;
2063                }
2064
2065                head = head.wrapping_add(1 << SHIFT);
2066            }
2067
2068            // Deallocate the last remaining block.
2069            drop(Box::from_raw(block));
2070        }
2071    }
2072}
2073
2074impl<T> fmt::Debug for Injector<T> {
2075    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2076        f.pad("Injector { .. }")
2077    }
2078}
2079
2080/// Possible outcomes of a steal operation.
2081///
2082/// # Examples
2083///
2084/// There are lots of ways to chain results of steal operations together:
2085///
2086/// ```
2087/// use crossbeam_deque::Steal::{self, Empty, Retry, Success};
2088///
2089/// let collect = |v: Vec<Steal<i32>>| v.into_iter().collect::<Steal<i32>>();
2090///
2091/// assert_eq!(collect(vec![Empty, Empty, Empty]), Empty);
2092/// assert_eq!(collect(vec![Empty, Retry, Empty]), Retry);
2093/// assert_eq!(collect(vec![Retry, Success(1), Empty]), Success(1));
2094///
2095/// assert_eq!(collect(vec![Empty, Empty]).or_else(|| Retry), Retry);
2096/// assert_eq!(collect(vec![Retry, Empty]).or_else(|| Success(1)), Success(1));
2097/// ```
2098#[must_use]
2099#[derive(PartialEq, Eq, Copy, Clone)]
2100pub enum Steal<T> {
2101    /// The queue was empty at the time of stealing.
2102    Empty,
2103
2104    /// At least one task was successfully stolen.
2105    Success(T),
2106
2107    /// The steal operation needs to be retried.
2108    Retry,
2109}
2110
2111impl<T> Steal<T> {
2112    /// Returns `true` if the queue was empty at the time of stealing.
2113    ///
2114    /// # Examples
2115    ///
2116    /// ```
2117    /// use crossbeam_deque::Steal::{Empty, Retry, Success};
2118    ///
2119    /// assert!(!Success(7).is_empty());
2120    /// assert!(!Retry::<i32>.is_empty());
2121    ///
2122    /// assert!(Empty::<i32>.is_empty());
2123    /// ```
2124    pub fn is_empty(&self) -> bool {
2125        match self {
2126            Steal::Empty => true,
2127            _ => false,
2128        }
2129    }
2130
2131    /// Returns `true` if at least one task was stolen.
2132    ///
2133    /// # Examples
2134    ///
2135    /// ```
2136    /// use crossbeam_deque::Steal::{Empty, Retry, Success};
2137    ///
2138    /// assert!(!Empty::<i32>.is_success());
2139    /// assert!(!Retry::<i32>.is_success());
2140    ///
2141    /// assert!(Success(7).is_success());
2142    /// ```
2143    pub fn is_success(&self) -> bool {
2144        match self {
2145            Steal::Success(_) => true,
2146            _ => false,
2147        }
2148    }
2149
2150    /// Returns `true` if the steal operation needs to be retried.
2151    ///
2152    /// # Examples
2153    ///
2154    /// ```
2155    /// use crossbeam_deque::Steal::{Empty, Retry, Success};
2156    ///
2157    /// assert!(!Empty::<i32>.is_retry());
2158    /// assert!(!Success(7).is_retry());
2159    ///
2160    /// assert!(Retry::<i32>.is_retry());
2161    /// ```
2162    pub fn is_retry(&self) -> bool {
2163        match self {
2164            Steal::Retry => true,
2165            _ => false,
2166        }
2167    }
2168
2169    /// Returns the result of the operation, if successful.
2170    ///
2171    /// # Examples
2172    ///
2173    /// ```
2174    /// use crossbeam_deque::Steal::{Empty, Retry, Success};
2175    ///
2176    /// assert_eq!(Empty::<i32>.success(), None);
2177    /// assert_eq!(Retry::<i32>.success(), None);
2178    ///
2179    /// assert_eq!(Success(7).success(), Some(7));
2180    /// ```
2181    pub fn success(self) -> Option<T> {
2182        match self {
2183            Steal::Success(res) => Some(res),
2184            _ => None,
2185        }
2186    }
2187
2188    /// If no task was stolen, attempts another steal operation.
2189    ///
2190    /// Returns this steal result if it is `Success`. Otherwise, closure `f` is invoked and then:
2191    ///
2192    /// * If the second steal resulted in `Success`, it is returned.
2193    /// * If both steals were unsuccessful but any resulted in `Retry`, then `Retry` is returned.
2194    /// * If both resulted in `None`, then `None` is returned.
2195    ///
2196    /// # Examples
2197    ///
2198    /// ```
2199    /// use crossbeam_deque::Steal::{Empty, Retry, Success};
2200    ///
2201    /// assert_eq!(Success(1).or_else(|| Success(2)), Success(1));
2202    /// assert_eq!(Retry.or_else(|| Success(2)), Success(2));
2203    ///
2204    /// assert_eq!(Retry.or_else(|| Empty), Retry::<i32>);
2205    /// assert_eq!(Empty.or_else(|| Retry), Retry::<i32>);
2206    ///
2207    /// assert_eq!(Empty.or_else(|| Empty), Empty::<i32>);
2208    /// ```
2209    pub fn or_else<F>(self, f: F) -> Steal<T>
2210    where
2211        F: FnOnce() -> Steal<T>,
2212    {
2213        match self {
2214            Steal::Empty => f(),
2215            Steal::Success(_) => self,
2216            Steal::Retry => {
2217                if let Steal::Success(res) = f() {
2218                    Steal::Success(res)
2219                } else {
2220                    Steal::Retry
2221                }
2222            }
2223        }
2224    }
2225}
2226
2227impl<T> fmt::Debug for Steal<T> {
2228    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2229        match self {
2230            Steal::Empty => f.pad("Empty"),
2231            Steal::Success(_) => f.pad("Success(..)"),
2232            Steal::Retry => f.pad("Retry"),
2233        }
2234    }
2235}
2236
2237impl<T> FromIterator<Steal<T>> for Steal<T> {
2238    /// Consumes items until a `Success` is found and returns it.
2239    ///
2240    /// If no `Success` was found, but there was at least one `Retry`, then returns `Retry`.
2241    /// Otherwise, `Empty` is returned.
2242    fn from_iter<I>(iter: I) -> Steal<T>
2243    where
2244        I: IntoIterator<Item = Steal<T>>,
2245    {
2246        let mut retry = false;
2247        for s in iter {
2248            match &s {
2249                Steal::Empty => {}
2250                Steal::Success(_) => return s,
2251                Steal::Retry => retry = true,
2252            }
2253        }
2254
2255        if retry {
2256            Steal::Retry
2257        } else {
2258            Steal::Empty
2259        }
2260    }
2261}