use std::{
ops::{Deref, DerefMut},
sync::Arc,
};
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
pub struct ReadGuard<'a, T: ?Sized>(RwLockReadGuard<'a, T>);
impl<'a, T> Deref for ReadGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
#[derive(Debug, Clone)]
pub struct Reader<T>(Arc<RwLock<T>>);
impl<T> Reader<T> {
pub async fn read(&self) -> ReadGuard<'_, T> {
ReadGuard(self.0.read().await)
}
}
pub struct WriteGuard<'a, T: ?Sized>(RwLockWriteGuard<'a, T>);
impl<'a, T> Deref for WriteGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.0.deref()
}
}
impl<'a, T> DerefMut for WriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.deref_mut()
}
}
#[derive(Debug)]
pub struct Writer<T>(Arc<RwLock<T>>);
impl<T> Writer<T> {
pub async fn write(&mut self) -> WriteGuard<'_, T> {
WriteGuard(self.0.write().await)
}
}
pub fn rw_lock<T>(value: T) -> (Reader<T>, Writer<T>) {
let lock = Arc::new(RwLock::new(value));
(Reader(lock.clone()), Writer(lock))
}