Coverage Report

Created: 2021-01-22 16:54

crossbeam-utils/src/backoff.rs
Line
Count
Source
1
use crate::primitive::sync::atomic;
2
use core::cell::Cell;
3
use core::fmt;
4
5
const SPIN_LIMIT: u32 = 6;
6
const YIELD_LIMIT: u32 = 10;
7
8
/// Performs exponential backoff in spin loops.
9
///
10
/// Backing off in spin loops reduces contention and improves overall performance.
11
///
12
/// This primitive can execute *YIELD* and *PAUSE* instructions, yield the current thread to the OS
13
/// scheduler, and tell when is a good time to block the thread using a different synchronization
14
/// mechanism. Each step of the back off procedure takes roughly twice as long as the previous
15
/// step.
16
///
17
/// # Examples
18
///
19
/// Backing off in a lock-free loop:
20
///
21
/// ```
22
/// use crossbeam_utils::Backoff;
23
/// use std::sync::atomic::AtomicUsize;
24
/// use std::sync::atomic::Ordering::SeqCst;
25
///
26
/// fn fetch_mul(a: &AtomicUsize, b: usize) -> usize {
27
///     let backoff = Backoff::new();
28
///     loop {
29
///         let val = a.load(SeqCst);
30
///         if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() {
31
///             return val;
32
///         }
33
///         backoff.spin();
34
///     }
35
/// }
36
/// ```
37
///
38
/// Waiting for an [`AtomicBool`] to become `true`:
39
///
40
/// ```
41
/// use crossbeam_utils::Backoff;
42
/// use std::sync::atomic::AtomicBool;
43
/// use std::sync::atomic::Ordering::SeqCst;
44
///
45
/// fn spin_wait(ready: &AtomicBool) {
46
///     let backoff = Backoff::new();
47
///     while !ready.load(SeqCst) {
48
///         backoff.snooze();
49
///     }
50
/// }
51
/// ```
52
///
53
/// Waiting for an [`AtomicBool`] to become `true` and parking the thread after a long wait.
54
/// Note that whoever sets the atomic variable to `true` must notify the parked thread by calling
55
/// [`unpark()`]:
56
///
57
/// ```
58
/// use crossbeam_utils::Backoff;
59
/// use std::sync::atomic::AtomicBool;
60
/// use std::sync::atomic::Ordering::SeqCst;
61
/// use std::thread;
62
///
63
/// fn blocking_wait(ready: &AtomicBool) {
64
///     let backoff = Backoff::new();
65
///     while !ready.load(SeqCst) {
66
///         if backoff.is_completed() {
67
///             thread::park();
68
///         } else {
69
///             backoff.snooze();
70
///         }
71
///     }
72
/// }
73
/// ```
74
///
75
/// [`is_completed`]: Backoff::is_completed
76
/// [`std::thread::park()`]: std::thread::park
77
/// [`Condvar`]: std::sync::Condvar
78
/// [`AtomicBool`]: std::sync::atomic::AtomicBool
79
/// [`unpark()`]: std::thread::Thread::unpark
80
pub struct Backoff {
81
    step: Cell<u32>,
82
}
83
84
impl Backoff {
85
    /// Creates a new `Backoff`.
86
    ///
87
    /// # Examples
88
    ///
89
    /// ```
90
    /// use crossbeam_utils::Backoff;
91
    ///
92
    /// let backoff = Backoff::new();
93
    /// ```
94
    #[inline]
95
117M
    pub fn new() -> Self {
96
117M
        Backoff { step: Cell::new(0) }
97
117M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
1.44M
    pub fn new() -> Self {
96
1.44M
        Backoff { step: Cell::new(0) }
97
1.44M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
1.61M
    pub fn new() -> Self {
96
1.61M
        Backoff { step: Cell::new(0) }
97
1.61M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
226k
    pub fn new() -> Self {
96
226k
        Backoff { step: Cell::new(0) }
97
226k
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
1.74M
    pub fn new() -> Self {
96
1.74M
        Backoff { step: Cell::new(0) }
97
1.74M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
25.6M
    pub fn new() -> Self {
96
25.6M
        Backoff { step: Cell::new(0) }
97
25.6M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
605k
    pub fn new() -> Self {
96
605k
        Backoff { step: Cell::new(0) }
97
605k
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
2.77M
    pub fn new() -> Self {
96
2.77M
        Backoff { step: Cell::new(0) }
97
2.77M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
201
    pub fn new() -> Self {
96
201
        Backoff { step: Cell::new(0) }
97
201
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
1
    pub fn new() -> Self {
96
1
        Backoff { step: Cell::new(0) }
97
1
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
5
    pub fn new() -> Self {
96
5
        Backoff { step: Cell::new(0) }
97
5
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
1
    pub fn new() -> Self {
96
1
        Backoff { step: Cell::new(0) }
97
1
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
1.39M
    pub fn new() -> Self {
96
1.39M
        Backoff { step: Cell::new(0) }
97
1.39M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
13
    pub fn new() -> Self {
96
13
        Backoff { step: Cell::new(0) }
97
13
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
6
    pub fn new() -> Self {
96
6
        Backoff { step: Cell::new(0) }
97
6
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
40
    pub fn new() -> Self {
96
40
        Backoff { step: Cell::new(0) }
97
40
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
2.84M
    pub fn new() -> Self {
96
2.84M
        Backoff { step: Cell::new(0) }
97
2.84M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
4.57M
    pub fn new() -> Self {
96
4.57M
        Backoff { step: Cell::new(0) }
97
4.57M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
73.5M
    pub fn new() -> Self {
96
73.5M
        Backoff { step: Cell::new(0) }
97
73.5M
    }
<crossbeam_utils::backoff::Backoff>::new
Line
Count
Source
95
726k
    pub fn new() -> Self {
96
726k
        Backoff { step: Cell::new(0) }
97
726k
    }
98
99
    /// Resets the `Backoff`.
100
    ///
101
    /// # Examples
102
    ///
103
    /// ```
104
    /// use crossbeam_utils::Backoff;
105
    ///
106
    /// let backoff = Backoff::new();
107
    /// backoff.reset();
108
    /// ```
109
    #[inline]
110
    pub fn reset(&self) {
111
        self.step.set(0);
112
    }
113
114
    /// Backs off in a lock-free loop.
115
    ///
116
    /// This method should be used when we need to retry an operation because another thread made
117
    /// progress.
118
    ///
119
    /// The processor may yield using the *YIELD* or *PAUSE* instruction.
120
    ///
121
    /// # Examples
122
    ///
123
    /// Backing off in a lock-free loop:
124
    ///
125
    /// ```
126
    /// use crossbeam_utils::Backoff;
127
    /// use std::sync::atomic::AtomicUsize;
128
    /// use std::sync::atomic::Ordering::SeqCst;
129
    ///
130
    /// fn fetch_mul(a: &AtomicUsize, b: usize) -> usize {
131
    ///     let backoff = Backoff::new();
132
    ///     loop {
133
    ///         let val = a.load(SeqCst);
134
    ///         if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() {
135
    ///             return val;
136
    ///         }
137
    ///         backoff.spin();
138
    ///     }
139
    /// }
140
    ///
141
    /// let a = AtomicUsize::new(7);
142
    /// assert_eq!(fetch_mul(&a, 8), 7);
143
    /// assert_eq!(a.load(SeqCst), 56);
144
    /// ```
145
    #[inline]
146
684k
    pub fn spin(&self) {
147
3.19M
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)684k
{
148
3.19M
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
3.19M
            // use [`core::hint::spin_loop`] instead.
150
3.19M
            #[allow(deprecated)]
151
3.19M
            atomic::spin_loop_hint();
152
3.19M
        }
153
154
696k
        if self.step.get() <= SPIN_LIMIT {
155
636k
            self.step.set(self.step.get() + 1);
156
636k
        }
59.5k
157
696k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
1.20k
    pub fn spin(&self) {
147
73.0k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)1.20k
{
148
73.0k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
73.0k
            // use [`core::hint::spin_loop`] instead.
150
73.0k
            #[allow(deprecated)]
151
73.0k
            atomic::spin_loop_hint();
152
73.0k
        }
153
154
1.20k
        if self.step.get() <= SPIN_LIMIT {
155
81
            self.step.set(self.step.get() + 1);
156
1.12k
        }
157
1.20k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
262
    pub fn spin(&self) {
147
262
        for _ in 0..1 << self.step.get().min(SPIN_LIMIT) {
148
262
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
262
            // use [`core::hint::spin_loop`] instead.
150
262
            #[allow(deprecated)]
151
262
            atomic::spin_loop_hint();
152
262
        }
153
154
262
        if self.step.get() <= SPIN_LIMIT {
155
262
            self.step.set(self.step.get() + 1);
156
262
        }
0
157
262
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
16.9k
    pub fn spin(&self) {
147
605k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)16.9k
{
148
605k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
605k
            // use [`core::hint::spin_loop`] instead.
150
605k
            #[allow(deprecated)]
151
605k
            atomic::spin_loop_hint();
152
605k
        }
153
154
17.0k
        if self.step.get() <= SPIN_LIMIT {
155
1.71k
            self.step.set(self.step.get() + 1);
156
15.3k
        }
157
17.0k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
34.0k
    pub fn spin(&self) {
147
35.1k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)34.0k
{
148
35.1k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
35.1k
            // use [`core::hint::spin_loop`] instead.
150
35.1k
            #[allow(deprecated)]
151
35.1k
            atomic::spin_loop_hint();
152
35.1k
        }
153
154
34.1k
        if self.step.get() <= SPIN_LIMIT {
155
34.1k
            self.step.set(self.step.get() + 1);
156
34.1k
        }
4
157
34.1k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
18.5k
    pub fn spin(&self) {
147
495k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)18.5k
{
148
495k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
495k
            // use [`core::hint::spin_loop`] instead.
150
495k
            #[allow(deprecated)]
151
495k
            atomic::spin_loop_hint();
152
495k
        }
153
154
18.5k
        if self.step.get() <= SPIN_LIMIT {
155
1.60k
            self.step.set(self.step.get() + 1);
156
16.9k
        }
157
18.5k
    }
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::spin
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
151k
    pub fn spin(&self) {
147
266k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)151k
{
148
266k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
266k
            // use [`core::hint::spin_loop`] instead.
150
266k
            #[allow(deprecated)]
151
266k
            atomic::spin_loop_hint();
152
266k
        }
153
154
152k
        if self.step.get() <= SPIN_LIMIT {
155
151k
            self.step.set(self.step.get() + 1);
156
151k
        }
883
157
152k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
1
    pub fn spin(&self) {
147
1
        for _ in 0..1 << self.step.get().min(SPIN_LIMIT) {
148
1
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
1
            // use [`core::hint::spin_loop`] instead.
150
1
            #[allow(deprecated)]
151
1
            atomic::spin_loop_hint();
152
1
        }
153
154
1
        if self.step.get() <= SPIN_LIMIT {
155
1
            self.step.set(self.step.get() + 1);
156
1
        }
0
157
1
    }
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::spin
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::spin
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::spin
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
86.8k
    pub fn spin(&self) {
147
269k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)86.8k
{
148
269k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
269k
            // use [`core::hint::spin_loop`] instead.
150
269k
            #[allow(deprecated)]
151
269k
            atomic::spin_loop_hint();
152
269k
        }
153
154
87.7k
        if self.step.get() <= SPIN_LIMIT {
155
86.2k
            self.step.set(self.step.get() + 1);
156
86.2k
        }
1.49k
157
87.7k
    }
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::spin
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::spin
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
37.9k
    pub fn spin(&self) {
147
992k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)37.9k
{
148
992k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
992k
            // use [`core::hint::spin_loop`] instead.
150
992k
            #[allow(deprecated)]
151
992k
            atomic::spin_loop_hint();
152
992k
        }
153
154
38.2k
        if self.step.get() <= SPIN_LIMIT {
155
17.3k
            self.step.set(self.step.get() + 1);
156
20.9k
        }
157
38.2k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
232k
    pub fn spin(&self) {
147
348k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)232k
{
148
348k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
348k
            // use [`core::hint::spin_loop`] instead.
150
348k
            #[allow(deprecated)]
151
348k
            atomic::spin_loop_hint();
152
348k
        }
153
154
241k
        if self.step.get() <= SPIN_LIMIT {
155
238k
            self.step.set(self.step.get() + 1);
156
238k
        }
2.77k
157
241k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
99.4k
    pub fn spin(&self) {
147
100k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)99.4k
{
148
100k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
100k
            // use [`core::hint::spin_loop`] instead.
150
100k
            #[allow(deprecated)]
151
100k
            atomic::spin_loop_hint();
152
100k
        }
153
154
99.4k
        if self.step.get() <= SPIN_LIMIT {
155
99.4k
            self.step.set(self.step.get() + 1);
156
99.4k
        }
16
157
99.4k
    }
<crossbeam_utils::backoff::Backoff>::spin
Line
Count
Source
146
5.40k
    pub fn spin(&self) {
147
6.51k
        for _ in 0..
1 << self.step.get().min(SPIN_LIMIT)5.40k
{
148
6.51k
            // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
149
6.51k
            // use [`core::hint::spin_loop`] instead.
150
6.51k
            #[allow(deprecated)]
151
6.51k
            atomic::spin_loop_hint();
152
6.51k
        }
153
154
5.41k
        if self.step.get() <= SPIN_LIMIT {
155
5.40k
            self.step.set(self.step.get() + 1);
156
5.40k
        }
5
157
5.41k
    }
158
159
    /// Backs off in a blocking loop.
160
    ///
161
    /// This method should be used when we need to wait for another thread to make progress.
162
    ///
163
    /// The processor may yield using the *YIELD* or *PAUSE* instruction and the current thread
164
    /// may yield by giving up a timeslice to the OS scheduler.
165
    ///
166
    /// In `#[no_std]` environments, this method is equivalent to [`spin`].
167
    ///
168
    /// If possible, use [`is_completed`] to check when it is advised to stop using backoff and
169
    /// block the current thread using a different synchronization mechanism instead.
170
    ///
171
    /// [`spin`]: Backoff::spin
172
    /// [`is_completed`]: Backoff::is_completed
173
    ///
174
    /// # Examples
175
    ///
176
    /// Waiting for an [`AtomicBool`] to become `true`:
177
    ///
178
    /// ```
179
    /// use crossbeam_utils::Backoff;
180
    /// use std::sync::Arc;
181
    /// use std::sync::atomic::AtomicBool;
182
    /// use std::sync::atomic::Ordering::SeqCst;
183
    /// use std::thread;
184
    /// use std::time::Duration;
185
    ///
186
    /// fn spin_wait(ready: &AtomicBool) {
187
    ///     let backoff = Backoff::new();
188
    ///     while !ready.load(SeqCst) {
189
    ///         backoff.snooze();
190
    ///     }
191
    /// }
192
    ///
193
    /// let ready = Arc::new(AtomicBool::new(false));
194
    /// let ready2 = ready.clone();
195
    ///
196
    /// thread::spawn(move || {
197
    ///     thread::sleep(Duration::from_millis(100));
198
    ///     ready2.store(true, SeqCst);
199
    /// });
200
    ///
201
    /// assert_eq!(ready.load(SeqCst), false);
202
    /// spin_wait(&ready);
203
    /// assert_eq!(ready.load(SeqCst), true);
204
    /// ```
205
    ///
206
    /// [`AtomicBool`]: std::sync::atomic::AtomicBool
207
    #[inline]
208
19.2M
    pub fn snooze(&self) {
209
19.2M
        if self.step.get() <= SPIN_LIMIT {
210
46.0M
            for _ in 0..
1 << self.step.get()18.7M
{
211
46.0M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
46.0M
                // use [`core::hint::spin_loop`] instead.
213
46.0M
                #[allow(deprecated)]
214
46.0M
                atomic::spin_loop_hint();
215
46.0M
            }
216
505k
        } else {
217
505k
            #[cfg(not(feature = "std"))]
218
505k
            for _ in 0..1 << self.step.get() {
219
505k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
505k
                // use [`core::hint::spin_loop`] instead.
221
505k
                #[allow(deprecated)]
222
505k
                atomic::spin_loop_hint();
223
505k
            }
224
505k
225
505k
            #[cfg(feature = "std")]
226
505k
            ::std::thread::yield_now();
227
505k
        }
228
229
20.1M
        if self.step.get() <= YIELD_LIMIT {
230
19.8M
            self.step.set(self.step.get() + 1);
231
19.8M
        }
319k
232
20.1M
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
5.88k
    pub fn snooze(&self) {
209
5.88k
        if self.step.get() <= SPIN_LIMIT {
210
8.02k
            for _ in 0..
1 << self.step.get()5.89k
{
211
8.02k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
8.02k
                // use [`core::hint::spin_loop`] instead.
213
8.02k
                #[allow(deprecated)]
214
8.02k
                atomic::spin_loop_hint();
215
8.02k
            }
216
18.4E
        } else {
217
18.4E
            #[cfg(not(feature = "std"))]
218
18.4E
            for _ in 0..1 << self.step.get() {
219
18.4E
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
18.4E
                // use [`core::hint::spin_loop`] instead.
221
18.4E
                #[allow(deprecated)]
222
18.4E
                atomic::spin_loop_hint();
223
18.4E
            }
224
18.4E
225
18.4E
            #[cfg(feature = "std")]
226
18.4E
            ::std::thread::yield_now();
227
18.4E
        }
228
229
6.63k
        if self.step.get() <= YIELD_LIMIT {
230
6.54k
            self.step.set(self.step.get() + 1);
231
6.54k
        }
90
232
6.63k
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
2.35M
    pub fn snooze(&self) {
209
2.35M
        if self.step.get() <= SPIN_LIMIT {
210
6.31M
            for _ in 0..
1 << self.step.get()2.15M
{
211
6.31M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
6.31M
                // use [`core::hint::spin_loop`] instead.
213
6.31M
                #[allow(deprecated)]
214
6.31M
                atomic::spin_loop_hint();
215
6.31M
            }
216
198k
        } else {
217
198k
            #[cfg(not(feature = "std"))]
218
198k
            for _ in 0..1 << self.step.get() {
219
198k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
198k
                // use [`core::hint::spin_loop`] instead.
221
198k
                #[allow(deprecated)]
222
198k
                atomic::spin_loop_hint();
223
198k
            }
224
198k
225
198k
            #[cfg(feature = "std")]
226
198k
            ::std::thread::yield_now();
227
198k
        }
228
229
2.48M
        if self.step.get() <= YIELD_LIMIT {
230
2.27M
            self.step.set(self.step.get() + 1);
231
2.27M
        }
203k
232
2.48M
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
277k
    pub fn snooze(&self) {
209
277k
        if self.step.get() <= SPIN_LIMIT {
210
2.27M
            for _ in 0..
1 << self.step.get()256k
{
211
2.27M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
2.27M
                // use [`core::hint::spin_loop`] instead.
213
2.27M
                #[allow(deprecated)]
214
2.27M
                atomic::spin_loop_hint();
215
2.27M
            }
216
21.6k
        } else {
217
21.6k
            #[cfg(not(feature = "std"))]
218
21.6k
            for _ in 0..1 << self.step.get() {
219
21.6k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
21.6k
                // use [`core::hint::spin_loop`] instead.
221
21.6k
                #[allow(deprecated)]
222
21.6k
                atomic::spin_loop_hint();
223
21.6k
            }
224
21.6k
225
21.6k
            #[cfg(feature = "std")]
226
21.6k
            ::std::thread::yield_now();
227
21.6k
        }
228
229
278k
        if self.step.get() <= YIELD_LIMIT {
230
278k
            self.step.set(self.step.get() + 1);
231
278k
        }
43
232
278k
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
312
    pub fn snooze(&self) {
209
312
        if self.step.get() <= SPIN_LIMIT {
210
533
            for _ in 0..
1 << self.step.get()67
{
211
533
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
533
                // use [`core::hint::spin_loop`] instead.
213
533
                #[allow(deprecated)]
214
533
                atomic::spin_loop_hint();
215
533
            }
216
245
        } else {
217
245
            #[cfg(not(feature = "std"))]
218
245
            for _ in 0..1 << self.step.get() {
219
245
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
245
                // use [`core::hint::spin_loop`] instead.
221
245
                #[allow(deprecated)]
222
245
                atomic::spin_loop_hint();
223
245
            }
224
245
225
245
            #[cfg(feature = "std")]
226
245
            ::std::thread::yield_now();
227
245
        }
228
229
312
        if self.step.get() <= YIELD_LIMIT {
230
303
            self.step.set(self.step.get() + 1);
231
303
        }
9
232
312
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
8.37M
    pub fn snooze(&self) {
209
8.37M
        if self.step.get() <= SPIN_LIMIT {
210
13.6M
            for _ in 0..
1 << self.step.get()8.34M
{
211
13.6M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
13.6M
                // use [`core::hint::spin_loop`] instead.
213
13.6M
                #[allow(deprecated)]
214
13.6M
                atomic::spin_loop_hint();
215
13.6M
            }
216
26.4k
        } else {
217
26.4k
            #[cfg(not(feature = "std"))]
218
26.4k
            for _ in 0..1 << self.step.get() {
219
26.4k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
26.4k
                // use [`core::hint::spin_loop`] instead.
221
26.4k
                #[allow(deprecated)]
222
26.4k
                atomic::spin_loop_hint();
223
26.4k
            }
224
26.4k
225
26.4k
            #[cfg(feature = "std")]
226
26.4k
            ::std::thread::yield_now();
227
26.4k
        }
228
229
8.68M
        if self.step.get() <= YIELD_LIMIT {
230
8.58M
            self.step.set(self.step.get() + 1);
231
8.58M
        }
92.0k
232
8.68M
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
217k
    pub fn snooze(&self) {
209
217k
        if self.step.get() <= SPIN_LIMIT {
210
651k
            for _ in 0..
1 << self.step.get()212k
{
211
651k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
651k
                // use [`core::hint::spin_loop`] instead.
213
651k
                #[allow(deprecated)]
214
651k
                atomic::spin_loop_hint();
215
651k
            }
216
4.68k
        } else {
217
4.68k
            #[cfg(not(feature = "std"))]
218
4.68k
            for _ in 0..1 << self.step.get() {
219
4.68k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
4.68k
                // use [`core::hint::spin_loop`] instead.
221
4.68k
                #[allow(deprecated)]
222
4.68k
                atomic::spin_loop_hint();
223
4.68k
            }
224
4.68k
225
4.68k
            #[cfg(feature = "std")]
226
4.68k
            ::std::thread::yield_now();
227
4.68k
        }
228
229
234k
        if self.step.get() <= YIELD_LIMIT {
230
229k
            self.step.set(self.step.get() + 1);
231
229k
        }
4.67k
232
234k
    }
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
196k
    pub fn snooze(&self) {
209
196k
        if self.step.get() <= SPIN_LIMIT {
210
1.68M
            for _ in 0..
1 << self.step.get()191k
{
211
1.68M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
1.68M
                // use [`core::hint::spin_loop`] instead.
213
1.68M
                #[allow(deprecated)]
214
1.68M
                atomic::spin_loop_hint();
215
1.68M
            }
216
5.53k
        } else {
217
5.53k
            #[cfg(not(feature = "std"))]
218
5.53k
            for _ in 0..1 << self.step.get() {
219
5.53k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
5.53k
                // use [`core::hint::spin_loop`] instead.
221
5.53k
                #[allow(deprecated)]
222
5.53k
                atomic::spin_loop_hint();
223
5.53k
            }
224
5.53k
225
5.53k
            #[cfg(feature = "std")]
226
5.53k
            ::std::thread::yield_now();
227
5.53k
        }
228
229
197k
        if self.step.get() <= YIELD_LIMIT {
230
197k
            self.step.set(self.step.get() + 1);
231
197k
        }
408
232
197k
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
47
    pub fn snooze(&self) {
209
47
        if self.step.get() <= SPIN_LIMIT {
210
412
            for _ in 0..
1 << self.step.get()33
{
211
412
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
412
                // use [`core::hint::spin_loop`] instead.
213
412
                #[allow(deprecated)]
214
412
                atomic::spin_loop_hint();
215
412
            }
216
14
        } else {
217
14
            #[cfg(not(feature = "std"))]
218
14
            for _ in 0..1 << self.step.get() {
219
14
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
14
                // use [`core::hint::spin_loop`] instead.
221
14
                #[allow(deprecated)]
222
14
                atomic::spin_loop_hint();
223
14
            }
224
14
225
14
            #[cfg(feature = "std")]
226
14
            ::std::thread::yield_now();
227
14
        }
228
229
45
        if self.step.get() <= YIELD_LIMIT {
230
45
            self.step.set(self.step.get() + 1);
231
45
        }
0
232
45
    }
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
19.1k
    pub fn snooze(&self) {
209
19.1k
        if self.step.get() <= SPIN_LIMIT {
210
167k
            for _ in 0..
1 << self.step.get()17.1k
{
211
167k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
167k
                // use [`core::hint::spin_loop`] instead.
213
167k
                #[allow(deprecated)]
214
167k
                atomic::spin_loop_hint();
215
167k
            }
216
2.01k
        } else {
217
2.01k
            #[cfg(not(feature = "std"))]
218
2.01k
            for _ in 0..1 << self.step.get() {
219
2.01k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
2.01k
                // use [`core::hint::spin_loop`] instead.
221
2.01k
                #[allow(deprecated)]
222
2.01k
                atomic::spin_loop_hint();
223
2.01k
            }
224
2.01k
225
2.01k
            #[cfg(feature = "std")]
226
2.01k
            ::std::thread::yield_now();
227
2.01k
        }
228
229
19.3k
        if self.step.get() <= YIELD_LIMIT {
230
19.1k
            self.step.set(self.step.get() + 1);
231
19.1k
        }
127
232
19.3k
    }
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
Unexecuted instantiation: <crossbeam_utils::backoff::Backoff>::snooze
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
151k
    pub fn snooze(&self) {
209
151k
        if self.step.get() <= SPIN_LIMIT {
210
1.41M
            for _ in 0..
1 << self.step.get()124k
{
211
1.41M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
1.41M
                // use [`core::hint::spin_loop`] instead.
213
1.41M
                #[allow(deprecated)]
214
1.41M
                atomic::spin_loop_hint();
215
1.41M
            }
216
26.8k
        } else {
217
26.8k
            #[cfg(not(feature = "std"))]
218
26.8k
            for _ in 0..1 << self.step.get() {
219
26.8k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
26.8k
                // use [`core::hint::spin_loop`] instead.
221
26.8k
                #[allow(deprecated)]
222
26.8k
                atomic::spin_loop_hint();
223
26.8k
            }
224
26.8k
225
26.8k
            #[cfg(feature = "std")]
226
26.8k
            ::std::thread::yield_now();
227
26.8k
        }
228
229
151k
        if self.step.get() <= YIELD_LIMIT {
230
151k
            self.step.set(self.step.get() + 1);
231
151k
        }
33
232
151k
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
1.78M
    pub fn snooze(&self) {
209
1.78M
        if self.step.get() <= SPIN_LIMIT {
210
8.76M
            for _ in 0..
1 << self.step.get()1.57M
{
211
8.76M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
8.76M
                // use [`core::hint::spin_loop`] instead.
213
8.76M
                #[allow(deprecated)]
214
8.76M
                atomic::spin_loop_hint();
215
8.76M
            }
216
205k
        } else {
217
205k
            #[cfg(not(feature = "std"))]
218
205k
            for _ in 0..1 << self.step.get() {
219
205k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
205k
                // use [`core::hint::spin_loop`] instead.
221
205k
                #[allow(deprecated)]
222
205k
                atomic::spin_loop_hint();
223
205k
            }
224
205k
225
205k
            #[cfg(feature = "std")]
226
205k
            ::std::thread::yield_now();
227
205k
        }
228
229
1.86M
        if 
self.step.get() <= YIELD_LIMIT1.84M
{
230
1.86M
            self.step.set(self.step.get() + 1);
231
18.4E
        }
232
1.84M
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
5.57M
    pub fn snooze(&self) {
209
5.57M
        if self.step.get() <= SPIN_LIMIT {
210
10.2M
            for _ in 0..
1 << self.step.get()5.56M
{
211
10.2M
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
10.2M
                // use [`core::hint::spin_loop`] instead.
213
10.2M
                #[allow(deprecated)]
214
10.2M
                atomic::spin_loop_hint();
215
10.2M
            }
216
13.7k
        } else {
217
13.7k
            #[cfg(not(feature = "std"))]
218
13.7k
            for _ in 0..1 << self.step.get() {
219
13.7k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
13.7k
                // use [`core::hint::spin_loop`] instead.
221
13.7k
                #[allow(deprecated)]
222
13.7k
                atomic::spin_loop_hint();
223
13.7k
            }
224
13.7k
225
13.7k
            #[cfg(feature = "std")]
226
13.7k
            ::std::thread::yield_now();
227
13.7k
        }
228
229
5.89M
        if self.step.get() <= YIELD_LIMIT {
230
5.85M
            self.step.set(self.step.get() + 1);
231
5.85M
        }
36.2k
232
5.89M
    }
<crossbeam_utils::backoff::Backoff>::snooze
Line
Count
Source
208
323k
    pub fn snooze(&self) {
209
323k
        if self.step.get() <= SPIN_LIMIT {
210
915k
            for _ in 0..
1 << self.step.get()322k
{
211
915k
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
212
915k
                // use [`core::hint::spin_loop`] instead.
213
915k
                #[allow(deprecated)]
214
915k
                atomic::spin_loop_hint();
215
915k
            }
216
782
        } else {
217
782
            #[cfg(not(feature = "std"))]
218
782
            for _ in 0..1 << self.step.get() {
219
782
                // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
220
782
                // use [`core::hint::spin_loop`] instead.
221
782
                #[allow(deprecated)]
222
782
                atomic::spin_loop_hint();
223
782
            }
224
782
225
782
            #[cfg(feature = "std")]
226
782
            ::std::thread::yield_now();
227
782
        }
228
229
343k
        if self.step.get() <= YIELD_LIMIT {
230
340k
            self.step.set(self.step.get() + 1);
231
340k
        }
3.64k
232
343k
    }
233
234
    /// Returns `true` if exponential backoff has completed and blocking the thread is advised.
235
    ///
236
    /// # Examples
237
    ///
238
    /// Waiting for an [`AtomicBool`] to become `true` and parking the thread after a long wait:
239
    ///
240
    /// ```
241
    /// use crossbeam_utils::Backoff;
242
    /// use std::sync::Arc;
243
    /// use std::sync::atomic::AtomicBool;
244
    /// use std::sync::atomic::Ordering::SeqCst;
245
    /// use std::thread;
246
    /// use std::time::Duration;
247
    ///
248
    /// fn blocking_wait(ready: &AtomicBool) {
249
    ///     let backoff = Backoff::new();
250
    ///     while !ready.load(SeqCst) {
251
    ///         if backoff.is_completed() {
252
    ///             thread::park();
253
    ///         } else {
254
    ///             backoff.snooze();
255
    ///         }
256
    ///     }
257
    /// }
258
    ///
259
    /// let ready = Arc::new(AtomicBool::new(false));
260
    /// let ready2 = ready.clone();
261
    /// let waiter = thread::current();
262
    ///
263
    /// thread::spawn(move || {
264
    ///     thread::sleep(Duration::from_millis(100));
265
    ///     ready2.store(true, SeqCst);
266
    ///     waiter.unpark();
267
    /// });
268
    ///
269
    /// assert_eq!(ready.load(SeqCst), false);
270
    /// blocking_wait(&ready);
271
    /// assert_eq!(ready.load(SeqCst), true);
272
    /// ```
273
    ///
274
    /// [`AtomicBool`]: std::sync::atomic::AtomicBool
275
    #[inline]
276
7.55M
    pub fn is_completed(&self) -> bool {
277
7.55M
        self.step.get() > YIELD_LIMIT
278
7.55M
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
1.02M
    pub fn is_completed(&self) -> bool {
277
1.02M
        self.step.get() > YIELD_LIMIT
278
1.02M
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
281k
    pub fn is_completed(&self) -> bool {
277
281k
        self.step.get() > YIELD_LIMIT
278
281k
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
1.96M
    pub fn is_completed(&self) -> bool {
277
1.96M
        self.step.get() > YIELD_LIMIT
278
1.96M
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
129k
    pub fn is_completed(&self) -> bool {
277
129k
        self.step.get() > YIELD_LIMIT
278
129k
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
192k
    pub fn is_completed(&self) -> bool {
277
192k
        self.step.get() > YIELD_LIMIT
278
192k
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
51
    pub fn is_completed(&self) -> bool {
277
51
        self.step.get() > YIELD_LIMIT
278
51
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
148k
    pub fn is_completed(&self) -> bool {
277
148k
        self.step.get() > YIELD_LIMIT
278
148k
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
1.63M
    pub fn is_completed(&self) -> bool {
277
1.63M
        self.step.get() > YIELD_LIMIT
278
1.63M
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
2.00M
    pub fn is_completed(&self) -> bool {
277
2.00M
        self.step.get() > YIELD_LIMIT
278
2.00M
    }
<crossbeam_utils::backoff::Backoff>::is_completed
Line
Count
Source
276
177k
    pub fn is_completed(&self) -> bool {
277
177k
        self.step.get() > YIELD_LIMIT
278
177k
    }
279
}
280
281
impl fmt::Debug for Backoff {
282
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283
        f.debug_struct("Backoff")
284
            .field("step", &self.step)
285
            .field("is_completed", &self.is_completed())
286
            .finish()
287
    }
288
}
289
290
impl Default for Backoff {
291
    fn default() -> Backoff {
292
        Backoff::new()
293
    }
294
}