use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
struct AllocatedMutex(SpinMutex<WaitVariable<bool>>);
pub struct Mutex {
inner: LazyBox<AllocatedMutex>,
}
impl LazyInit for AllocatedMutex {
fn init() -> Box<Self> {
Box::new(AllocatedMutex(SpinMutex::new(WaitVariable::new(false))))
}
}
impl Mutex {
pub const fn new() -> Mutex {
Mutex { inner: LazyBox::new() }
}
#[inline]
pub fn lock(&self) {
let mut guard = self.inner.0.lock();
if *guard.lock_var() {
WaitQueue::wait(guard, || {})
} else {
*guard.lock_var_mut() = true;
}
}
#[inline]
pub unsafe fn unlock(&self) {
let guard = self.inner.0.lock();
if let Err(mut guard) = WaitQueue::notify_one(guard) {
*guard.lock_var_mut() = false;
} else {
}
}
#[inline]
pub fn try_lock(&self) -> bool {
let mut guard = try_lock_or_false!(self.inner.0);
if *guard.lock_var() {
false
} else {
*guard.lock_var_mut() = true;
true
}
}
}