use crate::rt;
use std::{
ops,
sync::{LockResult, TryLockError, TryLockResult},
};
#[derive(Debug)]
pub struct RwLock<T> {
object: rt::RwLock,
data: std::sync::RwLock<T>,
}
#[derive(Debug)]
pub struct RwLockReadGuard<'a, T> {
lock: &'a RwLock<T>,
data: Option<std::sync::RwLockReadGuard<'a, T>>,
}
#[derive(Debug)]
pub struct RwLockWriteGuard<'a, T> {
lock: &'a RwLock<T>,
data: Option<std::sync::RwLockWriteGuard<'a, T>>,
}
impl<T> RwLock<T> {
pub fn new(data: T) -> RwLock<T> {
RwLock {
data: std::sync::RwLock::new(data),
object: rt::RwLock::new(),
}
}
pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
self.object.acquire_read_lock();
Ok(RwLockReadGuard {
lock: self,
data: Some(self.data.read().unwrap()),
})
}
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> {
if self.object.try_acquire_read_lock() {
Ok(RwLockReadGuard {
lock: self,
data: Some(self.data.read().unwrap()),
})
} else {
Err(TryLockError::WouldBlock)
}
}
pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
self.object.acquire_write_lock();
Ok(RwLockWriteGuard {
lock: self,
data: Some(self.data.write().unwrap()),
})
}
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
if self.object.try_acquire_write_lock() {
Ok(RwLockWriteGuard {
lock: self,
data: Some(self.data.write().unwrap()),
})
} else {
Err(TryLockError::WouldBlock)
}
}
}
impl<'a, T> ops::Deref for RwLockReadGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data.as_ref().unwrap().deref()
}
}
impl<'a, T: 'a> Drop for RwLockReadGuard<'a, T> {
fn drop(&mut self) {
self.data = None;
self.lock.object.release_read_lock()
}
}
impl<'a, T> ops::Deref for RwLockWriteGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.data.as_ref().unwrap().deref()
}
}
impl<'a, T> ops::DerefMut for RwLockWriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.data.as_mut().unwrap().deref_mut()
}
}
impl<'a, T: 'a> Drop for RwLockWriteGuard<'a, T> {
fn drop(&mut self) {
self.data = None;
self.lock.object.release_write_lock()
}
}