use core::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::cfg::atomic::AtomicBool;
use crate::relax::Relax;
pub trait Lock {
#[cfg(not(all(loom, test)))]
const LOCKED: Self;
#[cfg(not(all(loom, test)))]
const UNLOCKED: Self;
#[cfg(all(loom, test))]
fn locked() -> Self;
#[cfg(all(loom, test))]
fn unlocked() -> Self;
fn try_lock_acquire(&self) -> bool;
fn try_lock_acquire_weak(&self) -> bool;
fn wait_lock_relaxed<W: Wait>(&self);
fn is_locked_relaxed(&self) -> bool;
fn notify_release(&self);
}
pub trait Wait {
type LockRelax: Relax;
type UnlockRelax: Relax;
fn relax_policy() -> RelaxPolicy<Self> {
let relax = Self::LockRelax::new();
RelaxPolicy { relax }
}
}
pub struct RelaxPolicy<W: Wait + ?Sized> {
pub relax: W::LockRelax,
}
impl Lock for AtomicBool {
#[cfg(not(all(loom, test)))]
#[allow(clippy::declare_interior_mutable_const)]
const LOCKED: Self = Self::new(true);
#[cfg(not(all(loom, test)))]
#[allow(clippy::declare_interior_mutable_const)]
const UNLOCKED: Self = Self::new(false);
#[cfg(all(loom, test))]
#[cfg(not(tarpaulin_include))]
fn locked() -> Self {
Self::new(true)
}
#[cfg(all(loom, test))]
#[cfg(not(tarpaulin_include))]
fn unlocked() -> Self {
Self::new(false)
}
fn try_lock_acquire(&self) -> bool {
self.compare_exchange(false, true, Acquire, Relaxed).is_ok()
}
fn try_lock_acquire_weak(&self) -> bool {
self.compare_exchange_weak(false, true, Acquire, Relaxed).is_ok()
}
fn wait_lock_relaxed<W: Wait>(&self) {
let mut relax_policy = W::relax_policy();
while self.load(Relaxed) {
relax_policy.relax.relax();
}
}
fn is_locked_relaxed(&self) -> bool {
self.load(Relaxed)
}
fn notify_release(&self) {
self.store(false, Release);
}
}