• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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