#![allow(unsafe_code)]
use core::cell::UnsafeCell;
use core::fmt;
use core::future::Future;
use core::ops::{Deref, DerefMut};
use core::pin::Pin;
use core::task::{Context, Poll};
use super::semaphore::{Acquire, Semaphore};
use crate::sync::TryLockError;
pub struct Mutex<T: ?Sized> {
sem: Semaphore,
value: UnsafeCell<T>,
}
impl<T> Mutex<T> {
pub const fn new(value: T) -> Self {
Self {
sem: Semaphore::new(1),
value: UnsafeCell::new(value),
}
}
pub fn into_inner(self) -> T {
self.value.into_inner()
}
}
impl<T: ?Sized> Mutex<T> {
pub fn lock(&self) -> Lock<'_, T> {
Lock {
mutex: self,
acquire: self.sem.acquire(),
}
}
pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, TryLockError> {
match self.sem.try_acquire() {
Ok(permit) => {
permit.forget();
Ok(MutexGuard { mutex: self })
}
Err(_) => Err(TryLockError(())),
}
}
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
}
impl<T> From<T> for Mutex<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T: Default> Default for Mutex<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("Mutex");
match self.try_lock() {
Ok(inner) => d.field("data", &&*inner),
Err(_) => d.field("data", &format_args!("<locked>")),
};
d.finish()
}
}
#[must_use = "futures do nothing unless polled"]
pub struct Lock<'a, T: ?Sized> {
mutex: &'a Mutex<T>,
acquire: Acquire<'a>,
}
impl<'a, T: ?Sized> Future for Lock<'a, T> {
type Output = MutexGuard<'a, T>;
#[expect(
clippy::unreachable,
reason = "the mutex's semaphore is never closed, so its acquire never fails"
)]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
match Pin::new(&mut this.acquire).poll(cx) {
Poll::Ready(Ok(permit)) => {
permit.forget();
Poll::Ready(MutexGuard { mutex: this.mutex })
}
Poll::Ready(Err(_)) => unreachable!("the mutex's semaphore is never closed"),
Poll::Pending => Poll::Pending,
}
}
}
impl<T: ?Sized> fmt::Debug for Lock<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Lock").finish_non_exhaustive()
}
}
#[must_use = "dropping the guard unlocks the mutex at once"]
pub struct MutexGuard<'a, T: ?Sized> {
mutex: &'a Mutex<T>,
}
impl<T: ?Sized> Deref for MutexGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.mutex.value.get() }
}
}
impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.mutex.value.get() }
}
}
impl<T: ?Sized> Drop for MutexGuard<'_, T> {
fn drop(&mut self) {
self.mutex.sem.release(1);
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}