Coverage Report

Created: 2026-08-14 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/crossbeam-deque-0.8.7/src/deque.rs
Line
Count
Source
1
use std::alloc::{alloc_zeroed, handle_alloc_error, Layout};
2
use std::boxed::Box;
3
use std::cell::{Cell, UnsafeCell};
4
use std::cmp;
5
use std::fmt;
6
use std::marker::PhantomData;
7
use std::mem::{self, MaybeUninit};
8
use std::ptr;
9
use std::sync::atomic::{self, AtomicIsize, AtomicPtr, AtomicUsize, Ordering};
10
use std::sync::Arc;
11
12
use crossbeam_epoch::{self as epoch, Atomic, Owned};
13
use crossbeam_utils::{Backoff, CachePadded};
14
15
// Minimum buffer capacity.
16
const MIN_CAP: usize = 64;
17
// Maximum number of tasks that can be stolen in `steal_batch()` and `steal_batch_and_pop()`.
18
const 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.
21
const 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.
27
struct 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
35
unsafe impl<T> Send for Buffer<T> {}
36
37
impl<T> Buffer<T> {
38
    /// Allocates a new buffer with the specified capacity.
39
0
    fn alloc(cap: usize) -> Buffer<T> {
40
0
        debug_assert_eq!(cap, cap.next_power_of_two());
41
42
0
        let ptr = Box::into_raw(
43
0
            (0..cap)
44
0
                .map(|_| MaybeUninit::<T>::uninit())
45
0
                .collect::<Box<[_]>>(),
46
        )
47
0
        .cast::<T>();
48
49
0
        Buffer { ptr, cap }
50
0
    }
51
52
    /// Deallocates the buffer.
53
0
    unsafe fn dealloc(self) {
54
0
        drop(Box::from_raw(ptr::slice_from_raw_parts_mut(
55
0
            self.ptr.cast::<MaybeUninit<T>>(),
56
0
            self.cap,
57
        )));
58
0
    }
59
60
    /// Returns a pointer to the task at the specified `index`.
61
0
    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
0
        self.ptr.offset(index & (self.cap - 1) as isize)
66
0
    }
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
0
    unsafe fn write(&self, index: isize, task: MaybeUninit<T>) {
75
0
        ptr::write_volatile(self.at(index).cast::<MaybeUninit<T>>(), task)
76
0
    }
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
0
    unsafe fn read(&self, index: isize) -> MaybeUninit<T> {
85
0
        ptr::read_volatile(self.at(index).cast::<MaybeUninit<T>>())
86
0
    }
87
}
88
89
impl<T> Clone for Buffer<T> {
90
    fn clone(&self) -> Buffer<T> {
91
        *self
92
    }
93
}
94
95
impl<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
110
struct 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
121
impl<T> Drop for Inner<T> {
122
0
    fn drop(&mut self) {
123
        // Load the back index, front index, and buffer.
124
0
        let b = *self.back.get_mut();
125
0
        let f = *self.front.get_mut();
126
127
        unsafe {
128
0
            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
0
            let mut i = f;
132
0
            while i != b {
133
0
                buffer.deref().at(i).drop_in_place();
134
0
                i = i.wrapping_add(1);
135
0
            }
136
137
            // Free the memory allocated by the buffer.
138
0
            buffer.into_owned().into_box().dealloc();
139
        }
140
0
    }
141
}
142
143
/// Worker queue flavor: FIFO or LIFO.
144
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
145
enum 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
/// ```
193
pub 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
207
unsafe impl<T: Send> Send for Worker<T> {}
208
209
impl<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
0
    pub fn new_fifo() -> Worker<T> {
222
0
        let buffer = Buffer::alloc(MIN_CAP);
223
224
0
        let inner = Arc::new(CachePadded::new(Inner {
225
0
            front: AtomicIsize::new(0),
226
0
            back: AtomicIsize::new(0),
227
0
            buffer: CachePadded::new(Atomic::new(buffer)),
228
0
        }));
229
230
0
        Worker {
231
0
            inner,
232
0
            buffer: Cell::new(buffer),
233
0
            flavor: Flavor::Fifo,
234
0
            _marker: PhantomData,
235
0
        }
236
0
    }
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
0
    pub fn new_lifo() -> Worker<T> {
250
0
        let buffer = Buffer::alloc(MIN_CAP);
251
252
0
        let inner = Arc::new(CachePadded::new(Inner {
253
0
            front: AtomicIsize::new(0),
254
0
            back: AtomicIsize::new(0),
255
0
            buffer: CachePadded::new(Atomic::new(buffer)),
256
0
        }));
257
258
0
        Worker {
259
0
            inner,
260
0
            buffer: Cell::new(buffer),
261
0
            flavor: Flavor::Lifo,
262
0
            _marker: PhantomData,
263
0
        }
264
0
    }
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
0
    pub fn stealer(&self) -> Stealer<T> {
279
0
        Stealer {
280
0
            inner: self.inner.clone(),
281
0
            flavor: self.flavor,
282
0
        }
283
0
    }
