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