#![no_std]
use core::cell::UnsafeCell;
use core::convert::From;
use core::fmt;
use core::fmt::{Debug, Display};
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::sync::atomic::{AtomicBool, Ordering};
pub struct TryMutex<T> {
data: UnsafeCell<T>,
locked: AtomicBool,
}
impl<T> TryMutex<T> {
#[inline]
pub const fn new(t: T) -> Self {
TryMutex {
data: UnsafeCell::new(t),
locked: AtomicBool::new(false),
}
}
#[inline]
pub fn try_lock(&self) -> Option<TryMutexGuard<'_, T>> {
self.locked
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.ok()
.map(|_| TryMutexGuard {
lock: self,
notsend: PhantomData,
})
}
#[inline]
pub fn into_inner(self) -> T {
self.data.into_inner()
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.data.get() }
}
}
impl<T: Default> Default for TryMutex<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: Debug> Debug for TryMutex<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(guard) = self.try_lock() {
f.debug_struct("TryMutex").field("data", &*guard).finish()
} else {
struct LockedPlaceholder;
impl fmt::Debug for LockedPlaceholder {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("<locked>")
}
}
f.debug_struct("TryMutex")
.field("data", &LockedPlaceholder)
.finish()
}
}
}
pub struct TryMutexGuard<'a, T: 'a> {
lock: &'a TryMutex<T>,
notsend: PhantomData<*mut T>,
}
impl<'a, T> Deref for TryMutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.lock.data.get() }
}
}
impl<'a, T> DerefMut for TryMutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.lock.data.get() }
}
}
impl<'a, T> Drop for TryMutexGuard<'a, T> {
fn drop(&mut self) {
self.lock.locked.store(false, Ordering::Release);
}
}
impl<'a, T: Debug> Debug for TryMutexGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("TryMutexGuard")
.field("data", &**self)
.finish()
}
}
impl<'a, T: Display> Display for TryMutexGuard<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(**self).fmt(f)
}
}
impl<T> UnwindSafe for TryMutex<T> {}
impl<T> RefUnwindSafe for TryMutex<T> {}
unsafe impl<T: Send> Send for TryMutex<T> {}
unsafe impl<T: Send> Sync for TryMutex<T> {}
unsafe impl<'a, T: Sync> Sync for TryMutexGuard<'a, T> {}
unsafe impl<'a, T: Send> Send for TryMutexGuard<'a, T> {}
impl<T> From<T> for TryMutex<T> {
fn from(t: T) -> Self {
TryMutex::new(t)
}
}