284
285
    /// Resizes the internal buffer to the new capacity of `new_cap`.
286
    #[cold]
287
0
    unsafe fn resize(&self, new_cap: usize) {
288
        // Load the back index, front index, and buffer.
289
0
        let b = self.inner.back.load(Ordering::Relaxed);
290
0
        let f = self.inner.front.load(Ordering::Relaxed);
291
0
        let buffer = self.buffer.get();
292
293
        // Allocate a new buffer and copy data from the old buffer to the new one.
294
0
        let new = Buffer::alloc(new_cap);
295
0
        let mut i = f;
296
0
        while i != b {
297
0
            ptr::copy_nonoverlapping(buffer.at(i), new.at(i), 1);
298
0
            i = i.wrapping_add(1);
299
0
        }
300
301
0
        let guard = &epoch::pin();
302
303
        // Replace the old buffer with the new one.
304
0
        self.buffer.replace(new);
305
0
        let old =
306
0
            self.inner
307
0
                .buffer
308
0
                .swap(Owned::new(new).into_shared(guard), Ordering::Release, guard);
309
310
        // Destroy the old buffer later.
311
0
        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
0
        if mem::size_of::<T>() * new_cap >= FLUSH_THRESHOLD_BYTES {
316
0
            guard.flush();
317
0
        }
318
0
    }
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
0
    pub fn is_empty(&self) -> bool {
360
0
        let b = self.inner.back.load(Ordering::Relaxed);
361
0
        let f = self.inner.front.load(Ordering::SeqCst);
362
0
        b.wrapping_sub(f) <= 0
363
0
    }
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
0
    pub fn push(&self, task: T) {
396
        // Load the back index, front index, and buffer.
397
0
        let b = self.inner.back.load(Ordering::Relaxed);
398
0
        let f = self.inner.front.load(Ordering::Acquire);
399
0
        let mut buffer = self.buffer.get();
400
401
        // Calculate the length of the queue.
402
0
        let len = b.wrapping_sub(f);
403
404
        // Is the queue full?
405
0
        if len >= buffer.cap as isize {
406
0
            // Yes. Grow the underlying buffer.
407
0
            unsafe {
408
0
                self.resize(2 * buffer.cap);
409
0
            }
410
0
            buffer = self.buffer.get();
411
0
        }
412
413
        // Write `task` into the slot.
414
0
        unsafe {
415
0
            buffer.write(b, MaybeUninit::new(task));
416
0
        }
417
418
        // ThreadSanitizer does not understand fences, so we omit fence and do store with Release ordering.
419
        #[cfg(not(crossbeam_sanitize_thread))]
420
0
        atomic::fence(Ordering::Release);
421
0
        let store_order = if cfg!(crossbeam_sanitize_thread) {
422
0
            Ordering::Release
423
        } else {
424
0
            Ordering::Relaxed
425
        };
426
427
        // Increment the back index.
428
0
        self.inner.back.store(b.wrapping_add(1), store_order);
429
0
    }
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
0
    pub fn pop(&self) -> Option<T> {
447
        // Load the back and front index.
448
0
        let b = self.inner.back.load(Ordering::Relaxed);
449
0
        let f = self.inner.front.load(Ordering::Relaxed);
450
451
        // Calculate the length of the queue.
452
0
        let len = b.wrapping_sub(f);
453
454
        // Is the queue empty?
455
0
        if len <= 0 {
456
0
            return None;
457
0
        }
458
459
0
        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
0
                let f = self.inner.front.fetch_add(1, Ordering::SeqCst);
464
0
                let new_f = f.wrapping_add(1);
465
466
0
                if b.wrapping_sub(new_f) < 0 {
467
0
                    self.inner.front.store(f, Ordering::Relaxed);
468
0
                    return None;
469
0
                }
470
471
                unsafe {
472
                    // Read the popped task.
473
0
                    let buffer = self.buffer.get();
474
0
                    let task = buffer.read(f).assume_init();
475
476
                    // Shrink the buffer if `len - 1` is less than one fourth of the capacity.
477
0
                    if buffer.cap > MIN_CAP && len <= buffer.cap as isize / 4 {
478
0
                        self.resize(buffer.cap / 2);
479
0
                    }
480
481
0
                    Some(task)
482
                }
483
            }
