1 use crate::sync::rwlock::RwLock; 2 use std::fmt; 3 use std::marker::PhantomData; 4 use std::mem; 5 use std::mem::ManuallyDrop; 6 use std::ops; 7 use std::sync::Arc; 8 9 /// Owned RAII structure used to release the shared read access of a lock when 10 /// dropped. 11 /// 12 /// This structure is created by the [`read_owned`] method on 13 /// [`RwLock`]. 14 /// 15 /// [`read_owned`]: method@crate::sync::RwLock::read_owned 16 /// [`RwLock`]: struct@crate::sync::RwLock 17 pub struct OwnedRwLockReadGuard<T: ?Sized, U: ?Sized = T> { 18 // ManuallyDrop allows us to destructure into this field without running the destructor. 19 pub(super) lock: ManuallyDrop<Arc<RwLock<T>>>, 20 pub(super) data: *const U, 21 pub(super) _p: PhantomData<T>, 22 } 23 24 impl<T: ?Sized, U: ?Sized> OwnedRwLockReadGuard<T, U> { 25 /// Make a new `OwnedRwLockReadGuard` for a component of the locked data. 26 /// This operation cannot fail as the `OwnedRwLockReadGuard` passed in 27 /// already locked the data. 28 /// 29 /// This is an associated function that needs to be 30 /// used as `OwnedRwLockReadGuard::map(...)`. A method would interfere with 31 /// methods of the same name on the contents of the locked data. 32 /// 33 /// # Examples 34 /// 35 /// ``` 36 /// use std::sync::Arc; 37 /// use tokio::sync::{RwLock, OwnedRwLockReadGuard}; 38 /// 39 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] 40 /// struct Foo(u32); 41 /// 42 /// # #[tokio::main] 43 /// # async fn main() { 44 /// let lock = Arc::new(RwLock::new(Foo(1))); 45 /// 46 /// let guard = lock.read_owned().await; 47 /// let guard = OwnedRwLockReadGuard::map(guard, |f| &f.0); 48 /// 49 /// assert_eq!(1, *guard); 50 /// # } 51 /// ``` 52 #[inline] map<F, V: ?Sized>(mut this: Self, f: F) -> OwnedRwLockReadGuard<T, V> where F: FnOnce(&U) -> &V,53 pub fn map<F, V: ?Sized>(mut this: Self, f: F) -> OwnedRwLockReadGuard<T, V> 54 where 55 F: FnOnce(&U) -> &V, 56 { 57 let data = f(&*this) as *const V; 58 let lock = unsafe { ManuallyDrop::take(&mut this.lock) }; 59 // NB: Forget to avoid drop impl from being called. 60 mem::forget(this); 61 OwnedRwLockReadGuard { 62 lock: ManuallyDrop::new(lock), 63 data, 64 _p: PhantomData, 65 } 66 } 67 68 /// Attempts to make a new [`OwnedRwLockReadGuard`] for a component of the 69 /// locked data. The original guard is returned if the closure returns 70 /// `None`. 71 /// 72 /// This operation cannot fail as the `OwnedRwLockReadGuard` passed in 73 /// already locked the data. 74 /// 75 /// This is an associated function that needs to be used as 76 /// `OwnedRwLockReadGuard::try_map(..)`. A method would interfere with 77 /// methods of the same name on the contents of the locked data. 78 /// 79 /// # Examples 80 /// 81 /// ``` 82 /// use std::sync::Arc; 83 /// use tokio::sync::{RwLock, OwnedRwLockReadGuard}; 84 /// 85 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] 86 /// struct Foo(u32); 87 /// 88 /// # #[tokio::main] 89 /// # async fn main() { 90 /// let lock = Arc::new(RwLock::new(Foo(1))); 91 /// 92 /// let guard = lock.read_owned().await; 93 /// let guard = OwnedRwLockReadGuard::try_map(guard, |f| Some(&f.0)).expect("should not fail"); 94 /// 95 /// assert_eq!(1, *guard); 96 /// # } 97 /// ``` 98 #[inline] try_map<F, V: ?Sized>(mut this: Self, f: F) -> Result<OwnedRwLockReadGuard<T, V>, Self> where F: FnOnce(&U) -> Option<&V>,99 pub fn try_map<F, V: ?Sized>(mut this: Self, f: F) -> Result<OwnedRwLockReadGuard<T, V>, Self> 100 where 101 F: FnOnce(&U) -> Option<&V>, 102 { 103 let data = match f(&*this) { 104 Some(data) => data as *const V, 105 None => return Err(this), 106 }; 107 let lock = unsafe { ManuallyDrop::take(&mut this.lock) }; 108 // NB: Forget to avoid drop impl from being called. 109 mem::forget(this); 110 Ok(OwnedRwLockReadGuard { 111 lock: ManuallyDrop::new(lock), 112 data, 113 _p: PhantomData, 114 }) 115 } 116 } 117 118 impl<T: ?Sized, U: ?Sized> ops::Deref for OwnedRwLockReadGuard<T, U> { 119 type Target = U; 120 deref(&self) -> &U121 fn deref(&self) -> &U { 122 unsafe { &*self.data } 123 } 124 } 125 126 impl<T: ?Sized, U: ?Sized> fmt::Debug for OwnedRwLockReadGuard<T, U> 127 where 128 U: fmt::Debug, 129 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 131 fmt::Debug::fmt(&**self, f) 132 } 133 } 134 135 impl<T: ?Sized, U: ?Sized> fmt::Display for OwnedRwLockReadGuard<T, U> 136 where 137 U: fmt::Display, 138 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 140 fmt::Display::fmt(&**self, f) 141 } 142 } 143 144 impl<T: ?Sized, U: ?Sized> Drop for OwnedRwLockReadGuard<T, U> { drop(&mut self)145 fn drop(&mut self) { 146 self.lock.s.release(1); 147 unsafe { ManuallyDrop::drop(&mut self.lock) }; 148 } 149 } 150