use crate::sync::thread;
const SPIN_LIMIT: u32 = 6;
const YIELD_LIMIT: u32 = 10;
#[derive(Debug, Default)]
pub struct Backoff {
step: u32,
}
impl Backoff {
#[inline]
pub const fn new() -> Self {
Self { step: 0 }
}
#[inline]
pub fn reset(&mut self) {
self.step = 0;
}
#[inline]
pub fn spin(&mut self) {
#[cfg(loom)]
thread::yield_now();
#[cfg(not(loom))]
for _ in 0..1u32 << self.step.min(SPIN_LIMIT) {
std::hint::spin_loop();
}
if self.step <= SPIN_LIMIT {
self.step += 1;
}
}
#[inline]
pub fn snooze(&mut self) {
#[cfg(loom)]
thread::yield_now();
#[cfg(not(loom))]
if self.step <= SPIN_LIMIT {
for _ in 0..1u32 << self.step {
std::hint::spin_loop();
}
} else {
thread::yield_now();
}
if self.step <= YIELD_LIMIT {
self.step += 1;
}
}
#[inline]
pub fn is_completed(&self) -> bool {
if cfg!(loom) {
self.step > 0
} else {
self.step > YIELD_LIMIT
}
}
}