use crate::Mutex;
use crate::rwlock::{LOCKED_WRITE, RwLock, UNLOCKED};
pub struct Guard<'a, T> {
pub(crate) mutex: &'a Mutex<T>,
pub(crate) data: &'a mut T,
}
impl<T> std::ops::Deref for Guard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.data
}
}
impl<T> std::ops::DerefMut for Guard<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.data
}
}
impl<T> Drop for Guard<'_, T> {
fn drop(&mut self) {
self.mutex
.data_lock
.store(false, std::sync::atomic::Ordering::Release);
self.mutex.did_unlock();
}
}
impl<T: std::fmt::Debug> std::fmt::Debug for Guard<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Guard")
.field("data", &**self)
.finish_non_exhaustive()
}
}
impl<T: std::fmt::Display> std::fmt::Display for Guard<'_, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&**self, f)
}
}
impl<T> AsRef<T> for Guard<'_, T> {
fn as_ref(&self) -> &T {
self
}
}
impl<T> AsMut<T> for Guard<'_, T> {
fn as_mut(&mut self) -> &mut T {
self
}
}
#[derive(Debug)]
pub struct ReadGuard<'a, T> {
pub(crate) mutex: &'a RwLock<T>,
}
#[derive(Debug)]
pub struct WriteGuard<'a, T> {
pub(crate) mutex: &'a RwLock<T>,
}
impl<'a, T> AsRef<T> for ReadGuard<'a, T> {
fn as_ref(&self) -> &T {
self
}
}
impl<'a, T> AsRef<T> for WriteGuard<'a, T> {
fn as_ref(&self) -> &T {
self
}
}
impl<'a, T> AsMut<T> for WriteGuard<'a, T> {
fn as_mut(&mut self) -> &mut T {
&mut *self
}
}
impl<'a, T: std::fmt::Display> std::fmt::Display for ReadGuard<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&**self, f)
}
}
impl<'a, T: std::fmt::Display> std::fmt::Display for WriteGuard<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&**self, f)
}
}
impl<'a, T> std::ops::Deref for WriteGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.mutex.inner.get() }
}
}
impl<'a, T> std::ops::DerefMut for WriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.mutex.inner.get() }
}
}
impl<'a, T> std::ops::Deref for ReadGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.mutex.inner.get() }
}
}
impl<'a, T> Drop for ReadGuard<'a, T> {
fn drop(&mut self) {
let r = self
.mutex
.data_lock
.fetch_sub(1, std::sync::atomic::Ordering::Release);
assert!(r > 0);
self.mutex.did_unlock_read();
}
}
impl<'a, T> Drop for WriteGuard<'a, T> {
fn drop(&mut self) {
let old = self
.mutex
.data_lock
.swap(UNLOCKED, std::sync::atomic::Ordering::Release);
assert!(old == LOCKED_WRITE);
self.mutex.did_unlock_write();
}
}