use core::{
cell::{Cell, UnsafeCell},
ops::{Deref, DerefMut},
};
pub unsafe trait LockingMechanism {
fn lock(&self);
fn unlock(&self);
}
#[derive(Debug)]
pub struct SingleThreadedLockingMechanism {
locked: Cell<bool>,
}
#[cfg(doctest)]
struct _SingleThreadedLockingMechanismIsNotSync;
unsafe impl LockingMechanism for SingleThreadedLockingMechanism {
#[inline]
fn lock(&self) {
assert!(!self.locked.get());
self.locked.set(true);
}
#[inline]
fn unlock(&self) {
assert!(self.locked.get());
self.locked.set(false);
}
}
impl Default for SingleThreadedLockingMechanism {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl SingleThreadedLockingMechanism {
#[inline]
pub const fn new() -> Self {
SingleThreadedLockingMechanism {
locked: Cell::new(false),
}
}
}
#[derive(Default)]
pub struct Mutex<T, L> {
lock: L,
value: UnsafeCell<T>,
}
unsafe impl<T, L> Send for Mutex<T, L>
where
T: Send,
L: Send,
{
}
unsafe impl<T, L> Sync for Mutex<T, L>
where
T: Send,
L: Sync + LockingMechanism,
{
}
impl<T, L> Mutex<T, L>
where
L: LockingMechanism,
{
pub const fn new(value: T, lock: L) -> Self {
let value = UnsafeCell::new(value);
Mutex { lock, value }
}
pub fn lock(&self) -> MutexGuard<'_, T, L> {
self.lock.lock();
MutexGuard { mutex: self }
}
}
pub struct MutexGuard<'a, T, L>
where
L: LockingMechanism,
{
mutex: &'a Mutex<T, L>,
}
impl<'a, T, L> Drop for MutexGuard<'a, T, L>
where
L: LockingMechanism,
{
fn drop(&mut self) {
self.mutex.lock.unlock();
}
}
impl<T, L> Deref for MutexGuard<'_, T, L>
where
L: LockingMechanism,
{
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.mutex.value.get() }
}
}
impl<T, L> DerefMut for MutexGuard<'_, T, L>
where
L: LockingMechanism,
{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.mutex.value.get() }
}
}