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