#![deny(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
pub mod raw_impls;
pub use scoped_mutex_traits::{ConstInit, ScopedRawMutex};
use core::cell::UnsafeCell;
pub struct BlockingMutex<R, T: ?Sized> {
raw: R,
data: UnsafeCell<T>,
}
unsafe impl<R: ScopedRawMutex + Send, T: ?Sized + Send> Send for BlockingMutex<R, T> {}
unsafe impl<R: ScopedRawMutex + Sync, T: ?Sized + Send> Sync for BlockingMutex<R, T> {}
impl<R: ConstInit, T> BlockingMutex<R, T> {
#[inline]
pub const fn new(val: T) -> BlockingMutex<R, T> {
BlockingMutex {
raw: R::INIT,
data: UnsafeCell::new(val),
}
}
}
impl<R: ScopedRawMutex, T> BlockingMutex<R, T> {
pub fn with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> U {
self.raw.with_lock(|| {
let ptr = self.data.get();
let inner = unsafe { &mut *ptr };
f(inner)
})
}
#[must_use]
pub fn try_with_lock<U>(&self, f: impl FnOnce(&mut T) -> U) -> Option<U> {
self.raw.try_with_lock(|| {
let ptr = self.data.get();
let inner = unsafe { &mut *ptr };
f(inner)
})
}
}
impl<R, T> BlockingMutex<R, T> {
#[inline]
pub const fn const_new(raw_mutex: R, val: T) -> BlockingMutex<R, T> {
BlockingMutex {
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 unsafe fn get_unchecked(&self) -> *mut T {
self.data.get()
}
}