1 | use std::cell::UnsafeCell; |
2 | use std::fmt; |
3 | use std::mem::{self, ManuallyDrop}; |
4 | use std::ops::{Deref, DerefMut}; |
5 | use std::ptr::{self, NonNull}; |
6 | use std::sync::Arc; |
7 | |
8 | pub(crate) mod futures; |
9 | mod raw; |
10 | |
11 | use self::futures::{ |
12 | Read, ReadArc, UpgradableRead, UpgradableReadArc, Upgrade, UpgradeArc, Write, WriteArc, |
13 | }; |
14 | use self::raw::{RawRwLock, RawUpgrade}; |
15 | |
16 | /// An async reader-writer lock. |
17 | /// |
18 | /// This type of lock allows multiple readers or one writer at any point in time. |
19 | /// |
20 | /// The locking strategy is write-preferring, which means writers are never starved. |
21 | /// Releasing a write lock wakes the next blocked reader and the next blocked writer. |
22 | /// |
23 | /// # Examples |
24 | /// |
25 | /// ``` |
26 | /// # futures_lite::future::block_on(async { |
27 | /// use async_lock::RwLock; |
28 | /// |
29 | /// let lock = RwLock::new(5); |
30 | /// |
31 | /// // Multiple read locks can be held at a time. |
32 | /// let r1 = lock.read().await; |
33 | /// let r2 = lock.read().await; |
34 | /// assert_eq!(*r1, 5); |
35 | /// assert_eq!(*r2, 5); |
36 | /// drop((r1, r2)); |
37 | /// |
38 | /// // Only one write lock can be held at a time. |
39 | /// let mut w = lock.write().await; |
40 | /// *w += 1; |
41 | /// assert_eq!(*w, 6); |
42 | /// # }) |
43 | /// ``` |
44 | pub struct RwLock<T: ?Sized> { |
45 | /// The underlying locking implementation. |
46 | /// Doesn't depend on `T`. |
47 | raw: RawRwLock, |
48 | |
49 | /// The inner value. |
50 | value: UnsafeCell<T>, |
51 | } |
52 | |
53 | unsafe impl<T: Send + ?Sized> Send for RwLock<T> {} |
54 | unsafe impl<T: Send + Sync + ?Sized> Sync for RwLock<T> {} |
55 | |
56 | impl<T> RwLock<T> { |
57 | /// Creates a new reader-writer lock. |
58 | /// |
59 | /// # Examples |
60 | /// |
61 | /// ``` |
62 | /// use async_lock::RwLock; |
63 | /// |
64 | /// let lock = RwLock::new(0); |
65 | /// ``` |
66 | #[must_use ] |
67 | #[inline ] |
68 | pub const fn new(t: T) -> RwLock<T> { |
69 | RwLock { |
70 | raw: RawRwLock::new(), |
71 | value: UnsafeCell::new(t), |
72 | } |
73 | } |
74 | |
75 | /// Unwraps the lock and returns the inner value. |
76 | /// |
77 | /// # Examples |
78 | /// |
79 | /// ``` |
80 | /// use async_lock::RwLock; |
81 | /// |
82 | /// let lock = RwLock::new(5); |
83 | /// assert_eq!(lock.into_inner(), 5); |
84 | /// ``` |
85 | #[must_use ] |
86 | #[inline ] |
87 | pub fn into_inner(self) -> T { |
88 | self.value.into_inner() |
89 | } |
90 | |
91 | /// Attempts to acquire an an owned, reference-counted read lock. |
92 | /// |
93 | /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a |
94 | /// guard is returned that releases the lock when dropped. |
95 | /// |
96 | /// # Examples |
97 | /// |
98 | /// ``` |
99 | /// # futures_lite::future::block_on(async { |
100 | /// use std::sync::Arc; |
101 | /// use async_lock::RwLock; |
102 | /// |
103 | /// let lock = Arc::new(RwLock::new(1)); |
104 | /// |
105 | /// let reader = lock.read_arc().await; |
106 | /// assert_eq!(*reader, 1); |
107 | /// |
108 | /// assert!(lock.try_read_arc().is_some()); |
109 | /// # }) |
110 | /// ``` |
111 | #[inline ] |
112 | pub fn try_read_arc(self: &Arc<Self>) -> Option<RwLockReadGuardArc<T>> { |
113 | if self.raw.try_read() { |
114 | let arc = self.clone(); |
115 | |
116 | // SAFETY: we previously acquired a read lock. |
117 | Some(unsafe { RwLockReadGuardArc::from_arc(arc) }) |
118 | } else { |
119 | None |
120 | } |
121 | } |
122 | |
123 | /// Acquires an owned, reference-counted read lock. |
124 | /// |
125 | /// Returns a guard that releases the lock when dropped. |
126 | /// |
127 | /// Note that attempts to acquire a read lock will block if there are also concurrent attempts |
128 | /// to acquire a write lock. |
129 | /// |
130 | /// # Examples |
131 | /// |
132 | /// ``` |
133 | /// # futures_lite::future::block_on(async { |
134 | /// use std::sync::Arc; |
135 | /// use async_lock::RwLock; |
136 | /// |
137 | /// let lock = Arc::new(RwLock::new(1)); |
138 | /// |
139 | /// let reader = lock.read_arc().await; |
140 | /// assert_eq!(*reader, 1); |
141 | /// |
142 | /// assert!(lock.try_read_arc().is_some()); |
143 | /// # }) |
144 | /// ``` |
145 | #[inline ] |
146 | pub fn read_arc<'a>(self: &'a Arc<Self>) -> ReadArc<'a, T> { |
147 | ReadArc { |
148 | raw: self.raw.read(), |
149 | lock: self, |
150 | } |
151 | } |
152 | } |
153 | |
154 | impl<T: ?Sized> RwLock<T> { |
155 | /// Attempts to acquire a read lock. |
156 | /// |
157 | /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a |
158 | /// guard is returned that releases the lock when dropped. |
159 | /// |
160 | /// # Examples |
161 | /// |
162 | /// ``` |
163 | /// # futures_lite::future::block_on(async { |
164 | /// use async_lock::RwLock; |
165 | /// |
166 | /// let lock = RwLock::new(1); |
167 | /// |
168 | /// let reader = lock.read().await; |
169 | /// assert_eq!(*reader, 1); |
170 | /// |
171 | /// assert!(lock.try_read().is_some()); |
172 | /// # }) |
173 | /// ``` |
174 | #[inline ] |
175 | pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> { |
176 | if self.raw.try_read() { |
177 | Some(RwLockReadGuard { |
178 | lock: &self.raw, |
179 | value: self.value.get(), |
180 | }) |
181 | } else { |
182 | None |
183 | } |
184 | } |
185 | |
186 | /// Acquires a read lock. |
187 | /// |
188 | /// Returns a guard that releases the lock when dropped. |
189 | /// |
190 | /// Note that attempts to acquire a read lock will block if there are also concurrent attempts |
191 | /// to acquire a write lock. |
192 | /// |
193 | /// # Examples |
194 | /// |
195 | /// ``` |
196 | /// # futures_lite::future::block_on(async { |
197 | /// use async_lock::RwLock; |
198 | /// |
199 | /// let lock = RwLock::new(1); |
200 | /// |
201 | /// let reader = lock.read().await; |
202 | /// assert_eq!(*reader, 1); |
203 | /// |
204 | /// assert!(lock.try_read().is_some()); |
205 | /// # }) |
206 | /// ``` |
207 | #[inline ] |
208 | pub fn read(&self) -> Read<'_, T> { |
209 | Read { |
210 | raw: self.raw.read(), |
211 | value: self.value.get(), |
212 | } |
213 | } |
214 | |
215 | /// Attempts to acquire a read lock with the possiblity to upgrade to a write lock. |
216 | /// |
217 | /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a |
218 | /// guard is returned that releases the lock when dropped. |
219 | /// |
220 | /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there |
221 | /// can be at most one upgradable read lock at a time. |
222 | /// |
223 | /// # Examples |
224 | /// |
225 | /// ``` |
226 | /// # futures_lite::future::block_on(async { |
227 | /// use async_lock::{RwLock, RwLockUpgradableReadGuard}; |
228 | /// |
229 | /// let lock = RwLock::new(1); |
230 | /// |
231 | /// let reader = lock.upgradable_read().await; |
232 | /// assert_eq!(*reader, 1); |
233 | /// assert_eq!(*lock.try_read().unwrap(), 1); |
234 | /// |
235 | /// let mut writer = RwLockUpgradableReadGuard::upgrade(reader).await; |
236 | /// *writer = 2; |
237 | /// # }) |
238 | /// ``` |
239 | #[inline ] |
240 | pub fn try_upgradable_read(&self) -> Option<RwLockUpgradableReadGuard<'_, T>> { |
241 | if self.raw.try_upgradable_read() { |
242 | Some(RwLockUpgradableReadGuard { |
243 | lock: &self.raw, |
244 | value: self.value.get(), |
245 | }) |
246 | } else { |
247 | None |
248 | } |
249 | } |
250 | |
251 | /// Acquires a read lock with the possiblity to upgrade to a write lock. |
252 | /// |
253 | /// Returns a guard that releases the lock when dropped. |
254 | /// |
255 | /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there |
256 | /// can be at most one upgradable read lock at a time. |
257 | /// |
258 | /// Note that attempts to acquire an upgradable read lock will block if there are concurrent |
259 | /// attempts to acquire another upgradable read lock or a write lock. |
260 | /// |
261 | /// # Examples |
262 | /// |
263 | /// ``` |
264 | /// # futures_lite::future::block_on(async { |
265 | /// use async_lock::{RwLock, RwLockUpgradableReadGuard}; |
266 | /// |
267 | /// let lock = RwLock::new(1); |
268 | /// |
269 | /// let reader = lock.upgradable_read().await; |
270 | /// assert_eq!(*reader, 1); |
271 | /// assert_eq!(*lock.try_read().unwrap(), 1); |
272 | /// |
273 | /// let mut writer = RwLockUpgradableReadGuard::upgrade(reader).await; |
274 | /// *writer = 2; |
275 | /// # }) |
276 | /// ``` |
277 | #[inline ] |
278 | pub fn upgradable_read(&self) -> UpgradableRead<'_, T> { |
279 | UpgradableRead { |
280 | raw: self.raw.upgradable_read(), |
281 | value: self.value.get(), |
282 | } |
283 | } |
284 | |
285 | /// Attempts to acquire an owned, reference-counted read lock with the possiblity to |
286 | /// upgrade to a write lock. |
287 | /// |
288 | /// If a read lock could not be acquired at this time, then [`None`] is returned. Otherwise, a |
289 | /// guard is returned that releases the lock when dropped. |
290 | /// |
291 | /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there |
292 | /// can be at most one upgradable read lock at a time. |
293 | /// |
294 | /// # Examples |
295 | /// |
296 | /// ``` |
297 | /// # futures_lite::future::block_on(async { |
298 | /// use std::sync::Arc; |
299 | /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc}; |
300 | /// |
301 | /// let lock = Arc::new(RwLock::new(1)); |
302 | /// |
303 | /// let reader = lock.upgradable_read_arc().await; |
304 | /// assert_eq!(*reader, 1); |
305 | /// assert_eq!(*lock.try_read_arc().unwrap(), 1); |
306 | /// |
307 | /// let mut writer = RwLockUpgradableReadGuardArc::upgrade(reader).await; |
308 | /// *writer = 2; |
309 | /// # }) |
310 | /// ``` |
311 | #[inline ] |
312 | pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<RwLockUpgradableReadGuardArc<T>> { |
313 | if self.raw.try_upgradable_read() { |
314 | Some(RwLockUpgradableReadGuardArc { lock: self.clone() }) |
315 | } else { |
316 | None |
317 | } |
318 | } |
319 | |
320 | /// Acquires an owned, reference-counted read lock with the possiblity |
321 | /// to upgrade to a write lock. |
322 | /// |
323 | /// Returns a guard that releases the lock when dropped. |
324 | /// |
325 | /// Upgradable read lock reserves the right to be upgraded to a write lock, which means there |
326 | /// can be at most one upgradable read lock at a time. |
327 | /// |
328 | /// Note that attempts to acquire an upgradable read lock will block if there are concurrent |
329 | /// attempts to acquire another upgradable read lock or a write lock. |
330 | /// |
331 | /// # Examples |
332 | /// |
333 | /// ``` |
334 | /// # futures_lite::future::block_on(async { |
335 | /// use std::sync::Arc; |
336 | /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc}; |
337 | /// |
338 | /// let lock = Arc::new(RwLock::new(1)); |
339 | /// |
340 | /// let reader = lock.upgradable_read_arc().await; |
341 | /// assert_eq!(*reader, 1); |
342 | /// assert_eq!(*lock.try_read_arc().unwrap(), 1); |
343 | /// |
344 | /// let mut writer = RwLockUpgradableReadGuardArc::upgrade(reader).await; |
345 | /// *writer = 2; |
346 | /// # }) |
347 | /// ``` |
348 | #[inline ] |
349 | pub fn upgradable_read_arc<'a>(self: &'a Arc<Self>) -> UpgradableReadArc<'a, T> { |
350 | UpgradableReadArc { |
351 | raw: self.raw.upgradable_read(), |
352 | lock: self, |
353 | } |
354 | } |
355 | |
356 | /// Attempts to acquire a write lock. |
357 | /// |
358 | /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise, a |
359 | /// guard is returned that releases the lock when dropped. |
360 | /// |
361 | /// # Examples |
362 | /// |
363 | /// ``` |
364 | /// # futures_lite::future::block_on(async { |
365 | /// use async_lock::RwLock; |
366 | /// |
367 | /// let lock = RwLock::new(1); |
368 | /// |
369 | /// assert!(lock.try_write().is_some()); |
370 | /// let reader = lock.read().await; |
371 | /// assert!(lock.try_write().is_none()); |
372 | /// # }) |
373 | /// ``` |
374 | #[inline ] |
375 | pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T>> { |
376 | if self.raw.try_write() { |
377 | Some(RwLockWriteGuard { |
378 | lock: &self.raw, |
379 | value: self.value.get(), |
380 | }) |
381 | } else { |
382 | None |
383 | } |
384 | } |
385 | |
386 | /// Acquires a write lock. |
387 | /// |
388 | /// Returns a guard that releases the lock when dropped. |
389 | /// |
390 | /// # Examples |
391 | /// |
392 | /// ``` |
393 | /// # futures_lite::future::block_on(async { |
394 | /// use async_lock::RwLock; |
395 | /// |
396 | /// let lock = RwLock::new(1); |
397 | /// |
398 | /// let writer = lock.write().await; |
399 | /// assert!(lock.try_read().is_none()); |
400 | /// # }) |
401 | /// ``` |
402 | #[inline ] |
403 | pub fn write(&self) -> Write<'_, T> { |
404 | Write { |
405 | raw: self.raw.write(), |
406 | value: self.value.get(), |
407 | } |
408 | } |
409 | |
410 | /// Attempts to acquire an owned, reference-counted write lock. |
411 | /// |
412 | /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise, a |
413 | /// guard is returned that releases the lock when dropped. |
414 | /// |
415 | /// # Examples |
416 | /// |
417 | /// ``` |
418 | /// # futures_lite::future::block_on(async { |
419 | /// use std::sync::Arc; |
420 | /// use async_lock::RwLock; |
421 | /// |
422 | /// let lock = Arc::new(RwLock::new(1)); |
423 | /// |
424 | /// assert!(lock.try_write_arc().is_some()); |
425 | /// let reader = lock.read_arc().await; |
426 | /// assert!(lock.try_write_arc().is_none()); |
427 | /// # }) |
428 | /// ``` |
429 | #[inline ] |
430 | pub fn try_write_arc(self: &Arc<Self>) -> Option<RwLockWriteGuardArc<T>> { |
431 | if self.raw.try_write() { |
432 | Some(RwLockWriteGuardArc { lock: self.clone() }) |
433 | } else { |
434 | None |
435 | } |
436 | } |
437 | |
438 | /// Acquires an owned, reference-counted write lock. |
439 | /// |
440 | /// Returns a guard that releases the lock when dropped. |
441 | /// |
442 | /// # Examples |
443 | /// |
444 | /// ``` |
445 | /// # futures_lite::future::block_on(async { |
446 | /// use std::sync::Arc; |
447 | /// use async_lock::RwLock; |
448 | /// |
449 | /// let lock = Arc::new(RwLock::new(1)); |
450 | /// |
451 | /// let writer = lock.write_arc().await; |
452 | /// assert!(lock.try_read_arc().is_none()); |
453 | /// # }) |
454 | /// ``` |
455 | #[inline ] |
456 | pub fn write_arc<'a>(self: &'a Arc<Self>) -> WriteArc<'a, T> { |
457 | WriteArc { |
458 | raw: self.raw.write(), |
459 | lock: self, |
460 | } |
461 | } |
462 | |
463 | /// Returns a mutable reference to the inner value. |
464 | /// |
465 | /// Since this call borrows the lock mutably, no actual locking takes place. The mutable borrow |
466 | /// statically guarantees no locks exist. |
467 | /// |
468 | /// # Examples |
469 | /// |
470 | /// ``` |
471 | /// # futures_lite::future::block_on(async { |
472 | /// use async_lock::RwLock; |
473 | /// |
474 | /// let mut lock = RwLock::new(1); |
475 | /// |
476 | /// *lock.get_mut() = 2; |
477 | /// assert_eq!(*lock.read().await, 2); |
478 | /// # }) |
479 | /// ``` |
480 | #[must_use ] |
481 | #[inline ] |
482 | pub fn get_mut(&mut self) -> &mut T { |
483 | unsafe { &mut *self.value.get() } |
484 | } |
485 | } |
486 | |
487 | impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLock<T> { |
488 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
489 | struct Locked; |
490 | impl fmt::Debug for Locked { |
491 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
492 | f.write_str(data:"<locked>" ) |
493 | } |
494 | } |
495 | |
496 | match self.try_read() { |
497 | None => f.debug_struct("RwLock" ).field(name:"value" , &Locked).finish(), |
498 | Some(guard: RwLockReadGuard<'_, T>) => f.debug_struct("RwLock" ).field(name:"value" , &&*guard).finish(), |
499 | } |
500 | } |
501 | } |
502 | |
503 | impl<T> From<T> for RwLock<T> { |
504 | #[inline ] |
505 | fn from(val: T) -> RwLock<T> { |
506 | RwLock::new(val) |
507 | } |
508 | } |
509 | |
510 | impl<T: Default + ?Sized> Default for RwLock<T> { |
511 | #[inline ] |
512 | fn default() -> RwLock<T> { |
513 | RwLock::new(Default::default()) |
514 | } |
515 | } |
516 | |
517 | /// A guard that releases the read lock when dropped. |
518 | #[clippy::has_significant_drop] |
519 | pub struct RwLockReadGuard<'a, T: ?Sized> { |
520 | /// Reference to underlying locking implementation. |
521 | /// Doesn't depend on `T`. |
522 | lock: &'a RawRwLock, |
523 | |
524 | /// Pointer to the value protected by the lock. Covariant in `T`. |
525 | value: *const T, |
526 | } |
527 | |
528 | unsafe impl<T: Sync + ?Sized> Send for RwLockReadGuard<'_, T> {} |
529 | unsafe impl<T: Sync + ?Sized> Sync for RwLockReadGuard<'_, T> {} |
530 | |
531 | impl<T: ?Sized> Drop for RwLockReadGuard<'_, T> { |
532 | #[inline ] |
533 | fn drop(&mut self) { |
534 | // SAFETY: we are dropping a read guard. |
535 | unsafe { |
536 | self.lock.read_unlock(); |
537 | } |
538 | } |
539 | } |
540 | |
541 | impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockReadGuard<'_, T> { |
542 | #[inline ] |
543 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
544 | fmt::Debug::fmt(&**self, f) |
545 | } |
546 | } |
547 | |
548 | impl<T: fmt::Display + ?Sized> fmt::Display for RwLockReadGuard<'_, T> { |
549 | #[inline ] |
550 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
551 | (**self).fmt(f) |
552 | } |
553 | } |
554 | |
555 | impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> { |
556 | type Target = T; |
557 | |
558 | #[inline ] |
559 | fn deref(&self) -> &T { |
560 | unsafe { &*self.value } |
561 | } |
562 | } |
563 | |
564 | /// An owned, reference-counting guard that releases the read lock when dropped. |
565 | #[clippy::has_significant_drop] |
566 | pub struct RwLockReadGuardArc<T> { |
567 | /// **WARNING**: This doesn't actually point to a `T`! |
568 | /// It points to a `RwLock<T>`, via a pointer obtained with `Arc::into_raw`. |
569 | /// We lie for covariance. |
570 | lock: NonNull<T>, |
571 | } |
572 | |
573 | unsafe impl<T: Send + Sync> Send for RwLockReadGuardArc<T> {} |
574 | unsafe impl<T: Send + Sync> Sync for RwLockReadGuardArc<T> {} |
575 | |
576 | impl<T> RwLockReadGuardArc<T> { |
577 | /// Constructs the underlying `Arc` back from the underlying `RwLock`. |
578 | /// |
579 | /// # Safety |
580 | /// |
581 | /// Both the returned `Arc` and the guard will decrement their reference |
582 | /// counts on drop! So one of the two must be forgotten. |
583 | #[inline ] |
584 | unsafe fn inner_arc(guard: &Self) -> ManuallyDrop<Arc<RwLock<T>>> { |
585 | ManuallyDrop::new(Arc::from_raw(guard.lock.as_ptr().cast())) |
586 | } |
587 | |
588 | /// Constructs a guard from the underlying `Arc`. |
589 | /// |
590 | /// # Safety |
591 | /// |
592 | /// A read lock must be acquired before calling this. |
593 | #[inline ] |
594 | unsafe fn from_arc(arc: Arc<RwLock<T>>) -> Self { |
595 | let ptr = Arc::into_raw(arc); |
596 | |
597 | Self { |
598 | lock: NonNull::new(ptr as *mut RwLock<T> as *mut T).unwrap(), |
599 | } |
600 | } |
601 | } |
602 | |
603 | impl<T> Drop for RwLockReadGuardArc<T> { |
604 | #[inline ] |
605 | fn drop(&mut self) { |
606 | // SAFETY: we are in `drop`, decrementing the reference count |
607 | // on purpose. |
608 | // We hold a read lock on the `RwLock`. |
609 | unsafe { |
610 | let arc: Arc> = ManuallyDrop::into_inner(Self::inner_arc(self)); |
611 | arc.raw.read_unlock(); |
612 | } |
613 | } |
614 | } |
615 | |
616 | impl<T: fmt::Debug> fmt::Debug for RwLockReadGuardArc<T> { |
617 | #[inline ] |
618 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
619 | fmt::Debug::fmt(&**self, f) |
620 | } |
621 | } |
622 | |
623 | impl<T: fmt::Display> fmt::Display for RwLockReadGuardArc<T> { |
624 | #[inline ] |
625 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
626 | (**self).fmt(f) |
627 | } |
628 | } |
629 | |
630 | impl<T> Deref for RwLockReadGuardArc<T> { |
631 | type Target = T; |
632 | |
633 | #[inline ] |
634 | fn deref(&self) -> &T { |
635 | // SAFETY: we use `ManuallyDrop` to avoid double-drop. |
636 | // We hold a read lock on the `RwLock`. |
637 | unsafe { |
638 | let arc: ManuallyDrop>> = Self::inner_arc(self); |
639 | &*arc.value.get() |
640 | } |
641 | } |
642 | } |
643 | |
644 | /// A guard that releases the upgradable read lock when dropped. |
645 | #[clippy::has_significant_drop] |
646 | pub struct RwLockUpgradableReadGuard<'a, T: ?Sized> { |
647 | /// Reference to underlying locking implementation. |
648 | /// Doesn't depend on `T`. |
649 | /// This guard holds a lock on the witer mutex! |
650 | lock: &'a RawRwLock, |
651 | |
652 | /// Pointer to the value protected by the lock. Invariant in `T` |
653 | /// as the upgradable lock could provide write access. |
654 | value: *mut T, |
655 | } |
656 | |
657 | impl<'a, T: ?Sized> Drop for RwLockUpgradableReadGuard<'a, T> { |
658 | #[inline ] |
659 | fn drop(&mut self) { |
660 | // SAFETY: we are dropping an upgradable read guard. |
661 | unsafe { |
662 | self.lock.upgradable_read_unlock(); |
663 | } |
664 | } |
665 | } |
666 | |
667 | unsafe impl<T: Send + Sync + ?Sized> Send for RwLockUpgradableReadGuard<'_, T> {} |
668 | unsafe impl<T: Sync + ?Sized> Sync for RwLockUpgradableReadGuard<'_, T> {} |
669 | |
670 | impl<'a, T: ?Sized> RwLockUpgradableReadGuard<'a, T> { |
671 | /// Downgrades into a regular reader guard. |
672 | /// |
673 | /// # Examples |
674 | /// |
675 | /// ``` |
676 | /// # futures_lite::future::block_on(async { |
677 | /// use async_lock::{RwLock, RwLockUpgradableReadGuard}; |
678 | /// |
679 | /// let lock = RwLock::new(1); |
680 | /// |
681 | /// let reader = lock.upgradable_read().await; |
682 | /// assert_eq!(*reader, 1); |
683 | /// |
684 | /// assert!(lock.try_upgradable_read().is_none()); |
685 | /// |
686 | /// let reader = RwLockUpgradableReadGuard::downgrade(reader); |
687 | /// |
688 | /// assert!(lock.try_upgradable_read().is_some()); |
689 | /// # }) |
690 | /// ``` |
691 | #[inline ] |
692 | pub fn downgrade(guard: Self) -> RwLockReadGuard<'a, T> { |
693 | let upgradable = ManuallyDrop::new(guard); |
694 | |
695 | // SAFETY: `guard` is an upgradable read lock. |
696 | unsafe { |
697 | upgradable.lock.downgrade_upgradable_read(); |
698 | }; |
699 | |
700 | RwLockReadGuard { |
701 | lock: upgradable.lock, |
702 | value: upgradable.value, |
703 | } |
704 | } |
705 | |
706 | /// Attempts to upgrade into a write lock. |
707 | /// |
708 | /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise, |
709 | /// an upgraded guard is returned that releases the write lock when dropped. |
710 | /// |
711 | /// This function can only fail if there are other active read locks. |
712 | /// |
713 | /// # Examples |
714 | /// |
715 | /// ``` |
716 | /// # futures_lite::future::block_on(async { |
717 | /// use async_lock::{RwLock, RwLockUpgradableReadGuard}; |
718 | /// |
719 | /// let lock = RwLock::new(1); |
720 | /// |
721 | /// let reader = lock.upgradable_read().await; |
722 | /// assert_eq!(*reader, 1); |
723 | /// |
724 | /// let reader2 = lock.read().await; |
725 | /// let reader = RwLockUpgradableReadGuard::try_upgrade(reader).unwrap_err(); |
726 | /// |
727 | /// drop(reader2); |
728 | /// let writer = RwLockUpgradableReadGuard::try_upgrade(reader).unwrap(); |
729 | /// # }) |
730 | /// ``` |
731 | #[inline ] |
732 | pub fn try_upgrade(guard: Self) -> Result<RwLockWriteGuard<'a, T>, Self> { |
733 | // If there are no readers, grab the write lock. |
734 | // SAFETY: `guard` is an upgradable read guard |
735 | if unsafe { guard.lock.try_upgrade() } { |
736 | let reader = ManuallyDrop::new(guard); |
737 | |
738 | Ok(RwLockWriteGuard { |
739 | lock: reader.lock, |
740 | value: reader.value, |
741 | }) |
742 | } else { |
743 | Err(guard) |
744 | } |
745 | } |
746 | |
747 | /// Upgrades into a write lock. |
748 | /// |
749 | /// # Examples |
750 | /// |
751 | /// ``` |
752 | /// # futures_lite::future::block_on(async { |
753 | /// use async_lock::{RwLock, RwLockUpgradableReadGuard}; |
754 | /// |
755 | /// let lock = RwLock::new(1); |
756 | /// |
757 | /// let reader = lock.upgradable_read().await; |
758 | /// assert_eq!(*reader, 1); |
759 | /// |
760 | /// let mut writer = RwLockUpgradableReadGuard::upgrade(reader).await; |
761 | /// *writer = 2; |
762 | /// # }) |
763 | /// ``` |
764 | #[inline ] |
765 | pub fn upgrade(guard: Self) -> Upgrade<'a, T> { |
766 | let reader = ManuallyDrop::new(guard); |
767 | |
768 | Upgrade { |
769 | // SAFETY: `reader` is an upgradable read guard |
770 | raw: unsafe { reader.lock.upgrade() }, |
771 | value: reader.value, |
772 | } |
773 | } |
774 | } |
775 | |
776 | impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockUpgradableReadGuard<'_, T> { |
777 | #[inline ] |
778 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
779 | fmt::Debug::fmt(&**self, f) |
780 | } |
781 | } |
782 | |
783 | impl<T: fmt::Display + ?Sized> fmt::Display for RwLockUpgradableReadGuard<'_, T> { |
784 | #[inline ] |
785 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
786 | (**self).fmt(f) |
787 | } |
788 | } |
789 | |
790 | impl<T: ?Sized> Deref for RwLockUpgradableReadGuard<'_, T> { |
791 | type Target = T; |
792 | |
793 | #[inline ] |
794 | fn deref(&self) -> &T { |
795 | unsafe { &*self.value } |
796 | } |
797 | } |
798 | |
799 | /// An owned, reference-counting guard that releases the upgradable read lock when dropped. |
800 | #[clippy::has_significant_drop] |
801 | pub struct RwLockUpgradableReadGuardArc<T: ?Sized> { |
802 | /// We want invariance, so no need for pointer tricks. |
803 | lock: Arc<RwLock<T>>, |
804 | } |
805 | |
806 | impl<T: ?Sized> Drop for RwLockUpgradableReadGuardArc<T> { |
807 | #[inline ] |
808 | fn drop(&mut self) { |
809 | // SAFETY: we are dropping an upgradable read guard. |
810 | unsafe { |
811 | self.lock.raw.upgradable_read_unlock(); |
812 | } |
813 | } |
814 | } |
815 | |
816 | unsafe impl<T: Send + Sync + ?Sized> Send for RwLockUpgradableReadGuardArc<T> {} |
817 | unsafe impl<T: Send + Sync + ?Sized> Sync for RwLockUpgradableReadGuardArc<T> {} |
818 | |
819 | impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockUpgradableReadGuardArc<T> { |
820 | #[inline ] |
821 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
822 | fmt::Debug::fmt(&**self, f) |
823 | } |
824 | } |
825 | |
826 | impl<T: fmt::Display + ?Sized> fmt::Display for RwLockUpgradableReadGuardArc<T> { |
827 | #[inline ] |
828 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
829 | (**self).fmt(f) |
830 | } |
831 | } |
832 | |
833 | impl<T: ?Sized> Deref for RwLockUpgradableReadGuardArc<T> { |
834 | type Target = T; |
835 | |
836 | #[inline ] |
837 | fn deref(&self) -> &T { |
838 | unsafe { &*self.lock.value.get() } |
839 | } |
840 | } |
841 | |
842 | impl<T> RwLockUpgradableReadGuardArc<T> { |
843 | /// Downgrades into a regular reader guard. |
844 | /// |
845 | /// # Examples |
846 | /// |
847 | /// ``` |
848 | /// # futures_lite::future::block_on(async { |
849 | /// use std::sync::Arc; |
850 | /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc}; |
851 | /// |
852 | /// let lock = Arc::new(RwLock::new(1)); |
853 | /// |
854 | /// let reader = lock.upgradable_read_arc().await; |
855 | /// assert_eq!(*reader, 1); |
856 | /// |
857 | /// assert!(lock.try_upgradable_read_arc().is_none()); |
858 | /// |
859 | /// let reader = RwLockUpgradableReadGuardArc::downgrade(reader); |
860 | /// |
861 | /// assert!(lock.try_upgradable_read_arc().is_some()); |
862 | /// # }) |
863 | /// ``` |
864 | #[inline ] |
865 | pub fn downgrade(guard: Self) -> RwLockReadGuardArc<T> { |
866 | // SAFETY: we hold an upgradable read lock, which we are downgrading. |
867 | unsafe { |
868 | guard.lock.raw.downgrade_upgradable_read(); |
869 | } |
870 | |
871 | // SAFETY: we just downgraded to a read lock. |
872 | unsafe { RwLockReadGuardArc::from_arc(Self::into_arc(guard)) } |
873 | } |
874 | } |
875 | |
876 | impl<T: ?Sized> RwLockUpgradableReadGuardArc<T> { |
877 | /// Consumes the lock (without dropping) and returns the underlying `Arc`. |
878 | #[inline ] |
879 | fn into_arc(guard: Self) -> Arc<RwLock<T>> { |
880 | let guard = ManuallyDrop::new(guard); |
881 | // SAFETY: `guard` is not used after this |
882 | unsafe { ptr::read(&guard.lock) } |
883 | } |
884 | |
885 | /// Attempts to upgrade into a write lock. |
886 | /// |
887 | /// If a write lock could not be acquired at this time, then [`None`] is returned. Otherwise, |
888 | /// an upgraded guard is returned that releases the write lock when dropped. |
889 | /// |
890 | /// This function can only fail if there are other active read locks. |
891 | /// |
892 | /// # Examples |
893 | /// |
894 | /// ``` |
895 | /// # futures_lite::future::block_on(async { |
896 | /// use std::sync::Arc; |
897 | /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc}; |
898 | /// |
899 | /// let lock = Arc::new(RwLock::new(1)); |
900 | /// |
901 | /// let reader = lock.upgradable_read_arc().await; |
902 | /// assert_eq!(*reader, 1); |
903 | /// |
904 | /// let reader2 = lock.read_arc().await; |
905 | /// let reader = RwLockUpgradableReadGuardArc::try_upgrade(reader).unwrap_err(); |
906 | /// |
907 | /// drop(reader2); |
908 | /// let writer = RwLockUpgradableReadGuardArc::try_upgrade(reader).unwrap(); |
909 | /// # }) |
910 | /// ``` |
911 | #[inline ] |
912 | pub fn try_upgrade(guard: Self) -> Result<RwLockWriteGuardArc<T>, Self> { |
913 | // SAFETY: We hold an upgradable read guard. |
914 | if unsafe { guard.lock.raw.try_upgrade() } { |
915 | Ok(RwLockWriteGuardArc { |
916 | lock: Self::into_arc(guard), |
917 | }) |
918 | } else { |
919 | Err(guard) |
920 | } |
921 | } |
922 | |
923 | /// Upgrades into a write lock. |
924 | /// |
925 | /// # Examples |
926 | /// |
927 | /// ``` |
928 | /// # futures_lite::future::block_on(async { |
929 | /// use std::sync::Arc; |
930 | /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc}; |
931 | /// |
932 | /// let lock = Arc::new(RwLock::new(1)); |
933 | /// |
934 | /// let reader = lock.upgradable_read_arc().await; |
935 | /// assert_eq!(*reader, 1); |
936 | /// |
937 | /// let mut writer = RwLockUpgradableReadGuardArc::upgrade(reader).await; |
938 | /// *writer = 2; |
939 | /// # }) |
940 | /// ``` |
941 | #[inline ] |
942 | pub fn upgrade(guard: Self) -> UpgradeArc<T> { |
943 | // We need to do some ugly lying about lifetimes; |
944 | // See the comment on the `raw` field of `ArcUpgrade` |
945 | // for an explanation. |
946 | |
947 | // SAFETY: we hold an upgradable read guard. |
948 | let raw: RawUpgrade<'_> = unsafe { guard.lock.raw.upgrade() }; |
949 | |
950 | // SAFETY: see above explanation. |
951 | let raw: RawUpgrade<'static> = unsafe { mem::transmute(raw) }; |
952 | |
953 | UpgradeArc { |
954 | raw: ManuallyDrop::new(raw), |
955 | lock: ManuallyDrop::new(Self::into_arc(guard)), |
956 | } |
957 | } |
958 | } |
959 | |
960 | /// A guard that releases the write lock when dropped. |
961 | #[clippy::has_significant_drop] |
962 | pub struct RwLockWriteGuard<'a, T: ?Sized> { |
963 | /// Reference to underlying locking implementation. |
964 | /// Doesn't depend on `T`. |
965 | /// This guard holds a lock on the witer mutex! |
966 | lock: &'a RawRwLock, |
967 | |
968 | /// Pointer to the value protected by the lock. Invariant in `T`. |
969 | value: *mut T, |
970 | } |
971 | |
972 | unsafe impl<T: Send + ?Sized> Send for RwLockWriteGuard<'_, T> {} |
973 | unsafe impl<T: Sync + ?Sized> Sync for RwLockWriteGuard<'_, T> {} |
974 | |
975 | impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { |
976 | #[inline ] |
977 | fn drop(&mut self) { |
978 | // SAFETY: we are dropping a write lock |
979 | unsafe { |
980 | self.lock.write_unlock(); |
981 | } |
982 | } |
983 | } |
984 | |
985 | impl<'a, T: ?Sized> RwLockWriteGuard<'a, T> { |
986 | /// Downgrades into a regular reader guard. |
987 | /// |
988 | /// # Examples |
989 | /// |
990 | /// ``` |
991 | /// # futures_lite::future::block_on(async { |
992 | /// use async_lock::{RwLock, RwLockWriteGuard}; |
993 | /// |
994 | /// let lock = RwLock::new(1); |
995 | /// |
996 | /// let mut writer = lock.write().await; |
997 | /// *writer += 1; |
998 | /// |
999 | /// assert!(lock.try_read().is_none()); |
1000 | /// |
1001 | /// let reader = RwLockWriteGuard::downgrade(writer); |
1002 | /// assert_eq!(*reader, 2); |
1003 | /// |
1004 | /// assert!(lock.try_read().is_some()); |
1005 | /// # }) |
1006 | /// ``` |
1007 | #[inline ] |
1008 | pub fn downgrade(guard: Self) -> RwLockReadGuard<'a, T> { |
1009 | let write = ManuallyDrop::new(guard); |
1010 | |
1011 | // SAFETY: `write` is a write guard |
1012 | unsafe { |
1013 | write.lock.downgrade_write(); |
1014 | } |
1015 | |
1016 | RwLockReadGuard { |
1017 | lock: write.lock, |
1018 | value: write.value, |
1019 | } |
1020 | } |
1021 | |
1022 | /// Downgrades into an upgradable reader guard. |
1023 | /// |
1024 | /// # Examples |
1025 | /// |
1026 | /// ``` |
1027 | /// # futures_lite::future::block_on(async { |
1028 | /// use async_lock::{RwLock, RwLockUpgradableReadGuard, RwLockWriteGuard}; |
1029 | /// |
1030 | /// let lock = RwLock::new(1); |
1031 | /// |
1032 | /// let mut writer = lock.write().await; |
1033 | /// *writer += 1; |
1034 | /// |
1035 | /// assert!(lock.try_read().is_none()); |
1036 | /// |
1037 | /// let reader = RwLockWriteGuard::downgrade_to_upgradable(writer); |
1038 | /// assert_eq!(*reader, 2); |
1039 | /// |
1040 | /// assert!(lock.try_write().is_none()); |
1041 | /// assert!(lock.try_read().is_some()); |
1042 | /// |
1043 | /// assert!(RwLockUpgradableReadGuard::try_upgrade(reader).is_ok()) |
1044 | /// # }) |
1045 | /// ``` |
1046 | #[inline ] |
1047 | pub fn downgrade_to_upgradable(guard: Self) -> RwLockUpgradableReadGuard<'a, T> { |
1048 | let write = ManuallyDrop::new(guard); |
1049 | |
1050 | // SAFETY: `write` is a write guard |
1051 | unsafe { |
1052 | write.lock.downgrade_to_upgradable(); |
1053 | } |
1054 | |
1055 | RwLockUpgradableReadGuard { |
1056 | lock: write.lock, |
1057 | value: write.value, |
1058 | } |
1059 | } |
1060 | } |
1061 | |
1062 | impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockWriteGuard<'_, T> { |
1063 | #[inline ] |
1064 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1065 | fmt::Debug::fmt(&**self, f) |
1066 | } |
1067 | } |
1068 | |
1069 | impl<T: fmt::Display + ?Sized> fmt::Display for RwLockWriteGuard<'_, T> { |
1070 | #[inline ] |
1071 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1072 | (**self).fmt(f) |
1073 | } |
1074 | } |
1075 | |
1076 | impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> { |
1077 | type Target = T; |
1078 | |
1079 | #[inline ] |
1080 | fn deref(&self) -> &T { |
1081 | unsafe { &*self.value } |
1082 | } |
1083 | } |
1084 | |
1085 | impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> { |
1086 | #[inline ] |
1087 | fn deref_mut(&mut self) -> &mut T { |
1088 | unsafe { &mut *self.value } |
1089 | } |
1090 | } |
1091 | |
1092 | /// An owned, reference-counted guard that releases the write lock when dropped. |
1093 | #[clippy::has_significant_drop] |
1094 | pub struct RwLockWriteGuardArc<T: ?Sized> { |
1095 | lock: Arc<RwLock<T>>, |
1096 | } |
1097 | |
1098 | unsafe impl<T: Send + Sync + ?Sized> Send for RwLockWriteGuardArc<T> {} |
1099 | unsafe impl<T: Send + Sync + ?Sized> Sync for RwLockWriteGuardArc<T> {} |
1100 | |
1101 | impl<T: ?Sized> Drop for RwLockWriteGuardArc<T> { |
1102 | #[inline ] |
1103 | fn drop(&mut self) { |
1104 | // SAFETY: we are dropping a write lock. |
1105 | unsafe { |
1106 | self.lock.raw.write_unlock(); |
1107 | } |
1108 | } |
1109 | } |
1110 | |
1111 | impl<T> RwLockWriteGuardArc<T> { |
1112 | /// Downgrades into a regular reader guard. |
1113 | /// |
1114 | /// # Examples |
1115 | /// |
1116 | /// ``` |
1117 | /// # futures_lite::future::block_on(async { |
1118 | /// use std::sync::Arc; |
1119 | /// use async_lock::{RwLock, RwLockWriteGuardArc}; |
1120 | /// |
1121 | /// let lock = Arc::new(RwLock::new(1)); |
1122 | /// |
1123 | /// let mut writer = lock.write_arc().await; |
1124 | /// *writer += 1; |
1125 | /// |
1126 | /// assert!(lock.try_read_arc().is_none()); |
1127 | /// |
1128 | /// let reader = RwLockWriteGuardArc::downgrade(writer); |
1129 | /// assert_eq!(*reader, 2); |
1130 | /// |
1131 | /// assert!(lock.try_read_arc().is_some()); |
1132 | /// # }) |
1133 | /// ``` |
1134 | #[inline ] |
1135 | pub fn downgrade(guard: Self) -> RwLockReadGuardArc<T> { |
1136 | // SAFETY: `write` is a write guard |
1137 | unsafe { |
1138 | guard.lock.raw.downgrade_write(); |
1139 | } |
1140 | |
1141 | // SAFETY: we just downgraded to a read lock |
1142 | unsafe { RwLockReadGuardArc::from_arc(Self::into_arc(guard)) } |
1143 | } |
1144 | } |
1145 | |
1146 | impl<T: ?Sized> RwLockWriteGuardArc<T> { |
1147 | /// Consumes the lock (without dropping) and returns the underlying `Arc`. |
1148 | #[inline ] |
1149 | fn into_arc(guard: Self) -> Arc<RwLock<T>> { |
1150 | let guard = ManuallyDrop::new(guard); |
1151 | // SAFETY: `guard` is not used after this |
1152 | unsafe { ptr::read(&guard.lock) } |
1153 | } |
1154 | |
1155 | /// Downgrades into an upgradable reader guard. |
1156 | /// |
1157 | /// # Examples |
1158 | /// |
1159 | /// ``` |
1160 | /// # futures_lite::future::block_on(async { |
1161 | /// use std::sync::Arc; |
1162 | /// use async_lock::{RwLock, RwLockUpgradableReadGuardArc, RwLockWriteGuardArc}; |
1163 | /// |
1164 | /// let lock = Arc::new(RwLock::new(1)); |
1165 | /// |
1166 | /// let mut writer = lock.write_arc().await; |
1167 | /// *writer += 1; |
1168 | /// |
1169 | /// assert!(lock.try_read_arc().is_none()); |
1170 | /// |
1171 | /// let reader = RwLockWriteGuardArc::downgrade_to_upgradable(writer); |
1172 | /// assert_eq!(*reader, 2); |
1173 | /// |
1174 | /// assert!(lock.try_write_arc().is_none()); |
1175 | /// assert!(lock.try_read_arc().is_some()); |
1176 | /// |
1177 | /// assert!(RwLockUpgradableReadGuardArc::try_upgrade(reader).is_ok()) |
1178 | /// # }) |
1179 | /// ``` |
1180 | #[inline ] |
1181 | pub fn downgrade_to_upgradable(guard: Self) -> RwLockUpgradableReadGuardArc<T> { |
1182 | // SAFETY: `guard` is a write guard |
1183 | unsafe { |
1184 | guard.lock.raw.downgrade_to_upgradable(); |
1185 | } |
1186 | |
1187 | RwLockUpgradableReadGuardArc { |
1188 | lock: Self::into_arc(guard), |
1189 | } |
1190 | } |
1191 | } |
1192 | |
1193 | impl<T: fmt::Debug + ?Sized> fmt::Debug for RwLockWriteGuardArc<T> { |
1194 | #[inline ] |
1195 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1196 | fmt::Debug::fmt(&**self, f) |
1197 | } |
1198 | } |
1199 | |
1200 | impl<T: fmt::Display + ?Sized> fmt::Display for RwLockWriteGuardArc<T> { |
1201 | #[inline ] |
1202 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1203 | (**self).fmt(f) |
1204 | } |
1205 | } |
1206 | |
1207 | impl<T: ?Sized> Deref for RwLockWriteGuardArc<T> { |
1208 | type Target = T; |
1209 | |
1210 | #[inline ] |
1211 | fn deref(&self) -> &T { |
1212 | unsafe { &*self.lock.value.get() } |
1213 | } |
1214 | } |
1215 | |
1216 | impl<T: ?Sized> DerefMut for RwLockWriteGuardArc<T> { |
1217 | #[inline ] |
1218 | fn deref_mut(&mut self) -> &mut T { |
1219 | unsafe { &mut *self.lock.value.get() } |
1220 | } |
1221 | } |
1222 | |