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