use crate::sync::rwlock::RwLock;
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::mem::ManuallyDrop;
use std::ops;
use std::sync::Arc;
pub struct OwnedRwLockReadGuard<T: ?Sized, U: ?Sized = T> {
#[cfg(all(tokio_unstable, feature = "tracing"))]
pub(super) resource_span: tracing::Span,
pub(super) lock: ManuallyDrop<Arc<RwLock<T>>>,
pub(super) data: *const U,
pub(super) _p: PhantomData<T>,
}
impl<T: ?Sized, U: ?Sized> OwnedRwLockReadGuard<T, U> {
#[inline]
pub fn map<F, V: ?Sized>(mut this: Self, f: F) -> OwnedRwLockReadGuard<T, V>
where
F: FnOnce(&U) -> &V,
{
let data = f(&*this) as *const V;
let lock = unsafe { ManuallyDrop::take(&mut this.lock) };
#[cfg(all(tokio_unstable, feature = "tracing"))]
let resource_span = this.resource_span.clone();
mem::forget(this);
OwnedRwLockReadGuard {
lock: ManuallyDrop::new(lock),
data,
_p: PhantomData,
#[cfg(all(tokio_unstable, feature = "tracing"))]
resource_span,
}
}
#[inline]
pub fn try_map<F, V: ?Sized>(mut this: Self, f: F) -> Result<OwnedRwLockReadGuard<T, V>, Self>
where
F: FnOnce(&U) -> Option<&V>,
{
let data = match f(&*this) {
Some(data) => data as *const V,
None => return Err(this),
};
let lock = unsafe { ManuallyDrop::take(&mut this.lock) };
#[cfg(all(tokio_unstable, feature = "tracing"))]
let resource_span = this.resource_span.clone();
mem::forget(this);
Ok(OwnedRwLockReadGuard {
lock: ManuallyDrop::new(lock),
data,
_p: PhantomData,
#[cfg(all(tokio_unstable, feature = "tracing"))]
resource_span,
})
}
}
impl<T: ?Sized, U: ?Sized> ops::Deref for OwnedRwLockReadGuard<T, U> {
type Target = U;
fn deref(&self) -> &U {
unsafe { &*self.data }
}
}
impl<T: ?Sized, U: ?Sized> fmt::Debug for OwnedRwLockReadGuard<T, U>
where
U: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: ?Sized, U: ?Sized> fmt::Display for OwnedRwLockReadGuard<T, U>
where
U: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: ?Sized, U: ?Sized> Drop for OwnedRwLockReadGuard<T, U> {
fn drop(&mut self) {
self.lock.s.release(1);
unsafe { ManuallyDrop::drop(&mut self.lock) };
#[cfg(all(tokio_unstable, feature = "tracing"))]
self.resource_span.in_scope(|| {
tracing::trace!(
target: "runtime::resource::state_update",
current_readers = 1,
current_readers.op = "sub",
)
});
}
}