1 use crate::sync::rwlock::owned_read_guard::OwnedRwLockReadGuard; 2 use crate::sync::rwlock::owned_write_guard_mapped::OwnedRwLockMappedWriteGuard; 3 use crate::sync::rwlock::RwLock; 4 use std::fmt; 5 use std::marker::PhantomData; 6 use std::mem::{self, ManuallyDrop}; 7 use std::ops; 8 use std::sync::Arc; 9 10 /// Owned RAII structure used to release the exclusive write access of a lock when 11 /// dropped. 12 /// 13 /// This structure is created by the [`write_owned`] method 14 /// on [`RwLock`]. 15 /// 16 /// [`write_owned`]: method@crate::sync::RwLock::write_owned 17 /// [`RwLock`]: struct@crate::sync::RwLock 18 pub struct OwnedRwLockWriteGuard<T: ?Sized> { 19 pub(super) permits_acquired: u32, 20 // ManuallyDrop allows us to destructure into this field without running the destructor. 21 pub(super) lock: ManuallyDrop<Arc<RwLock<T>>>, 22 pub(super) data: *mut T, 23 pub(super) _p: PhantomData<T>, 24 } 25 26 impl<T: ?Sized> OwnedRwLockWriteGuard<T> { 27 /// Make a new [`OwnedRwLockMappedWriteGuard`] for a component of the locked 28 /// data. 29 /// 30 /// This operation cannot fail as the `OwnedRwLockWriteGuard` passed in 31 /// already locked the data. 32 /// 33 /// This is an associated function that needs to be used as 34 /// `OwnedRwLockWriteGuard::map(..)`. A method would interfere with methods 35 /// of the same name on the contents of the locked data. 36 /// 37 /// # Examples 38 /// 39 /// ``` 40 /// use std::sync::Arc; 41 /// use tokio::sync::{RwLock, OwnedRwLockWriteGuard}; 42 /// 43 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] 44 /// struct Foo(u32); 45 /// 46 /// # #[tokio::main] 47 /// # async fn main() { 48 /// let lock = Arc::new(RwLock::new(Foo(1))); 49 /// 50 /// { 51 /// let lock = Arc::clone(&lock); 52 /// let mut mapped = OwnedRwLockWriteGuard::map(lock.write_owned().await, |f| &mut f.0); 53 /// *mapped = 2; 54 /// } 55 /// 56 /// assert_eq!(Foo(2), *lock.read().await); 57 /// # } 58 /// ``` 59 #[inline] map<F, U: ?Sized>(mut this: Self, f: F) -> OwnedRwLockMappedWriteGuard<T, U> where F: FnOnce(&mut T) -> &mut U,60 pub fn map<F, U: ?Sized>(mut this: Self, f: F) -> OwnedRwLockMappedWriteGuard<T, U> 61 where 62 F: FnOnce(&mut T) -> &mut U, 63 { 64 let data = f(&mut *this) as *mut U; 65 let lock = unsafe { ManuallyDrop::take(&mut this.lock) }; 66 let permits_acquired = this.permits_acquired; 67 // NB: Forget to avoid drop impl from being called. 68 mem::forget(this); 69 OwnedRwLockMappedWriteGuard { 70 permits_acquired, 71 lock: ManuallyDrop::new(lock), 72 data, 73 _p: PhantomData, 74 } 75 } 76 77 /// Attempts to make a new [`OwnedRwLockMappedWriteGuard`] for a component 78 /// of the locked data. The original guard is returned if the closure 79 /// returns `None`. 80 /// 81 /// This operation cannot fail as the `OwnedRwLockWriteGuard` passed in 82 /// already locked the data. 83 /// 84 /// This is an associated function that needs to be 85 /// used as `OwnedRwLockWriteGuard::try_map(...)`. A method would interfere 86 /// with methods of the same name on the contents of the locked data. 87 /// 88 /// [`RwLockMappedWriteGuard`]: struct@crate::sync::RwLockMappedWriteGuard 89 /// 90 /// # Examples 91 /// 92 /// ``` 93 /// use std::sync::Arc; 94 /// use tokio::sync::{RwLock, OwnedRwLockWriteGuard}; 95 /// 96 /// #[derive(Debug, Clone, Copy, PartialEq, Eq)] 97 /// struct Foo(u32); 98 /// 99 /// # #[tokio::main] 100 /// # async fn main() { 101 /// let lock = Arc::new(RwLock::new(Foo(1))); 102 /// 103 /// { 104 /// let guard = Arc::clone(&lock).write_owned().await; 105 /// let mut guard = OwnedRwLockWriteGuard::try_map(guard, |f| Some(&mut f.0)).expect("should not fail"); 106 /// *guard = 2; 107 /// } 108 /// 109 /// assert_eq!(Foo(2), *lock.read().await); 110 /// # } 111 /// ``` 112 #[inline] try_map<F, U: ?Sized>( mut this: Self, f: F, ) -> Result<OwnedRwLockMappedWriteGuard<T, U>, Self> where F: FnOnce(&mut T) -> Option<&mut U>,113 pub fn try_map<F, U: ?Sized>( 114 mut this: Self, 115 f: F, 116 ) -> Result<OwnedRwLockMappedWriteGuard<T, U>, Self> 117 where 118 F: FnOnce(&mut T) -> Option<&mut U>, 119 { 120 let data = match f(&mut *this) { 121 Some(data) => data as *mut U, 122 None => return Err(this), 123 }; 124 let permits_acquired = this.permits_acquired; 125 let lock = unsafe { ManuallyDrop::take(&mut this.lock) }; 126 // NB: Forget to avoid drop impl from being called. 127 mem::forget(this); 128 Ok(OwnedRwLockMappedWriteGuard { 129 permits_acquired, 130 lock: ManuallyDrop::new(lock), 131 data, 132 _p: PhantomData, 133 }) 134 } 135 136 /// Converts this `OwnedRwLockWriteGuard` into an 137 /// `OwnedRwLockMappedWriteGuard`. This method can be used to store a 138 /// non-mapped guard in a struct field that expects a mapped guard. 139 /// 140 /// This is equivalent to calling `OwnedRwLockWriteGuard::map(guard, |me| me)`. 141 #[inline] into_mapped(this: Self) -> OwnedRwLockMappedWriteGuard<T>142 pub fn into_mapped(this: Self) -> OwnedRwLockMappedWriteGuard<T> { 143 Self::map(this, |me| me) 144 } 145 146 /// Atomically downgrades a write lock into a read lock without allowing 147 /// any writers to take exclusive access of the lock in the meantime. 148 /// 149 /// **Note:** This won't *necessarily* allow any additional readers to acquire 150 /// locks, since [`RwLock`] is fair and it is possible that a writer is next 151 /// in line. 152 /// 153 /// Returns an RAII guard which will drop this read access of the `RwLock` 154 /// when dropped. 155 /// 156 /// # Examples 157 /// 158 /// ``` 159 /// # use tokio::sync::RwLock; 160 /// # use std::sync::Arc; 161 /// # 162 /// # #[tokio::main] 163 /// # async fn main() { 164 /// let lock = Arc::new(RwLock::new(1)); 165 /// 166 /// let n = lock.clone().write_owned().await; 167 /// 168 /// let cloned_lock = lock.clone(); 169 /// let handle = tokio::spawn(async move { 170 /// *cloned_lock.write_owned().await = 2; 171 /// }); 172 /// 173 /// let n = n.downgrade(); 174 /// assert_eq!(*n, 1, "downgrade is atomic"); 175 /// 176 /// drop(n); 177 /// handle.await.unwrap(); 178 /// assert_eq!(*lock.read().await, 2, "second writer obtained write lock"); 179 /// # } 180 /// ``` downgrade(mut self) -> OwnedRwLockReadGuard<T>181 pub fn downgrade(mut self) -> OwnedRwLockReadGuard<T> { 182 let lock = unsafe { ManuallyDrop::take(&mut self.lock) }; 183 let data = self.data; 184 185 // Release all but one of the permits held by the write guard 186 lock.s.release((self.permits_acquired - 1) as usize); 187 // NB: Forget to avoid drop impl from being called. 188 mem::forget(self); 189 OwnedRwLockReadGuard { 190 lock: ManuallyDrop::new(lock), 191 data, 192 _p: PhantomData, 193 } 194 } 195 } 196 197 impl<T: ?Sized> ops::Deref for OwnedRwLockWriteGuard<T> { 198 type Target = T; 199 deref(&self) -> &T200 fn deref(&self) -> &T { 201 unsafe { &*self.data } 202 } 203 } 204 205 impl<T: ?Sized> ops::DerefMut for OwnedRwLockWriteGuard<T> { deref_mut(&mut self) -> &mut T206 fn deref_mut(&mut self) -> &mut T { 207 unsafe { &mut *self.data } 208 } 209 } 210 211 impl<T: ?Sized> fmt::Debug for OwnedRwLockWriteGuard<T> 212 where 213 T: fmt::Debug, 214 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 216 fmt::Debug::fmt(&**self, f) 217 } 218 } 219 220 impl<T: ?Sized> fmt::Display for OwnedRwLockWriteGuard<T> 221 where 222 T: fmt::Display, 223 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 225 fmt::Display::fmt(&**self, f) 226 } 227 } 228 229 impl<T: ?Sized> Drop for OwnedRwLockWriteGuard<T> { drop(&mut self)230 fn drop(&mut self) { 231 self.lock.s.release(self.permits_acquired as usize); 232 unsafe { ManuallyDrop::drop(&mut self.lock) }; 233 } 234 } 235