use std::fmt;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::ptr::NonNull;
use crate::rwlock::MappedRwLockReadGuard;
use crate::rwlock::RwLock;
impl<T: ?Sized> RwLock<T> {
pub async fn read(&self) -> RwLockReadGuard<'_, T> {
self.s.acquire(1).await;
RwLockReadGuard { lock: self }
}
pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
if self.s.try_acquire(1) {
Some(RwLockReadGuard { lock: self })
} else {
None
}
}
}
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct RwLockReadGuard<'a, T: ?Sized> {
pub(super) lock: &'a RwLock<T>,
}
unsafe impl<T: ?Sized + Sync> Send for RwLockReadGuard<'_, T> {}
unsafe impl<T: ?Sized + Send + Sync> Sync for RwLockReadGuard<'_, T> {}
impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> {
fn drop(&mut self) {
self.lock.s.release(1);
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.c.get() }
}
}
impl<'a, T: ?Sized> RwLockReadGuard<'a, T> {
pub fn map<U, F>(orig: Self, f: F) -> MappedRwLockReadGuard<'a, U>
where
F: FnOnce(&T) -> &U,
U: ?Sized,
{
let d = NonNull::from(f(&*orig));
let orig = ManuallyDrop::new(orig);
MappedRwLockReadGuard::new(d, &orig.lock.s)
}
pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedRwLockReadGuard<'a, U>, Self>
where
F: FnOnce(&T) -> Option<&U>,
U: ?Sized,
{
match f(&*orig) {
Some(d) => {
let d = NonNull::from(d);
let orig = ManuallyDrop::new(orig);
Ok(MappedRwLockReadGuard::new(d, &orig.lock.s))
}
None => Err(orig),
}
}
}