484
485
            // Pop from the back of the queue.
486
            Flavor::Lifo => {
487
                // Decrement the back index.
488
0
                let b = b.wrapping_sub(1);
489
0
                self.inner.back.store(b, Ordering::Relaxed);
490
491
0
                atomic::fence(Ordering::SeqCst);
492
493
                // Load the front index.
494
0
                let f = self.inner.front.load(Ordering::Relaxed);
495
496
                // Compute the length after the back index was decremented.
497
0
                let len = b.wrapping_sub(f);
498
499
0
                if len < 0 {
500
                    // The queue is empty. Restore the back index to the original task.
501
0
                    self.inner.back.store(b.wrapping_add(1), Ordering::Relaxed);
502
0
                    None
503
                } else {
504
                    // Read the task to be popped.
505
0
                    let buffer = self.buffer.get();
506
0
                    let mut task = unsafe { Some(buffer.read(b)) };
507
508
                    // Are we popping the last task from the queue?
509
0
                    if len == 0 {
510
                        // Try incrementing the front index.
511
0
                        if self
512
0
                            .inner
513
0
                            .front
514
0
                            .compare_exchange(
515
0
                                f,
516
0
                                f.wrapping_add(1),
517
0
                                Ordering::SeqCst,
518
0
                                Ordering::Relaxed,
519
0
                            )
520
0
                            .is_err()
521
0
                        {
522
0
                            // Failed. We didn't pop anything. Reset to `None`.
523
0
                            task.take();
524
0
                        }
525
526
                        // Restore the back index to the original task.
527
0
                        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
0
                        if buffer.cap > MIN_CAP && len < buffer.cap as isize / 4 {
531
0
                            unsafe {
532
0
                                self.resize(buffer.cap / 2);
533
0
                            }
534
0
                        }
535
                    }
536
537
0
                    task.map(|t| unsafe { t.assume_init() })
538
                }
539
            }
540
        }
541
0
    }
