#[cfg(unix)]
use libc;
use std::sync::atomic::spin_loop_hint;
#[cfg(not(any(windows, unix)))]
use std::thread;
#[cfg(windows)]
use winapi;
#[cfg(windows)]
#[inline]
fn thread_yield() {
extern "system" {
fn Sleep(a: winapi::shared::minwindef::DWORD);
}
unsafe {
Sleep(0);
}
}
#[cfg(unix)]
#[inline]
fn thread_yield() {
unsafe {
libc::sched_yield();
}
}
#[cfg(not(any(windows, unix)))]
#[inline]
fn thread_yield() {
thread::yield_now();
}
#[inline]
fn cpu_relax(iterations: u32) {
for _ in 0..iterations {
spin_loop_hint()
}
}
pub struct SpinWait {
counter: u32,
}
impl SpinWait {
#[inline]
pub fn new() -> SpinWait {
SpinWait { counter: 0 }
}
#[inline]
pub fn reset(&mut self) {
self.counter = 0;
}
#[inline]
pub fn spin(&mut self) -> bool {
if self.counter >= 10 {
return false;
}
self.counter += 1;
if self.counter <= 3 {
cpu_relax(1 << self.counter);
} else {
thread_yield();
}
true
}
#[inline]
pub fn spin_no_yield(&mut self) {
self.counter += 1;
if self.counter > 10 {
self.counter = 10;
}
cpu_relax(1 << self.counter);
}
}
impl Default for SpinWait {
#[inline]
fn default() -> SpinWait {
SpinWait::new()
}
}