+use crate::primitive::sync::atomic;
use core::cell::Cell;
use core::fmt;
-use core::sync::atomic;
const SPIN_LIMIT: u32 = 6;
const YIELD_LIMIT: u32 = 10;
/// let backoff = Backoff::new();
/// loop {
/// let val = a.load(SeqCst);
-/// if a.compare_and_swap(val, val.wrapping_mul(b), SeqCst) == val {
+/// if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() {
/// return val;
/// }
/// backoff.spin();
/// }
/// ```
///
-/// [`is_completed`]: struct.Backoff.html#method.is_completed
-/// [`std::thread::park()`]: https://doc.rust-lang.org/std/thread/fn.park.html
-/// [`Condvar`]: https://doc.rust-lang.org/std/sync/struct.Condvar.html
-/// [`AtomicBool`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html
-/// [`unpark()`]: https://doc.rust-lang.org/std/thread/struct.Thread.html#method.unpark
+/// [`is_completed`]: Backoff::is_completed
+/// [`std::thread::park()`]: std::thread::park
+/// [`Condvar`]: std::sync::Condvar
+/// [`AtomicBool`]: std::sync::atomic::AtomicBool
+/// [`unpark()`]: std::thread::Thread::unpark
pub struct Backoff {
step: Cell<u32>,
}
/// let backoff = Backoff::new();
/// loop {
/// let val = a.load(SeqCst);
- /// if a.compare_and_swap(val, val.wrapping_mul(b), SeqCst) == val {
+ /// if a.compare_exchange(val, val.wrapping_mul(b), SeqCst, SeqCst).is_ok() {
/// return val;
/// }
/// backoff.spin();
#[inline]
pub fn spin(&self) {
for _ in 0..1 << self.step.get().min(SPIN_LIMIT) {
+ // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+ // use [`core::hint::spin_loop`] instead.
+ #[allow(deprecated)]
atomic::spin_loop_hint();
}
/// If possible, use [`is_completed`] to check when it is advised to stop using backoff and
/// block the current thread using a different synchronization mechanism instead.
///
- /// [`spin`]: struct.Backoff.html#method.spin
- /// [`is_completed`]: struct.Backoff.html#method.is_completed
+ /// [`spin`]: Backoff::spin
+ /// [`is_completed`]: Backoff::is_completed
///
/// # Examples
///
/// assert_eq!(ready.load(SeqCst), true);
/// ```
///
- /// [`AtomicBool`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html
+ /// [`AtomicBool`]: std::sync::atomic::AtomicBool
#[inline]
pub fn snooze(&self) {
if self.step.get() <= SPIN_LIMIT {
for _ in 0..1 << self.step.get() {
+ // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+ // use [`core::hint::spin_loop`] instead.
+ #[allow(deprecated)]
atomic::spin_loop_hint();
}
} else {
#[cfg(not(feature = "std"))]
for _ in 0..1 << self.step.get() {
+ // TODO(taiki-e): once we bump the minimum required Rust version to 1.49+,
+ // use [`core::hint::spin_loop`] instead.
+ #[allow(deprecated)]
atomic::spin_loop_hint();
}
/// assert_eq!(ready.load(SeqCst), true);
/// ```
///
- /// [`AtomicBool`]: https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html
+ /// [`AtomicBool`]: std::sync::atomic::AtomicBool
#[inline]
pub fn is_completed(&self) -> bool {
self.step.get() > YIELD_LIMIT
}
-
- #[inline]
- #[doc(hidden)]
- #[deprecated(note = "use `is_completed` instead")]
- pub fn is_complete(&self) -> bool {
- self.is_completed()
- }
}
impl fmt::Debug for Backoff {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Backoff")
.field("step", &self.step)
.field("is_completed", &self.is_completed())