542
}
543
544
impl<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
/// ```
570
pub 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
578
unsafe impl<T: Send> Send for Stealer<T> {}
579
unsafe impl<T: Send> Sync for Stealer<T> {}
580
581
impl<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
0
    pub fn is_empty(&self) -> bool {
595
0
        let f = self.inner.front.load(Ordering::Acquire);
596
0
        atomic::fence(Ordering::SeqCst);
597
0
        let b = self.inner.back.load(Ordering::Acquire);
598
0
        b.wrapping_sub(f) <= 0
599
0
    }
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
0
    pub fn steal(&self) -> Steal<T> {
638
        // Load the front index.
639
0
        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
0
        if epoch::is_pinned() {
647
0
            atomic::fence(Ordering::SeqCst);
648
0
        }
649
650
0
        let guard = &epoch::pin();
651
652
        // Load the back index.
653
0
        let b = self.inner.back.load(Ordering::Acquire);
654
655
        // Is the queue empty?
656
0
        if b.wrapping_sub(f) <= 0 {
657
0
            return Steal::Empty;
658
0
        }
659
660
        // Load the buffer and read the task at the front.
661
0
        let buffer = self.inner.buffer.load(Ordering::Acquire, guard);
662
0
        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
0
        if self.inner.buffer.load(Ordering::Acquire, guard) != buffer
667
0
            || self
668
0
                .inner
669
0
                .front
670
0
                .compare_exchange(f, f.wrapping_add(1), Ordering::SeqCst, Ordering::Relaxed)
671
0
                .is_err()
672
        {
673
            // We didn't steal this task, forget it.
674
0
            return Steal::Retry;
675
0
        }
676
677
        // Return the stolen task.
678
0
        Steal::Success(unsafe { task.assume_init() })
679
0
    }
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
1177
impl<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
1186
impl<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.
1196
const WRITE: usize = 1;
1197
const READ: usize = 2;
1198
const DESTROY: usize = 4;
1199
1200
// Each block covers one "lap" of indices.
1201
const LAP: usize = 64;
1202
// The maximum number of values a block can hold.
1203
const BLOCK_CAP: usize = LAP - 1;
1204
// How many lower bits are reserved for metadata.
1205
const SHIFT: usize = 1;
1206
// Indicates that the block is not the last one.
1207
const HAS_NEXT: usize = 1;
1208
1209
/// A slot in a block.
1210
struct Slot<T> {
1211
    /// The task.
1212
    task: UnsafeCell<MaybeUninit<T>>,
1213
1214
    /// The state of the slot.
1215
    state: AtomicUsize,
1216
}
1217
1218
impl<T> Slot<T> {
1219
    /// Waits until a task is written into the slot.
1220
0
    fn wait_write(&self) {
1221
0
        let backoff = Backoff::new();
1222
0
        while self.state.load(Ordering::Acquire) & WRITE == 0 {
1223
0
            backoff.snooze();
1224
0
        }
1225
0
    }
1226
}
1227
1228
/// A block in a linked list.
1229
///
1230
/// Each block in the list can hold up to `BLOCK_CAP` values.
1231
struct 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
1239
impl<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
0
    fn new() -> Box<Self> {
1251
        // SAFETY: layout is not zero-sized
1252
0
        let ptr = unsafe { alloc_zeroed(Self::LAYOUT) };
1253
        // Handle allocation failure
1254
0
        if ptr.is_null() {
1255
0
            handle_alloc_error(Self::LAYOUT)
1256
0
        }
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
0
        unsafe { Box::from_raw(ptr.cast()) }
1265
0
    }
1266
1267
    /// Waits until the next pointer is set.
1268
0
    fn wait_next(&self) -> *mut Block<T> {
1269
0
        let backoff = Backoff::new();
1270
        loop {
1271
0
            let next = self.next.load(Ordering::Acquire);
1272
0
            if !next.is_null() {
1273
0
                return next;
1274
0
            }
1275
0
            backoff.snooze();
1276
        }
1277
0
    }
1278
1279
    /// Sets the `DESTROY` bit in slots starting from `start` and destroys the block.
1280
0
    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
0
        for i in (0..count).rev() {
1284
0
            let slot = (*this).slots.get_unchecked(i);
1285
1286
            // Mark the `DESTROY` bit if a thread is still using the slot.
1287
0
            if slot.state.load(Ordering::Acquire) & READ == 0
1288
0
                && 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
0
                return;
1292
0
            }
1293
        }
1294
1295
        // No thread is using the block, now it is safe to destroy it.
1296
0
        drop(Box::from_raw(this));
1297
0
    }
