use core::cell::UnsafeCell;
use core::fmt;
use core::marker::PhantomData;
use core::mem;
use core::ops::{Deref, DerefMut};
#[cfg(feature = "owning_ref")]
use owning_ref::StableAddress;
pub unsafe trait RawMutex {
const INIT: Self;
type GuardMarker;
fn lock(&self);
fn try_lock(&self) -> bool;
fn unlock(&self);
}
pub unsafe trait RawMutexFair: RawMutex {
fn unlock_fair(&self);
fn bump(&self) {
self.unlock_fair();
self.lock();
}
}
pub unsafe trait RawMutexTimed: RawMutex {
type Duration;
type Instant;
fn try_lock_for(&self, timeout: Self::Duration) -> bool;
fn try_lock_until(&self, timeout: Self::Instant) -> bool;
}
pub struct Mutex<R: RawMutex, T: ?Sized> {
raw: R,
data: UnsafeCell<T>,
}
unsafe impl<R: RawMutex + Send, T: ?Sized + Send> Send for Mutex<R, T> {}
unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {}
impl<R: RawMutex, T> Mutex<R, T> {
#[cfg(feature = "nightly")]
#[inline]
pub const fn new(val: T) -> Mutex<R, T> {
Mutex {
data: UnsafeCell::new(val),
raw: R::INIT,
}
}
#[cfg(not(feature = "nightly"))]
#[inline]
pub fn new(val: T) -> Mutex<R, T> {
Mutex {
data: UnsafeCell::new(val),
raw: R::INIT,
}
}
#[inline]
#[allow(unused_unsafe)]
pub fn into_inner(self) -> T {
unsafe { self.data.into_inner() }
}
}
impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
#[inline]
fn guard(&self) -> MutexGuard<R, T> {
MutexGuard {
mutex: self,
marker: PhantomData,
}
}
#[inline]
pub fn lock(&self) -> MutexGuard<R, T> {
self.raw.lock();
self.guard()
}
#[inline]
pub fn try_lock(&self) -> Option<MutexGuard<R, T>> {
if self.raw.try_lock() {
Some(self.guard())
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut *self.data.get() }
}
#[inline]
pub unsafe fn force_unlock(&self) {
self.raw.unlock();
}
#[inline]
pub unsafe fn raw(&self) -> &R {
&self.raw
}
}
impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> {
#[inline]
pub unsafe fn force_unlock_fair(&self) {
self.raw.unlock_fair();
}
}
impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
#[inline]
pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<R, T>> {
if self.raw.try_lock_for(timeout) {
Some(self.guard())
} else {
None
}
}
#[inline]
pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<R, T>> {
if self.raw.try_lock_until(timeout) {
Some(self.guard())
} else {
None
}
}
}
impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> {
#[inline]
fn default() -> Mutex<R, T> {
Mutex::new(Default::default())
}
}
impl<R: RawMutex, T> From<T> for Mutex<R, T> {
#[inline]
fn from(t: T) -> Mutex<R, T> {
Mutex::new(t)
}
}
impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.try_lock() {
Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
None => f.pad("Mutex { <locked> }"),
}
}
}
#[must_use]
pub struct MutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> {
mutex: &'a Mutex<R, T>,
marker: PhantomData<(&'a mut T, R::GuardMarker)>,
}
unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
pub fn mutex(s: &Self) -> &'a Mutex<R, T> {
s.mutex
}
#[inline]
pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
where
F: FnOnce(&mut T) -> &mut U,
{
let raw = &s.mutex.raw;
let data = f(unsafe { &mut *s.mutex.data.get() });
mem::forget(s);
MappedMutexGuard {
raw,
data,
marker: PhantomData,
}
}
#[inline]
pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
s.mutex.raw.unlock();
defer!(s.mutex.raw.lock());
f()
}
}
impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
#[inline]
pub fn unlock_fair(s: Self) {
s.mutex.raw.unlock_fair();
mem::forget(s);
}
#[inline]
pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
where
F: FnOnce() -> U,
{
s.mutex.raw.unlock_fair();
defer!(s.mutex.raw.lock());
f()
}
#[inline]
pub fn bump(s: &mut Self) {
s.mutex.raw.bump();
}
}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.mutex.data.get() }
}
}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.mutex.data.get() }
}
}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
self.mutex.raw.unlock();
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {}
#[must_use]
pub struct MappedMutexGuard<'a, R: RawMutex + 'a, T: ?Sized + 'a> {
raw: &'a R,
data: *mut T,
marker: PhantomData<&'a mut T>,
}
unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync
for MappedMutexGuard<'a, R, T>
{}
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Send for MappedMutexGuard<'a, R, T> where
R::GuardMarker: Send
{}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
#[inline]
pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
where
F: FnOnce(&mut T) -> &mut U,
{
let raw = s.raw;
let data = f(unsafe { &mut *s.data });
mem::forget(s);
MappedMutexGuard {
raw,
data,
marker: PhantomData,
}
}
}
impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
#[inline]
pub fn unlock_fair(s: Self) {
s.raw.unlock_fair();
mem::forget(s);
}
}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.data }
}
}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.data }
}
}
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> {
#[inline]
fn drop(&mut self) {
self.raw.unlock();
}
}
#[cfg(feature = "owning_ref")]
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {}