use std::fmt;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::ops::DerefMut;
use std::ptr::NonNull;
use std::sync::Arc;
use crate::rwlock::OwnedMappedRwLockReadGuard;
use crate::rwlock::RwLock;
#[must_use = "if unused the RwLock will immediately unlock"]
pub struct OwnedMappedRwLockWriteGuard<T: ?Sized, U: ?Sized> {
d: NonNull<U>,
lock: Arc<RwLock<T>>,
permits_acquired: usize,
variance: PhantomData<*mut U>,
}
unsafe impl<T: ?Sized + Send + Sync, U: ?Sized + Sync> Sync for OwnedMappedRwLockWriteGuard<T, U> {}
unsafe impl<T: ?Sized + Send + Sync, U: ?Sized + Send> Send for OwnedMappedRwLockWriteGuard<T, U> {}
impl<T: ?Sized, U: ?Sized> OwnedMappedRwLockWriteGuard<T, U> {
pub(crate) fn new(d: NonNull<U>, lock: Arc<RwLock<T>>, permits_acquired: usize) -> Self {
Self {
d,
lock,
permits_acquired,
variance: PhantomData,
}
}
}
impl<T: ?Sized, U: ?Sized> Drop for OwnedMappedRwLockWriteGuard<T, U> {
fn drop(&mut self) {
self.lock.s.release(self.permits_acquired);
}
}
impl<T: ?Sized, U: ?Sized + fmt::Debug> fmt::Debug for OwnedMappedRwLockWriteGuard<T, U> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: ?Sized, U: ?Sized + fmt::Display> fmt::Display for OwnedMappedRwLockWriteGuard<T, U> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: ?Sized, U: ?Sized> Deref for OwnedMappedRwLockWriteGuard<T, U> {
type Target = U;
fn deref(&self) -> &Self::Target {
unsafe { self.d.as_ref() }
}
}
impl<T: ?Sized, U: ?Sized> DerefMut for OwnedMappedRwLockWriteGuard<T, U> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.d.as_mut() }
}
}
impl<T: ?Sized, U: ?Sized> OwnedMappedRwLockWriteGuard<T, U> {
pub fn map<V, F>(mut orig: Self, f: F) -> OwnedMappedRwLockWriteGuard<T, V>
where
F: FnOnce(&mut U) -> &mut V,
V: ?Sized,
{
let d = NonNull::from(f(unsafe { orig.d.as_mut() }));
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<V, F>(mut orig: Self, f: F) -> Result<OwnedMappedRwLockWriteGuard<T, V>, Self>
where
F: FnOnce(&mut U) -> Option<&mut V>,
V: ?Sized,
{
match f(unsafe { orig.d.as_mut() }) {
Some(d) => {
let d = NonNull::from(d);
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))
}
None => Err(orig),
}
}
pub fn downgrade(self) -> OwnedMappedRwLockReadGuard<T, U> {
let guard = ManuallyDrop::new(self);
guard.lock.s.release(guard.permits_acquired - 1);
let lock = unsafe { std::ptr::read(&guard.lock) };
OwnedMappedRwLockReadGuard::new(guard.d, lock)
}
}