use std::{fmt, ops};
use rclite::Arc;
use tokio::sync::RwLock;
use crate::{readguard_into_ref, SharedReadGuard, SharedWriteGuard, TryLockError, TryLockResult};
pub struct Shared<T>(Arc<RwLock<T>>);
impl<T> Shared<T> {
pub fn new(data: T) -> Self {
Self(Arc::new(RwLock::new(data)))
}
pub fn unwrap(this: Self) -> Result<T, Self> {
match Arc::try_unwrap(this.0) {
Ok(rwlock) => Ok(rwlock.into_inner()),
Err(arc) => Err(Self(arc)),
}
}
#[track_caller]
pub fn get(this: &Self) -> &T {
let read_guard =
this.0.try_read().expect("nothing else can hold a write lock at this time");
unsafe { readguard_into_ref(read_guard) }
}
pub async fn lock(this: &mut Self) -> SharedWriteGuard<'_, T> {
SharedWriteGuard(this.0.write().await)
}
pub fn get_read_lock(this: &Self) -> SharedReadLock<T> {
SharedReadLock(this.0.clone())
}
}
impl<T> ops::Deref for Shared<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
Shared::get(self)
}
}
impl<T: fmt::Debug> fmt::Debug for Shared<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Clone)]
pub struct SharedReadLock<T>(Arc<RwLock<T>>);
impl<T> SharedReadLock<T> {
pub async fn lock(&self) -> SharedReadGuard<'_, T> {
SharedReadGuard(self.0.read().await)
}
pub fn try_lock(&self) -> TryLockResult<SharedReadGuard<'_, T>> {
self.0.try_read().map(SharedReadGuard).map_err(TryLockError)
}
}
impl<T: fmt::Debug> fmt::Debug for SharedReadLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}