use core::cell::UnsafeCell;
use crate::Mutex;
use bun_safety::ThreadLock;
pub type Guarded<Value> = GuardedBy<Value, Mutex>;
pub type MutexGuard<'a, Value> = GuardedLock<'a, Value, Mutex>;
pub type Debug<Value> = GuardedBy<Value, ThreadLock>;
pub struct GuardedBy<Value, M: RawMutex> {
pub unsynchronized_value: UnsafeCell<Value>,
mutex: M,
}
unsafe impl<Value: Send, M: RawMutex + Sync> Sync for GuardedBy<Value, M> {}
impl<Value, M: RawMutex + Default> GuardedBy<Value, M> {
pub fn init(value: Value) -> Self {
Self {
unsynchronized_value: UnsafeCell::new(value),
mutex: M::default(),
}
}
}
impl<Value: Default, M: RawMutex + Default> Default for GuardedBy<Value, M> {
fn default() -> Self {
Self::init(Value::default())
}
}
impl<Value> GuardedBy<Value, Mutex> {
pub const fn new(value: Value) -> Self {
Self {
unsynchronized_value: UnsafeCell::new(value),
mutex: Mutex::new(),
}
}
#[inline]
pub fn try_lock(&self) -> Option<GuardedLock<'_, Value, Mutex>> {
if self.mutex.try_lock() {
Some(GuardedLock { guarded: self })
} else {
None
}
}
#[inline]
pub fn raw_mutex(&self) -> &Mutex {
&self.mutex
}
}
impl<Value, M: RawMutex> GuardedBy<Value, M> {
pub fn lock(&self) -> GuardedLock<'_, Value, M> {
self.mutex.lock();
GuardedLock { guarded: self }
}
#[inline]
pub fn get_mut(&mut self) -> &mut Value {
self.unsynchronized_value.get_mut()
}
}
pub struct GuardedLock<'a, Value, M: RawMutex> {
guarded: &'a GuardedBy<Value, M>,
}
impl<'a, Value> GuardedLock<'a, Value, Mutex> {
#[inline]
pub fn mutex(&self) -> &Mutex {
&self.guarded.mutex
}
}
impl<'a, Value, M: RawMutex> core::ops::Deref for GuardedLock<'a, Value, M> {
type Target = Value;
#[inline]
fn deref(&self) -> &Value {
unsafe { &*self.guarded.unsynchronized_value.get() }
}
}
impl<'a, Value, M: RawMutex> core::ops::DerefMut for GuardedLock<'a, Value, M> {
#[inline]
fn deref_mut(&mut self) -> &mut Value {
unsafe { &mut *self.guarded.unsynchronized_value.get() }
}
}
impl<'a, Value, M: RawMutex> Drop for GuardedLock<'a, Value, M> {
#[inline]
fn drop(&mut self) {
self.guarded.mutex.unlock();
}
}
pub trait RawMutex {
fn lock(&self);
fn unlock(&self);
}
impl RawMutex for Mutex {
#[inline]
fn lock(&self) {
Mutex::lock(self)
}
#[inline]
fn unlock(&self) {
Mutex::unlock(self)
}
}