use std::ops::{Deref, DerefMut};
use std::sync::Arc;
pub struct Mutex<T> {
inner: Arc<tokio::sync::Mutex<T>>,
}
impl<T> Mutex<T> {
pub fn new(value: T) -> Self {
Self {
inner: Arc::new(tokio::sync::Mutex::new(value)),
}
}
pub async fn lock(&self) -> MutexGuard<'_, T> {
MutexGuard {
inner: self.inner.lock().await,
}
}
pub async fn lock_owned(self: Arc<Self>) -> OwnedMutexGuard<T> {
let inner = Arc::clone(&self.inner).lock_owned().await;
OwnedMutexGuard {
inner,
_owner: self,
}
}
pub fn try_lock(&self) -> Result<MutexGuard<'_, T>, MutexTryLockError> {
self.inner
.try_lock()
.map(|inner| MutexGuard { inner })
.map_err(|_| MutexTryLockError)
}
pub fn try_lock_owned(self: Arc<Self>) -> Result<OwnedMutexGuard<T>, MutexTryLockError> {
let inner = Arc::clone(&self.inner)
.try_lock_owned()
.map_err(|_| MutexTryLockError)?;
Ok(OwnedMutexGuard {
inner,
_owner: self,
})
}
pub fn blocking_lock(&self) -> MutexGuard<'_, T> {
MutexGuard {
inner: self.inner.blocking_lock(),
}
}
}
impl<T: Default> Default for Mutex<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T> std::fmt::Debug for Mutex<T> {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.debug_struct("Mutex").finish_non_exhaustive()
}
}
pub struct MutexGuard<'a, T> {
inner: tokio::sync::MutexGuard<'a, T>,
}
impl<T> Deref for MutexGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner
}
}
impl<T> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.inner
}
}
pub struct OwnedMutexGuard<T> {
inner: tokio::sync::OwnedMutexGuard<T>,
_owner: Arc<Mutex<T>>,
}
impl<T> Deref for OwnedMutexGuard<T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner
}
}
impl<T> DerefMut for OwnedMutexGuard<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.inner
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for MutexGuard<'_, T> {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, formatter)
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for OwnedMutexGuard<T> {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&**self, formatter)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct MutexTryLockError;
impl std::fmt::Display for MutexTryLockError {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("mutex is busy")
}
}
impl std::error::Error for MutexTryLockError {}