62 lines
1.2 KiB
Rust
62 lines
1.2 KiB
Rust
|
use crate::{Mutex, MutexGuard};
|
||
|
use core::ops::{Deref, DerefMut};
|
||
|
|
||
|
enum Value<T> {
|
||
|
Full(T),
|
||
|
Empty
|
||
|
}
|
||
|
|
||
|
pub struct StaticMutex<T> {
|
||
|
value: Mutex<Value<T>>
|
||
|
}
|
||
|
|
||
|
impl<T> StaticMutex<T> {
|
||
|
pub const fn new() -> Self {
|
||
|
Self {
|
||
|
value: Mutex::new(Value::Empty)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[track_caller]
|
||
|
pub async fn init(&self, new: T) {
|
||
|
let mut value = self.value.lock().await;
|
||
|
if !matches!(*value, Value::Empty) {
|
||
|
panic!("Cannot initialise StaticMutex more than once");
|
||
|
}
|
||
|
*value = Value::Full(new);
|
||
|
}
|
||
|
|
||
|
#[track_caller]
|
||
|
pub async fn lock(&self) -> StaticMutexLockGuard<'_, T> {
|
||
|
let inner = self.value.lock().await;
|
||
|
if matches!(*inner, Value::Empty) {
|
||
|
panic!("This StaticMutex has not been initialised yet");
|
||
|
}
|
||
|
StaticMutexLockGuard { inner }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct StaticMutexLockGuard<'a, T> {
|
||
|
inner: MutexGuard<'a, Value<T>>
|
||
|
}
|
||
|
|
||
|
impl<T> Deref for StaticMutexLockGuard<'_, T> {
|
||
|
type Target = T;
|
||
|
|
||
|
fn deref(&self) -> &Self::Target {
|
||
|
match self.inner.deref() {
|
||
|
Value::Full(ref value) => value,
|
||
|
_ => unreachable!()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<T> DerefMut for StaticMutexLockGuard<'_, T> {
|
||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||
|
match self.inner.deref_mut() {
|
||
|
Value::Full(ref mut value) => value,
|
||
|
_ => unreachable!()
|
||
|
}
|
||
|
}
|
||
|
}
|