pub use mutex::*;
mod mutex {
#![allow(clippy::should_implement_trait)]
use core::cell::UnsafeCell;
use embassy_sync::blocking_mutex::raw::RawMutex;
use crate::utils::{
init::{init, Init, UnsafeCellInit},
sync::blocking::raw::MatterRawMutex,
};
pub struct Mutex<T: ?Sized, R = MatterRawMutex> {
raw: R,
data: UnsafeCell<T>,
}
unsafe impl<T: ?Sized + Send, R: RawMutex + Send> Send for Mutex<T, R> {}
unsafe impl<T: ?Sized + Send, R: RawMutex + Sync> Sync for Mutex<T, R> {}
impl<T, R: RawMutex> Mutex<T, R> {
#[inline]
pub const fn new(val: T) -> Self {
Self {
raw: R::INIT,
data: UnsafeCell::new(val),
}
}
pub fn init<I: Init<T>>(val: I) -> impl Init<Self> {
init!(Self {
raw: R::INIT,
data <- UnsafeCell::init(val),
})
}
#[inline(always)]
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)
})
}
}
impl<T, R> Mutex<T, R> {
#[inline]
pub const fn const_new(raw_mutex: R, val: T) -> Self {
Self {
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 mod raw {
#[cfg(not(feature = "sync-mutex"))]
pub type MatterRawMutex = embassy_sync::blocking_mutex::raw::NoopRawMutex;
#[cfg(all(feature = "sync-mutex", not(feature = "std")))]
pub type MatterRawMutex = embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
#[cfg(all(feature = "sync-mutex", feature = "std"))]
pub type MatterRawMutex = StdRawMutex;
#[cfg(feature = "std")]
pub use std::*;
#[cfg(feature = "std")]
mod std {
use embassy_sync::blocking_mutex::raw::RawMutex;
#[derive(Default)]
pub struct StdRawMutex(std::sync::Mutex<()>);
impl StdRawMutex {
pub const fn new() -> Self {
Self(std::sync::Mutex::new(()))
}
}
unsafe impl RawMutex for StdRawMutex {
#[allow(clippy::declare_interior_mutable_const)]
const INIT: Self = StdRawMutex(std::sync::Mutex::new(()));
#[inline(always)]
fn lock<R>(&self, f: impl FnOnce() -> R) -> R {
let _guard = unwrap!(self.0.lock(), "Mutex lock failed");
f()
}
}
}
}