use lock_api::{GetThreadId, GuardSend, RawMutex};
use std::{
num::NonZero,
ops::Deref,
ptr::NonNull,
sync::atomic::{AtomicBool, Ordering},
};
pub struct RawSpinlock(AtomicBool);
unsafe impl RawMutex for RawSpinlock {
#[allow(clippy::declare_interior_mutable_const)]
const INIT: RawSpinlock = RawSpinlock(AtomicBool::new(false));
type GuardMarker = GuardSend;
fn lock(&self) {
while !self.try_lock() {}
}
fn try_lock(&self) -> bool {
self.0
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_ok()
}
unsafe fn unlock(&self) {
self.0.store(false, Ordering::Release);
}
}
pub(crate) fn current_thread_unique_ptr() -> NonZero<usize> {
thread_local! { static X: u8 = const { 0 } }
X.with(|x| <NonNull<_>>::addr(<&u8>::into(x)))
}
pub(crate) struct G;
unsafe impl GetThreadId for G {
const INIT: Self = G;
fn nonzero_thread_id(&self) -> std::num::NonZeroUsize {
current_thread_unique_ptr()
}
}
pub(crate) type Mutex<T> = lock_api::ReentrantMutex<RawSpinlock, G, T>;
impl<'s, T: 's> super::Reentrant<'s, T> for Mutex<T> {
fn create(data: T) -> Self {
Mutex::new(data)
}
fn reentrant_lock(&'s self) -> impl Deref<Target = T> + 's {
self.lock()
}
}