1use std::fmt;
2use std::future::Future;
3use std::mem::ManuallyDrop;
4use std::pin::Pin;
5use std::sync::Arc;
6use std::task::{Context, Poll};
7
8use super::raw::{RawRead, RawUpgradableRead, RawUpgrade, RawWrite};
9use super::{
10 RwLock, RwLockReadGuard, RwLockReadGuardArc, RwLockUpgradableReadGuard,
11 RwLockUpgradableReadGuardArc, RwLockWriteGuard, RwLockWriteGuardArc,
12};
13
14/// The future returned by [`RwLock::read`].
15pub struct Read<'a, T: ?Sized> {
16 /// Raw read lock acquisition future, doesn't depend on `T`.
17 pub(super) raw: RawRead<'a>,
18
19 /// Pointer to the value protected by the lock. Covariant in `T`.
20 pub(super) value: *const T,
21}
22
23unsafe impl<T: Sync + ?Sized> Send for Read<'_, T> {}
24unsafe impl<T: Sync + ?Sized> Sync for Read<'_, T> {}
25
26impl<T: ?Sized> fmt::Debug for Read<'_, T> {
27 #[inline]
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.write_str(data:"Read { .. }")
30 }
31}
32
33impl<T: ?Sized> Unpin for Read<'_, T> {}
34
35impl<'a, T: ?Sized> Future for Read<'a, T> {
36 type Output = RwLockReadGuard<'a, T>;
37
38 #[inline]
39 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
40 ready!(Pin::new(&mut self.raw).poll(cx));
41
42 Poll::Ready(RwLockReadGuard {
43 lock: self.raw.lock,
44 value: self.value,
45 })
46 }
47}
48
49/// The future returned by [`RwLock::read_arc`].
50pub struct ReadArc<'a, T> {
51 /// Raw read lock acquisition future, doesn't depend on `T`.
52 pub(super) raw: RawRead<'a>,
53
54 // FIXME: Could be covariant in T
55 pub(super) lock: &'a Arc<RwLock<T>>,
56}
57
58unsafe impl<T: Send + Sync> Send for ReadArc<'_, T> {}
59unsafe impl<T: Send + Sync> Sync for ReadArc<'_, T> {}
60
61impl<T> fmt::Debug for ReadArc<'_, T> {
62 #[inline]
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 f.write_str(data:"ReadArc { .. }")
65 }
66}
67
68impl<T> Unpin for ReadArc<'_, T> {}
69
70impl<'a, T> Future for ReadArc<'a, T> {
71 type Output = RwLockReadGuardArc<T>;
72
73 #[inline]
74 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
75 ready!(Pin::new(&mut self.raw).poll(cx));
76
77 // SAFETY: we just acquired a read lock
78 Poll::Ready(unsafe { RwLockReadGuardArc::from_arc(self.lock.clone()) })
79 }
80}
81
82/// The future returned by [`RwLock::upgradable_read`].
83pub struct UpgradableRead<'a, T: ?Sized> {
84 /// Raw upgradable read lock acquisition future, doesn't depend on `T`.
85 pub(super) raw: RawUpgradableRead<'a>,
86
87 /// Pointer to the value protected by the lock. Invariant in `T`
88 /// as the upgradable lock could provide write access.
89 pub(super) value: *mut T,
90}
91
92unsafe impl<T: Send + Sync + ?Sized> Send for UpgradableRead<'_, T> {}
93unsafe impl<T: Sync + ?Sized> Sync for UpgradableRead<'_, T> {}
94
95impl<T: ?Sized> fmt::Debug for UpgradableRead<'_, T> {
96 #[inline]
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 f.write_str(data:"UpgradableRead { .. }")
99 }
100}
101
102impl<T: ?Sized> Unpin for UpgradableRead<'_, T> {}
103
104impl<'a, T: ?Sized> Future for UpgradableRead<'a, T> {
105 type Output = RwLockUpgradableReadGuard<'a, T>;
106
107 #[inline]
108 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
109 ready!(Pin::new(&mut self.raw).poll(cx));
110
111 Poll::Ready(RwLockUpgradableReadGuard {
112 lock: self.raw.lock,
113 value: self.value,
114 })
115 }
116}
117
118/// The future returned by [`RwLock::upgradable_read_arc`].
119pub struct UpgradableReadArc<'a, T: ?Sized> {
120 /// Raw upgradable read lock acquisition future, doesn't depend on `T`.
121 pub(super) raw: RawUpgradableRead<'a>,
122
123 pub(super) lock: &'a Arc<RwLock<T>>,
124}
125
126unsafe impl<T: Send + Sync + ?Sized> Send for UpgradableReadArc<'_, T> {}
127unsafe impl<T: Send + Sync + ?Sized> Sync for UpgradableReadArc<'_, T> {}
128
129impl<T: ?Sized> fmt::Debug for UpgradableReadArc<'_, T> {
130 #[inline]
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.write_str(data:"UpgradableReadArc { .. }")
133 }
134}
135
136impl<T: ?Sized> Unpin for UpgradableReadArc<'_, T> {}
137
138impl<'a, T: ?Sized> Future for UpgradableReadArc<'a, T> {
139 type Output = RwLockUpgradableReadGuardArc<T>;
140
141 #[inline]
142 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
143 ready!(Pin::new(&mut self.raw).poll(cx));
144 Poll::Ready(RwLockUpgradableReadGuardArc {
145 lock: self.lock.clone(),
146 })
147 }
148}
149
150/// The future returned by [`RwLock::write`].
151pub struct Write<'a, T: ?Sized> {
152 /// Raw write lock acquisition future, doesn't depend on `T`.
153 pub(super) raw: RawWrite<'a>,
154
155 /// Pointer to the value protected by the lock. Invariant in `T`.
156 pub(super) value: *mut T,
157}
158
159unsafe impl<T: Send + ?Sized> Send for Write<'_, T> {}
160unsafe impl<T: Sync + ?Sized> Sync for Write<'_, T> {}
161
162impl<T: ?Sized> fmt::Debug for Write<'_, T> {
163 #[inline]
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 f.write_str(data:"Write { .. }")
166 }
167}
168
169impl<T: ?Sized> Unpin for Write<'_, T> {}
170
171impl<'a, T: ?Sized> Future for Write<'a, T> {
172 type Output = RwLockWriteGuard<'a, T>;
173
174 #[inline]
175 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
176 ready!(Pin::new(&mut self.raw).poll(cx));
177
178 Poll::Ready(RwLockWriteGuard {
179 lock: self.raw.lock,
180 value: self.value,
181 })
182 }
183}
184
185/// The future returned by [`RwLock::write_arc`].
186pub struct WriteArc<'a, T: ?Sized> {
187 /// Raw write lock acquisition future, doesn't depend on `T`.
188 pub(super) raw: RawWrite<'a>,
189
190 pub(super) lock: &'a Arc<RwLock<T>>,
191}
192
193unsafe impl<T: Send + Sync + ?Sized> Send for WriteArc<'_, T> {}
194unsafe impl<T: Send + Sync + ?Sized> Sync for WriteArc<'_, T> {}
195
196impl<T: ?Sized> fmt::Debug for WriteArc<'_, T> {
197 #[inline]
198 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 f.write_str(data:"WriteArc { .. }")
200 }
201}
202
203impl<T: ?Sized> Unpin for WriteArc<'_, T> {}
204
205impl<'a, T: ?Sized> Future for WriteArc<'a, T> {
206 type Output = RwLockWriteGuardArc<T>;
207
208 #[inline]
209 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
210 ready!(Pin::new(&mut self.raw).poll(cx));
211
212 Poll::Ready(RwLockWriteGuardArc {
213 lock: self.lock.clone(),
214 })
215 }
216}
217
218/// The future returned by [`RwLockUpgradableReadGuard::upgrade`].
219pub struct Upgrade<'a, T: ?Sized> {
220 /// Raw read lock upgrade future, doesn't depend on `T`.
221 pub(super) raw: RawUpgrade<'a>,
222
223 /// Pointer to the value protected by the lock. Invariant in `T`.
224 pub(super) value: *mut T,
225}
226
227unsafe impl<T: Send + ?Sized> Send for Upgrade<'_, T> {}
228unsafe impl<T: Sync + ?Sized> Sync for Upgrade<'_, T> {}
229
230impl<T: ?Sized> fmt::Debug for Upgrade<'_, T> {
231 #[inline]
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 f.debug_struct(name:"Upgrade").finish()
234 }
235}
236
237impl<T: ?Sized> Unpin for Upgrade<'_, T> {}
238
239impl<'a, T: ?Sized> Future for Upgrade<'a, T> {
240 type Output = RwLockWriteGuard<'a, T>;
241
242 #[inline]
243 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
244 let lock: &RawRwLock = ready!(Pin::new(&mut self.raw).poll(cx));
245
246 Poll::Ready(RwLockWriteGuard {
247 lock,
248 value: self.value,
249 })
250 }
251}
252
253/// The future returned by [`RwLockUpgradableReadGuardArc::upgrade`].
254pub struct UpgradeArc<T: ?Sized> {
255 /// Raw read lock upgrade future, doesn't depend on `T`.
256 /// `'static` is a lie, this field is actually referencing the
257 /// `Arc` data. But since this struct also stores said `Arc`, we know
258 /// this value will be alive as long as the struct is.
259 ///
260 /// Yes, one field of the `ArcUpgrade` struct is referencing another.
261 /// Such self-references are usually not sound without pinning.
262 /// However, in this case, there is an indirection via the heap;
263 /// moving the `ArcUpgrade` won't move the heap allocation of the `Arc`,
264 /// so the reference inside `RawUpgrade` isn't invalidated.
265 pub(super) raw: ManuallyDrop<RawUpgrade<'static>>,
266
267 /// Pointer to the value protected by the lock. Invariant in `T`.
268 pub(super) lock: ManuallyDrop<Arc<RwLock<T>>>,
269}
270
271impl<T: ?Sized> fmt::Debug for UpgradeArc<T> {
272 #[inline]
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 f.debug_struct(name:"ArcUpgrade").finish()
275 }
276}
277
278impl<T: ?Sized> Unpin for UpgradeArc<T> {}
279
280impl<T: ?Sized> Future for UpgradeArc<T> {
281 type Output = RwLockWriteGuardArc<T>;
282
283 #[inline]
284 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
285 ready!(Pin::new(&mut *self.raw).poll(cx));
286
287 Poll::Ready(RwLockWriteGuardArc {
288 lock: unsafe { ManuallyDrop::take(&mut self.lock) },
289 })
290 }
291}
292
293impl<T: ?Sized> Drop for UpgradeArc<T> {
294 #[inline]
295 fn drop(&mut self) {
296 if !self.raw.is_ready() {
297 // SAFETY: we drop the `Arc` (decrementing the reference count)
298 // only if this future was cancelled before returning an
299 // upgraded lock.
300 unsafe {
301 ManuallyDrop::drop(&mut self.raw);
302 ManuallyDrop::drop(&mut self.lock);
303 };
304 }
305 }
306}
307