1298
}
1299
1300
/// A position in a queue.
1301
struct 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
/// ```
1327
pub 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
1338
unsafe impl<T: Send> Send for Injector<T> {}
1339
unsafe impl<T: Send> Sync for Injector<T> {}
1340
1341
impl<T> Default for Injector<T> {
1342
0
    fn default() -> Self {
1343
0
        let block = Box::into_raw(Block::<T>::new());
1344
0
        Self {
1345
0
            head: CachePadded::new(Position {
1346
0
                block: AtomicPtr::new(block),
1347
0
                index: AtomicUsize::new(0),
1348
0
            }),
1349
0
            tail: CachePadded::new(Position {
1350
0
                block: AtomicPtr::new(block),
1351
0
                index: AtomicUsize::new(0),
1352
0
            }),
1353
0
            _marker: PhantomData,
1354
0
        }
1355
0
    }
1356
}
1357
1358
impl<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
0
    pub fn new() -> Injector<T> {
1369
0
        Self::default()
1370
0
    }
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
0
    pub fn push(&self, task: T) {
1384
0
        let backoff = Backoff::new();
1385
0
        let mut tail = self.tail.index.load(Ordering::Acquire);
1386
0
        let mut block = self.tail.block.load(Ordering::Acquire);
1387
0
        let mut next_block = None;
1388
1389
        loop {
1390
            // Calculate the offset of the index into the block.
1391
0
            let offset = (tail >> SHIFT) % LAP;
1392
1393
            // If we reached the end of the block, wait until the next one is installed.
1394
0
            if offset == BLOCK_CAP {
1395
0
                backoff.snooze();
1396
0
                tail = self.tail.index.load(Ordering::Acquire);
1397
0
                block = self.tail.block.load(Ordering::Acquire);
1398
0
                continue;
1399
0
            }
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
0
            if offset + 1 == BLOCK_CAP && next_block.is_none() {
1404
0
                next_block = Some(Block::<T>::new());
1405
0
            }
1406
1407
0
            let new_tail = tail + (1 << SHIFT);
1408
1409
            // Try advancing the tail forward.
1410
0
            match self.tail.index.compare_exchange_weak(
1411
0
                tail,
1412
0
                new_tail,
1413
0
                Ordering::SeqCst,
1414
0
                Ordering::Acquire,
1415
0
            ) {
1416
                Ok(_) => unsafe {
1417
                    // If we've reached the end of the block, install the next one.
1418
0
                    if offset + 1 == BLOCK_CAP {
1419
0
                        let next_block = Box::into_raw(next_block.unwrap());
1420
0
                        let next_index = new_tail.wrapping_add(1 << SHIFT);
1421
0
1422
0
                        self.tail.block.store(next_block, Ordering::Release);
1423
0
                        self.tail.index.store(next_index, Ordering::Release);
1424
0
                        (*block).next.store(next_block, Ordering::Release);
1425
0
                    }
1426
1427
                    // Write the task into the slot.
1428
0
                    let slot = (*block).slots.get_unchecked(offset);
1429
0
                    slot.task.get().write(MaybeUninit::new(task));
1430
0
                    slot.state.fetch_or(WRITE, Ordering::Release);
1431
1432
0
                    return;
1433
                },
1434
0
                Err(t) => {
1435
0
                    tail = t;
1436
0
                    block = self.tail.block.load(Ordering::Acquire);
1437
0
                    backoff.spin();
1438
0
                }
1439
            }
1440
        }
1441
0
    }
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
0
    pub fn steal(&self) -> Steal<T> {
1459
        let mut head;
1460
        let mut block;
1461
        let mut offset;
1462
1463
0
        let backoff = Backoff::new();
1464
        loop {
1465
0
            head = self.head.index.load(Ordering::Acquire);
1466
0
            block = self.head.block.load(Ordering::Acquire);
1467
1468
            // Calculate the offset of the index into the block.
1469
0
            offset = (head >> SHIFT) % LAP;
1470
1471
            // If we reached the end of the block, wait until the next one is installed.
1472
0
            if offset == BLOCK_CAP {
1473
0
                backoff.snooze();
1474
0
            } else {
1475
0
                break;
1476
            }
1477
        }
1478
1479
0
        let mut new_head = head + (1 << SHIFT);
1480
1481
0
        if new_head & HAS_NEXT == 0 {
1482
0
            atomic::fence(Ordering::SeqCst);
1483
0
            let tail = self.tail.index.load(Ordering::Relaxed);
1484
1485
            // If the tail equals the head, that means the queue is empty.
1486
0
            if head >> SHIFT == tail >> SHIFT {
1487
0
                return Steal::Empty;
1488
0
            }
1489
1490
            // If head and tail are not in the same block, set `HAS_NEXT` in head.
1491
0
            if (head >> SHIFT) / LAP != (tail >> SHIFT) / LAP {
1492
0
                new_head |= HAS_NEXT;
1493
0
            }
1494
0
        }
1495
1496
        // Try moving the head index forward.
1497
0
        if self
1498
0
            .head
1499
0
            .index
1500
0
            .compare_exchange_weak(head, new_head, Ordering::SeqCst, Ordering::Acquire)
1501
0
            .is_err()
1502
        {
1503
0
            return Steal::Retry;
1504
0
        }
1505
1506
        unsafe {
1507
            // If we've reached the end of the block, move to the next one.
1508
0
            if offset + 1 == BLOCK_CAP {
1509
0
                let next = (*block).wait_next();
1510
0
                let mut next_index = (new_head & !HAS_NEXT).wrapping_add(1 << SHIFT);
1511
0
                if !(*next).next.load(Ordering::Relaxed).is_null() {
1512
0
                    next_index |= HAS_NEXT;
1513
0
                }
1514
1515
0
                self.head.block.store(next, Ordering::Release);
1516
0
                self.head.index.store(next_index, Ordering::Release);
1517
0
            }
1518
1519
            // Read the task.
1520
0
            let slot = (*block).slots.get_unchecked(offset);
1521
0
            slot.wait_write();
1522
0
            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
0
            if (offset + 1 == BLOCK_CAP)
1527
0
                || (slot.state.fetch_or(READ, Ordering::AcqRel) & DESTROY != 0)
1528
0
            {
1529
0
                Block::destroy(block, offset);
1530
0
            }
1531
1532
0
            Steal::Success(task)
1533
        }
1534
0
    }
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
0
    pub fn is_empty(&self) -> bool {
1958
0
        let head = self.head.index.load(Ordering::SeqCst);
1959
0
        let tail = self.tail.index.load(Ordering::SeqCst);
1960
0
        head >> SHIFT == tail >> SHIFT
1961
0
    }
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
2014
impl<T> Drop for Injector<T> {
2015
0
    fn drop(&mut self) {
2016
0
        let mut head = *self.head.index.get_mut();
2017
0
        let mut tail = *self.tail.index.get_mut();
2018
0
        let mut block = *self.head.block.get_mut();
2019
2020
        // Erase the lower bits.
2021
0
        head &= !((1 << SHIFT) - 1);
2022
0
        tail &= !((1 << SHIFT) - 1);
2023
2024
        unsafe {
2025
            // Drop all values between `head` and `tail` and deallocate the heap-allocated blocks.
2026
0
            while head != tail {
2027
0
                let offset = (head >> SHIFT) % LAP;
2028
2029
0
                if offset < BLOCK_CAP {
2030
0
                    // Drop the task in the slot.
2031
0
                    let slot = (*block).slots.get_unchecked(offset);
2032
0
                    (*slot.task.get()).assume_init_drop();
2033
0
                } else {
2034
0
                    // Deallocate the block and move to the next one.
2035
0
                    let next = *(*block).next.get_mut();
2036
0
                    drop(Box::from_raw(block));
2037
0
                    block = next;
2038
0
                }
2039
2040
0
                head = head.wrapping_add(1 << SHIFT);
2041
            }
2042
2043
            // Deallocate the last remaining block.
2044
0
            drop(Box::from_raw(block));
2045
        }
2046
0
    }
2047
}
2048
2049
impl<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)]
2075
pub 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
2086
impl<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
2202
impl<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
2212
impl<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
}