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