use std::fmt::{Debug, Display}; use std::hash::Hash; use std::marker::PhantomData; use std::ops::Deref; use lock_api::RawRwLock; use crate::lockable::RawLock; use crate::ThreadKey; use super::{RwLock, RwLockReadGuard, RwLockReadRef}; // These impls make things slightly easier because now you can use // `println!("{guard}")` instead of `println!("{}", *guard)` #[mutants::skip] // hashing involves PRNG and is hard to test #[cfg(not(tarpaulin_include))] impl Hash for RwLockReadRef<'_, T, R> { fn hash(&self, state: &mut H) { self.deref().hash(state) } } #[mutants::skip] #[cfg(not(tarpaulin_include))] impl Debug for RwLockReadRef<'_, T, R> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) } } impl Display for RwLockReadRef<'_, T, R> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } } impl Deref for RwLockReadRef<'_, T, R> { type Target = T; fn deref(&self) -> &Self::Target { // safety: this is the only type that can use `value`, and there's // a reference to this type, so there cannot be any mutable // references to this value. unsafe { &*self.0.data.get() } } } impl AsRef for RwLockReadRef<'_, T, R> { fn as_ref(&self) -> &T { self } } impl Drop for RwLockReadRef<'_, T, R> { fn drop(&mut self) { // safety: this guard is being destroyed, so the data cannot be // accessed without locking again unsafe { self.0.raw_unlock_read() } } } impl<'a, T: ?Sized, R: RawRwLock> RwLockReadRef<'a, T, R> { /// Creates an immutable reference for the underlying data of an [`RwLock`] /// without locking it or taking ownership of the key. #[must_use] pub(crate) const unsafe fn new(mutex: &'a RwLock) -> Self { Self(mutex, PhantomData) } } #[mutants::skip] // hashing involves PRNG and is hard to test #[cfg(not(tarpaulin_include))] impl Hash for RwLockReadGuard<'_, T, R> { fn hash(&self, state: &mut H) { self.deref().hash(state) } } #[mutants::skip] #[cfg(not(tarpaulin_include))] impl Debug for RwLockReadGuard<'_, T, R> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Debug::fmt(&**self, f) } } impl Display for RwLockReadGuard<'_, T, R> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Display::fmt(&**self, f) } } impl Deref for RwLockReadGuard<'_, T, R> { type Target = T; fn deref(&self) -> &Self::Target { &self.rwlock } } impl AsRef for RwLockReadGuard<'_, T, R> { fn as_ref(&self) -> &T { self } } impl<'a, T: ?Sized, R: RawRwLock> RwLockReadGuard<'a, T, R> { /// Create a guard to the given mutex. Undefined if multiple guards to the /// same mutex exist at once. #[must_use] pub(super) const unsafe fn new(rwlock: &'a RwLock, thread_key: ThreadKey) -> Self { Self { rwlock: RwLockReadRef(rwlock, PhantomData), thread_key, } } } unsafe impl Sync for RwLockReadRef<'_, T, R> {}