use crate::{Event, EventListener};
use core::cell::{RefCell, RefMut};
use core::ops;
use core::pin::Pin;
pub struct Mutex<T: ?Sized> {
unlocked: Event<()>,
data: RefCell<T>,
}
impl<T: Default> Default for Mutex<T> {
fn default() -> Mutex<T> {
Mutex::new(Default::default())
}
}
pub struct MutexGuard<'a, T: ?Sized> {
event: &'a Event<()>,
data: RefMut<'a, T>,
}
impl<T> Mutex<T> {
pub fn new(data: T) -> Mutex<T> {
Mutex {
unlocked: Event::new(),
data: RefCell::new(data),
}
}
pub fn into_inner(self) -> T {
self.data.into_inner()
}
}
impl<T: ?Sized> Mutex<T> {
pub fn get_mut(&mut self) -> &mut T {
self.data.get_mut()
}
pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
self.data.try_borrow_mut().ok().map(|data| MutexGuard {
event: &self.unlocked,
data,
})
}
pub async fn lock(&self) -> MutexGuard<'_, T> {
let mut listener = EventListener::new(&self.unlocked);
{
let mut listener = unsafe { Pin::new_unchecked(&mut listener) };
loop {
if let Some(lock) = self.try_lock() {
return lock;
}
listener.as_mut().await;
}
}
}
}
impl<T: ?Sized> ops::Deref for MutexGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.data
}
}
impl<T: ?Sized> ops::DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.data
}
}
impl<T: ?Sized> Drop for MutexGuard<'_, T> {
fn drop(&mut self) {
self.event.notify(1);
}
}