pub mod raw;
use core::cell::UnsafeCell;
use self::raw::RawMutex;
#[derive(Debug)]
pub struct Mutex<R, 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> {
#[inline]
pub const fn new(val: T) -> Mutex<R, T> {
Mutex {
raw: R::INIT,
data: UnsafeCell::new(val),
}
}
pub fn lock<U>(&self, f: impl FnOnce(&T) -> U) -> U {
self.raw.lock(|| {
let ptr = self.data.get() as *const T;
let inner = unsafe { &*ptr };
f(inner)
})
}
pub unsafe fn lock_mut<U>(&self, f: impl FnOnce(&mut T) -> U) -> U {
self.raw.lock(|| {
let ptr = self.data.get() as *mut T;
let inner = unsafe { &mut *ptr };
f(inner)
})
}
}
impl<R, T> Mutex<R, T> {
#[inline]
pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
Mutex {
raw: raw_mutex,
data: UnsafeCell::new(val),
}
}
#[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() }
}
}
pub type CriticalSectionMutex<T> = Mutex<raw::CriticalSectionRawMutex, T>;
pub type NoopMutex<T> = Mutex<raw::NoopRawMutex, T>;
impl<T> Mutex<raw::CriticalSectionRawMutex, T> {
pub fn borrow<'cs>(&'cs self, _cs: critical_section::CriticalSection<'cs>) -> &'cs T {
let ptr = self.data.get() as *const T;
unsafe { &*ptr }
}
}
impl<T> Mutex<raw::NoopRawMutex, T> {
#[allow(clippy::should_implement_trait)]
pub fn borrow(&self) -> &T {
let ptr = self.data.get() as *const T;
unsafe { &*ptr }
}
}
#[cfg(any(cortex_m, doc, feature = "std"))]
pub use thread_mode_mutex::*;
#[cfg(any(cortex_m, doc, feature = "std"))]
mod thread_mode_mutex {
use super::*;
pub struct ThreadModeMutex<T: ?Sized> {
inner: UnsafeCell<T>,
}
unsafe impl<T: ?Sized> Sync for ThreadModeMutex<T> {}
unsafe impl<T: ?Sized> Send for ThreadModeMutex<T> {}
impl<T> ThreadModeMutex<T> {
pub const fn new(value: T) -> Self {
ThreadModeMutex {
inner: UnsafeCell::new(value),
}
}
}
impl<T: ?Sized> ThreadModeMutex<T> {
pub fn lock<R>(&self, f: impl FnOnce(&T) -> R) -> R {
f(self.borrow())
}
pub fn borrow(&self) -> &T {
assert!(
raw::in_thread_mode(),
"ThreadModeMutex can only be borrowed from thread mode."
);
unsafe { &*self.inner.get() }
}
}
impl<T: ?Sized> Drop for ThreadModeMutex<T> {
fn drop(&mut self) {
assert!(
raw::in_thread_mode(),
"ThreadModeMutex can only be dropped from thread mode."
);
}
}
}