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