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