#[cfg(not(teksilo_loom))]
mod imp {
use std::time::Duration;
pub(crate) struct Lock<T>(parking_lot::Mutex<T>);
pub(crate) struct Guard<'a, T>(parking_lot::MutexGuard<'a, T>);
impl<T> Lock<T> {
pub(crate) fn new(value: T) -> Self {
Self(parking_lot::Mutex::new(value))
}
pub(crate) fn lock(&self) -> Guard<'_, T> {
Guard(self.0.lock())
}
pub(crate) fn try_lock(&self) -> Option<Guard<'_, T>> {
self.0.try_lock().map(Guard)
}
pub(crate) fn try_lock_for(&self, timeout: Duration) -> Option<Guard<'_, T>> {
self.0.try_lock_for(timeout).map(Guard)
}
}
impl<'a, T> Guard<'a, T> {
pub(crate) fn get(&self) -> &T {
&self.0
}
pub(crate) fn get_mut(&mut self) -> &mut T {
&mut self.0
}
pub(crate) fn unlock(self, fair: bool) {
if fair {
parking_lot::MutexGuard::unlock_fair(self.0);
} else {
drop(self.0);
}
}
}
}
#[cfg(teksilo_loom)]
mod imp {
use std::mem::ManuallyDrop;
use std::time::Duration;
use loom::cell::{MutPtr, UnsafeCell};
use crate::sync::{AtomicBool, Ordering};
pub(crate) struct Lock<T> {
locked: AtomicBool,
value: UnsafeCell<T>,
}
unsafe impl<T: Send> Send for Lock<T> {}
unsafe impl<T: Send> Sync for Lock<T> {}
pub(crate) struct Guard<'a, T> {
lock: &'a Lock<T>,
value: ManuallyDrop<MutPtr<T>>,
}
impl<T> Lock<T> {
pub(crate) fn new(value: T) -> Self {
Self {
locked: AtomicBool::new(false),
value: UnsafeCell::new(value),
}
}
pub(crate) fn lock(&self) -> Guard<'_, T> {
loop {
if let Some(guard) = self.try_lock() {
return guard;
}
loom::thread::yield_now();
}
}
pub(crate) fn try_lock(&self) -> Option<Guard<'_, T>> {
if self.locked.load(Ordering::Relaxed) {
return None;
}
self.locked
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.ok()?;
Some(Guard {
lock: self,
value: ManuallyDrop::new(self.value.get_mut()),
})
}
pub(crate) fn try_lock_for(&self, _timeout: Duration) -> Option<Guard<'_, T>> {
self.try_lock()
}
}
impl<'a, T> Guard<'a, T> {
pub(crate) fn get(&self) -> &T {
unsafe { self.value.deref() }
}
pub(crate) fn get_mut(&mut self) -> &mut T {
unsafe { self.value.deref() }
}
pub(crate) fn unlock(self, _fair: bool) {
drop(self);
}
}
impl<T> Drop for Guard<'_, T> {
fn drop(&mut self) {
unsafe { ManuallyDrop::drop(&mut self.value) };
let _ = self.lock.locked.compare_exchange(
true,
false,
Ordering::Release,
Ordering::Relaxed,
);
}
}
}
pub(crate) use imp::{Guard, Lock};