use std::sync::atomic::{AtomicBool, Ordering};
pub(crate) struct RawMutex {
locked: AtomicBool,
}
impl RawMutex {
pub(crate) const fn new() -> Self {
Self { locked: AtomicBool::new(false) }
}
pub(crate) fn lock(&self) {
let mut spins = 0u32;
loop {
if self
.locked
.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
{
return;
}
spins += 1;
if spins < 100 {
std::hint::spin_loop();
} else {
std::thread::yield_now();
spins = 0;
}
}
}
pub(crate) fn try_lock(&self) -> bool {
self.locked
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
}
pub(crate) unsafe fn unlock(&self) {
self.locked.store(false, Ordering::Release);
}
}
pub(crate) struct LockGuard<'a>(pub &'a RawMutex);
impl Drop for LockGuard<'_> {
fn drop(&mut self) {
unsafe { self.0.unlock() };
}
}
impl<'a> LockGuard<'a> {
pub(crate) fn new(m: &'a RawMutex) -> Self {
m.lock();
LockGuard(m)
}
}