lock_api/rwlock.rs
1// Copyright 2016 Amanieu d'Antras
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use core::cell::UnsafeCell;
9use core::fmt;
10use core::marker::PhantomData;
11use core::mem;
12use core::ops::{Deref, DerefMut};
13
14#[cfg(feature = "arc_lock")]
15use alloc::sync::Arc;
16#[cfg(feature = "arc_lock")]
17use core::mem::ManuallyDrop;
18#[cfg(feature = "arc_lock")]
19use core::ptr;
20
21#[cfg(feature = "owning_ref")]
22use owning_ref::StableAddress;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Deserializer, Serialize, Serializer};
26
27/// Basic operations for a reader-writer lock.
28///
29/// Types implementing this trait can be used by `RwLock` to form a safe and
30/// fully-functioning `RwLock` type.
31///
32/// # Safety
33///
34/// Implementations of this trait must ensure that the `RwLock` is actually
35/// exclusive: an exclusive lock can't be acquired while an exclusive or shared
36/// lock exists, and a shared lock can't be acquire while an exclusive lock
37/// exists.
38pub unsafe trait RawRwLock {
39 /// Initial value for an unlocked `RwLock`.
40 // A “non-constant” const item is a legacy way to supply an initialized value to downstream
41 // static items. Can hopefully be replaced with `const fn new() -> Self` at some point.
42 #[allow(clippy::declare_interior_mutable_const)]
43 const INIT: Self;
44
45 /// Marker type which determines whether a lock guard should be `Send`. Use
46 /// one of the `GuardSend` or `GuardNoSend` helper types here.
47 type GuardMarker;
48
49 /// Acquires a shared lock, blocking the current thread until it is able to do so.
50 fn lock_shared(&self);
51
52 /// Attempts to acquire a shared lock without blocking.
53 fn try_lock_shared(&self) -> bool;
54
55 /// Releases a shared lock.
56 ///
57 /// # Safety
58 ///
59 /// This method may only be called if a shared lock is held in the current context.
60 unsafe fn unlock_shared(&self);
61
62 /// Acquires an exclusive lock, blocking the current thread until it is able to do so.
63 fn lock_exclusive(&self);
64
65 /// Attempts to acquire an exclusive lock without blocking.
66 fn try_lock_exclusive(&self) -> bool;
67
68 /// Releases an exclusive lock.
69 ///
70 /// # Safety
71 ///
72 /// This method may only be called if an exclusive lock is held in the current context.
73 unsafe fn unlock_exclusive(&self);
74
75 /// Checks if this `RwLock` is currently locked in any way.
76 #[inline]
77 fn is_locked(&self) -> bool {
78 let acquired_lock = self.try_lock_exclusive();
79 if acquired_lock {
80 // Safety: A lock was successfully acquired above.
81 unsafe {
82 self.unlock_exclusive();
83 }
84 }
85 !acquired_lock
86 }
87
88 /// Check if this `RwLock` is currently exclusively locked.
89 fn is_locked_exclusive(&self) -> bool {
90 let acquired_lock = self.try_lock_shared();
91 if acquired_lock {
92 // Safety: A shared lock was successfully acquired above.
93 unsafe {
94 self.unlock_shared();
95 }
96 }
97 !acquired_lock
98 }
99}
100
101/// Additional methods for `RwLock`s which support fair unlocking.
102///
103/// Fair unlocking means that a lock is handed directly over to the next waiting
104/// thread if there is one, without giving other threads the opportunity to
105/// "steal" the lock in the meantime. This is typically slower than unfair
106/// unlocking, but may be necessary in certain circumstances.
107pub unsafe trait RawRwLockFair: RawRwLock {
108 /// Releases a shared lock using a fair unlock protocol.
109 ///
110 /// # Safety
111 ///
112 /// This method may only be called if a shared lock is held in the current context.
113 unsafe fn unlock_shared_fair(&self);
114
115 /// Releases an exclusive lock using a fair unlock protocol.
116 ///
117 /// # Safety
118 ///
119 /// This method may only be called if an exclusive lock is held in the current context.
120 unsafe fn unlock_exclusive_fair(&self);
121
122 /// Temporarily yields a shared lock to a waiting thread if there is one.
123 ///
124 /// This method is functionally equivalent to calling `unlock_shared_fair` followed
125 /// by `lock_shared`, however it can be much more efficient in the case where there
126 /// are no waiting threads.
127 ///
128 /// # Safety
129 ///
130 /// This method may only be called if a shared lock is held in the current context.
131 unsafe fn bump_shared(&self) {
132 self.unlock_shared_fair();
133 self.lock_shared();
134 }
135
136 /// Temporarily yields an exclusive lock to a waiting thread if there is one.
137 ///
138 /// This method is functionally equivalent to calling `unlock_exclusive_fair` followed
139 /// by `lock_exclusive`, however it can be much more efficient in the case where there
140 /// are no waiting threads.
141 ///
142 /// # Safety
143 ///
144 /// This method may only be called if an exclusive lock is held in the current context.
145 unsafe fn bump_exclusive(&self) {
146 self.unlock_exclusive_fair();
147 self.lock_exclusive();
148 }
149}
150
151/// Additional methods for `RwLock`s which support atomically downgrading an
152/// exclusive lock to a shared lock.
153pub unsafe trait RawRwLockDowngrade: RawRwLock {
154 /// Atomically downgrades an exclusive lock into a shared lock without
155 /// allowing any thread to take an exclusive lock in the meantime.
156 ///
157 /// # Safety
158 ///
159 /// This method may only be called if an exclusive lock is held in the current context.
160 unsafe fn downgrade(&self);
161}
162
163/// Additional methods for `RwLock`s which support locking with timeouts.
164///
165/// The `Duration` and `Instant` types are specified as associated types so that
166/// this trait is usable even in `no_std` environments.
167pub unsafe trait RawRwLockTimed: RawRwLock {
168 /// Duration type used for `try_lock_for`.
169 type Duration;
170
171 /// Instant type used for `try_lock_until`.
172 type Instant;
173
174 /// Attempts to acquire a shared lock until a timeout is reached.
175 fn try_lock_shared_for(&self, timeout: Self::Duration) -> bool;
176
177 /// Attempts to acquire a shared lock until a timeout is reached.
178 fn try_lock_shared_until(&self, timeout: Self::Instant) -> bool;
179
180 /// Attempts to acquire an exclusive lock until a timeout is reached.
181 fn try_lock_exclusive_for(&self, timeout: Self::Duration) -> bool;
182
183 /// Attempts to acquire an exclusive lock until a timeout is reached.
184 fn try_lock_exclusive_until(&self, timeout: Self::Instant) -> bool;
185}
186
187/// Additional methods for `RwLock`s which support recursive read locks.
188///
189/// These are guaranteed to succeed without blocking if
190/// another read lock is held at the time of the call. This allows a thread
191/// to recursively lock a `RwLock`. However using this method can cause
192/// writers to starve since readers no longer block if a writer is waiting
193/// for the lock.
194pub unsafe trait RawRwLockRecursive: RawRwLock {
195 /// Acquires a shared lock without deadlocking in case of a recursive lock.
196 fn lock_shared_recursive(&self);
197
198 /// Attempts to acquire a shared lock without deadlocking in case of a recursive lock.
199 fn try_lock_shared_recursive(&self) -> bool;
200}
201
202/// Additional methods for `RwLock`s which support recursive read locks and timeouts.
203pub unsafe trait RawRwLockRecursiveTimed: RawRwLockRecursive + RawRwLockTimed {
204 /// Attempts to acquire a shared lock until a timeout is reached, without
205 /// deadlocking in case of a recursive lock.
206 fn try_lock_shared_recursive_for(&self, timeout: Self::Duration) -> bool;
207
208 /// Attempts to acquire a shared lock until a timeout is reached, without
209 /// deadlocking in case of a recursive lock.
210 fn try_lock_shared_recursive_until(&self, timeout: Self::Instant) -> bool;
211}
212
213/// Additional methods for `RwLock`s which support atomically upgrading a shared
214/// lock to an exclusive lock.
215///
216/// This requires acquiring a special "upgradable read lock" instead of a
217/// normal shared lock. There may only be one upgradable lock at any time,
218/// otherwise deadlocks could occur when upgrading.
219pub unsafe trait RawRwLockUpgrade: RawRwLock {
220 /// Acquires an upgradable lock, blocking the current thread until it is able to do so.
221 fn lock_upgradable(&self);
222
223 /// Attempts to acquire an upgradable lock without blocking.
224 fn try_lock_upgradable(&self) -> bool;
225
226 /// Releases an upgradable lock.
227 ///
228 /// # Safety
229 ///
230 /// This method may only be called if an upgradable lock is held in the current context.
231 unsafe fn unlock_upgradable(&self);
232
233 /// Upgrades an upgradable lock to an exclusive lock.
234 ///
235 /// # Safety
236 ///
237 /// This method may only be called if an upgradable lock is held in the current context.
238 unsafe fn upgrade(&self);
239
240 /// Attempts to upgrade an upgradable lock to an exclusive lock without
241 /// blocking.
242 ///
243 /// # Safety
244 ///
245 /// This method may only be called if an upgradable lock is held in the current context.
246 unsafe fn try_upgrade(&self) -> bool;
247}
248
249/// Additional methods for `RwLock`s which support upgradable locks and fair
250/// unlocking.
251pub unsafe trait RawRwLockUpgradeFair: RawRwLockUpgrade + RawRwLockFair {
252 /// Releases an upgradable lock using a fair unlock protocol.
253 ///
254 /// # Safety
255 ///
256 /// This method may only be called if an upgradable lock is held in the current context.
257 unsafe fn unlock_upgradable_fair(&self);
258
259 /// Temporarily yields an upgradable lock to a waiting thread if there is one.
260 ///
261 /// This method is functionally equivalent to calling `unlock_upgradable_fair` followed
262 /// by `lock_upgradable`, however it can be much more efficient in the case where there
263 /// are no waiting threads.
264 ///
265 /// # Safety
266 ///
267 /// This method may only be called if an upgradable lock is held in the current context.
268 unsafe fn bump_upgradable(&self) {
269 self.unlock_upgradable_fair();
270 self.lock_upgradable();
271 }
272}
273
274/// Additional methods for `RwLock`s which support upgradable locks and lock
275/// downgrading.
276pub unsafe trait RawRwLockUpgradeDowngrade: RawRwLockUpgrade + RawRwLockDowngrade {
277 /// Downgrades an upgradable lock to a shared lock.
278 ///
279 /// # Safety
280 ///
281 /// This method may only be called if an upgradable lock is held in the current context.
282 unsafe fn downgrade_upgradable(&self);
283
284 /// Downgrades an exclusive lock to an upgradable lock.
285 ///
286 /// # Safety
287 ///
288 /// This method may only be called if an exclusive lock is held in the current context.
289 unsafe fn downgrade_to_upgradable(&self);
290}
291
292/// Additional methods for `RwLock`s which support upgradable locks and locking
293/// with timeouts.
294pub unsafe trait RawRwLockUpgradeTimed: RawRwLockUpgrade + RawRwLockTimed {
295 /// Attempts to acquire an upgradable lock until a timeout is reached.
296 fn try_lock_upgradable_for(&self, timeout: Self::Duration) -> bool;
297
298 /// Attempts to acquire an upgradable lock until a timeout is reached.
299 fn try_lock_upgradable_until(&self, timeout: Self::Instant) -> bool;
300
301 /// Attempts to upgrade an upgradable lock to an exclusive lock until a
302 /// timeout is reached.
303 ///
304 /// # Safety
305 ///
306 /// This method may only be called if an upgradable lock is held in the current context.
307 unsafe fn try_upgrade_for(&self, timeout: Self::Duration) -> bool;
308
309 /// Attempts to upgrade an upgradable lock to an exclusive lock until a
310 /// timeout is reached.
311 ///
312 /// # Safety
313 ///
314 /// This method may only be called if an upgradable lock is held in the current context.
315 unsafe fn try_upgrade_until(&self, timeout: Self::Instant) -> bool;
316}
317
318/// A reader-writer lock
319///
320/// This type of lock allows a number of readers or at most one writer at any
321/// point in time. The write portion of this lock typically allows modification
322/// of the underlying data (exclusive access) and the read portion of this lock
323/// typically allows for read-only access (shared access).
324///
325/// The type parameter `T` represents the data that this lock protects. It is
326/// required that `T` satisfies `Send` to be shared across threads and `Sync` to
327/// allow concurrent access through readers. The RAII guards returned from the
328/// locking methods implement `Deref` (and `DerefMut` for the `write` methods)
329/// to allow access to the contained of the lock.
330pub struct RwLock<R, T: ?Sized> {
331 raw: R,
332 data: UnsafeCell<T>,
333}
334
335// Copied and modified from serde
336#[cfg(feature = "serde")]
337impl<R, T> Serialize for RwLock<R, T>
338where
339 R: RawRwLock,
340 T: Serialize + ?Sized,
341{
342 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
343 where
344 S: Serializer,
345 {
346 self.read().serialize(serializer)
347 }
348}
349
350#[cfg(feature = "serde")]
351impl<'de, R, T> Deserialize<'de> for RwLock<R, T>
352where
353 R: RawRwLock,
354 T: Deserialize<'de> + ?Sized,
355{
356 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
357 where
358 D: Deserializer<'de>,
359 {
360 Deserialize::deserialize(deserializer).map(RwLock::new)
361 }
362}
363
364unsafe impl<R: RawRwLock + Send, T: ?Sized + Send> Send for RwLock<R, T> {}
365unsafe impl<R: RawRwLock + Sync, T: ?Sized + Send + Sync> Sync for RwLock<R, T> {}
366
367impl<R: RawRwLock, T> RwLock<R, T> {
368 /// Creates a new instance of an `RwLock<T>` which is unlocked.
369 #[inline]
370 pub const fn new(val: T) -> RwLock<R, T> {
371 RwLock {
372 data: UnsafeCell::new(val),
373 raw: R::INIT,
374 }
375 }
376
377 /// Consumes this `RwLock`, returning the underlying data.
378 #[inline]
379 #[allow(unused_unsafe)]
380 pub fn into_inner(self) -> T {
381 unsafe { self.data.into_inner() }
382 }
383}
384
385impl<R, T> RwLock<R, T> {
386 /// Creates a new new instance of an `RwLock<T>` based on a pre-existing
387 /// `RawRwLock<T>`.
388 #[inline]
389 pub const fn from_raw(raw_rwlock: R, val: T) -> RwLock<R, T> {
390 RwLock {
391 data: UnsafeCell::new(val),
392 raw: raw_rwlock,
393 }
394 }
395
396 /// Creates a new new instance of an `RwLock<T>` based on a pre-existing
397 /// `RawRwLock<T>`.
398 ///
399 /// This allows creating a `RwLock<T>` in a constant context on stable
400 /// Rust.
401 ///
402 /// This method is a legacy alias for [`from_raw`](Self::from_raw).
403 #[inline]
404 pub const fn const_new(raw_rwlock: R, val: T) -> RwLock<R, T> {
405 Self::from_raw(raw_rwlock, val)
406 }
407
408 /// Consumes this read-write lock, returning the underlying data and raw lock.
409 #[inline]
410 pub fn into_inner_with_raw(self) -> (R, T) {
411 (self.raw, self.data.into_inner())
412 }
413}
414
415impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
416 /// Creates a new `RwLockReadGuard` without checking if the lock is held.
417 ///
418 /// # Safety
419 ///
420 /// This method must only be called if the thread logically holds a read lock.
421 ///
422 /// This function does not increment the read count of the lock. Calling this function when a
423 /// guard has already been produced is undefined behaviour unless the guard was forgotten
424 /// with `mem::forget`.
425 #[inline]
426 pub unsafe fn make_read_guard_unchecked(&self) -> RwLockReadGuard<'_, R, T> {
427 RwLockReadGuard {
428 rwlock: self,
429 marker: PhantomData,
430 }
431 }
432
433 /// Creates a new `RwLockReadGuard` without checking if the lock is held.
434 ///
435 /// # Safety
436 ///
437 /// This method must only be called if the thread logically holds a write lock.
438 ///
439 /// Calling this function when a guard has already been produced is undefined behaviour unless
440 /// the guard was forgotten with `mem::forget`.
441 #[inline]
442 pub unsafe fn make_write_guard_unchecked(&self) -> RwLockWriteGuard<'_, R, T> {
443 RwLockWriteGuard {
444 rwlock: self,
445 marker: PhantomData,
446 }
447 }
448
449 /// Locks this `RwLock` with shared read access, blocking the current thread
450 /// until it can be acquired.
451 ///
452 /// The calling thread will be blocked until there are no more writers which
453 /// hold the lock. There may be other readers currently inside the lock when
454 /// this method returns.
455 ///
456 /// Note that attempts to recursively acquire a read lock on a `RwLock` when
457 /// the current thread already holds one may result in a deadlock.
458 ///
459 /// Returns an RAII guard which will release this thread's shared access
460 /// once it is dropped.
461 #[inline]
462 #[track_caller]
463 pub fn read(&self) -> RwLockReadGuard<'_, R, T> {
464 self.raw.lock_shared();
465 // SAFETY: The lock is held, as required.
466 unsafe { self.make_read_guard_unchecked() }
467 }
468
469 /// Attempts to acquire this `RwLock` with shared read access.
470 ///
471 /// If the access could not be granted at this time, then `None` is returned.
472 /// Otherwise, an RAII guard is returned which will release the shared access
473 /// when it is dropped.
474 ///
475 /// This function does not block.
476 #[inline]
477 #[track_caller]
478 pub fn try_read(&self) -> Option<RwLockReadGuard<'_, R, T>> {
479 if self.raw.try_lock_shared() {
480 // SAFETY: The lock is held, as required.
481 Some(unsafe { self.make_read_guard_unchecked() })
482 } else {
483 None
484 }
485 }
486
487 /// Locks this `RwLock` with exclusive write access, blocking the current
488 /// thread until it can be acquired.
489 ///
490 /// This function will not return while other writers or other readers
491 /// currently have access to the lock.
492 ///
493 /// Returns an RAII guard which will drop the write access of this `RwLock`
494 /// when dropped.
495 #[inline]
496 #[track_caller]
497 pub fn write(&self) -> RwLockWriteGuard<'_, R, T> {
498 self.raw.lock_exclusive();
499 // SAFETY: The lock is held, as required.
500 unsafe { self.make_write_guard_unchecked() }
501 }
502
503 /// Attempts to lock this `RwLock` with exclusive write access.
504 ///
505 /// If the lock could not be acquired at this time, then `None` is returned.
506 /// Otherwise, an RAII guard is returned which will release the lock when
507 /// it is dropped.
508 ///
509 /// This function does not block.
510 #[inline]
511 #[track_caller]
512 pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, R, T>> {
513 if self.raw.try_lock_exclusive() {
514 // SAFETY: The lock is held, as required.
515 Some(unsafe { self.make_write_guard_unchecked() })
516 } else {
517 None
518 }
519 }
520
521 /// Returns a mutable reference to the underlying data.
522 ///
523 /// Since this call borrows the `RwLock` mutably, no actual locking needs to
524 /// take place---the mutable borrow statically guarantees no locks exist.
525 #[inline]
526 pub fn get_mut(&mut self) -> &mut T {
527 unsafe { &mut *self.data.get() }
528 }
529
530 /// Checks whether this `RwLock` is currently locked in any way.
531 #[inline]
532 #[track_caller]
533 pub fn is_locked(&self) -> bool {
534 self.raw.is_locked()
535 }
536
537 /// Check if this `RwLock` is currently exclusively locked.
538 #[inline]
539 #[track_caller]
540 pub fn is_locked_exclusive(&self) -> bool {
541 self.raw.is_locked_exclusive()
542 }
543
544 /// Forcibly unlocks a read lock.
545 ///
546 /// This is useful when combined with `mem::forget` to hold a lock without
547 /// the need to maintain a `RwLockReadGuard` object alive, for example when
548 /// dealing with FFI.
549 ///
550 /// # Safety
551 ///
552 /// This method must only be called if the current thread logically owns a
553 /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`.
554 /// Behavior is undefined if a rwlock is read-unlocked when not read-locked.
555 #[inline]
556 #[track_caller]
557 pub unsafe fn force_unlock_read(&self) {
558 self.raw.unlock_shared();
559 }
560
561 /// Forcibly unlocks a write lock.
562 ///
563 /// This is useful when combined with `mem::forget` to hold a lock without
564 /// the need to maintain a `RwLockWriteGuard` object alive, for example when
565 /// dealing with FFI.
566 ///
567 /// # Safety
568 ///
569 /// This method must only be called if the current thread logically owns a
570 /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`.
571 /// Behavior is undefined if a rwlock is write-unlocked when not write-locked.
572 #[inline]
573 #[track_caller]
574 pub unsafe fn force_unlock_write(&self) {
575 self.raw.unlock_exclusive();
576 }
577
578 /// Returns the underlying raw reader-writer lock object.
579 ///
580 /// Note that you will most likely need to import the `RawRwLock` trait from
581 /// `lock_api` to be able to call functions on the raw
582 /// reader-writer lock.
583 ///
584 /// # Safety
585 ///
586 /// This method is unsafe because it allows unlocking a mutex while
587 /// still holding a reference to a lock guard.
588 pub unsafe fn raw(&self) -> &R {
589 &self.raw
590 }
591
592 /// Returns a raw pointer to the underlying data.
593 ///
594 /// This is useful when combined with `mem::forget` to hold a lock without
595 /// the need to maintain a `RwLockReadGuard` or `RwLockWriteGuard` object
596 /// alive, for example when dealing with FFI.
597 ///
598 /// # Safety
599 ///
600 /// You must ensure that there are no data races when dereferencing the
601 /// returned pointer, for example if the current thread logically owns a
602 /// `RwLockReadGuard` or `RwLockWriteGuard` but that guard has been discarded
603 /// using `mem::forget`.
604 #[inline]
605 pub fn data_ptr(&self) -> *mut T {
606 self.data.get()
607 }
608
609 /// Creates a new `RwLockReadGuard` without checking if the lock is held.
610 ///
611 /// # Safety
612 ///
613 /// This method must only be called if the thread logically holds a read lock.
614 ///
615 /// This function does not increment the read count of the lock. Calling this function when a
616 /// guard has already been produced is undefined behaviour unless the guard was forgotten
617 /// with `mem::forget`.`
618 #[cfg(feature = "arc_lock")]
619 #[inline]
620 pub unsafe fn make_arc_read_guard_unchecked(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
621 ArcRwLockReadGuard {
622 rwlock: self.clone(),
623 marker: PhantomData,
624 }
625 }
626
627 /// Creates a new `RwLockWriteGuard` without checking if the lock is held.
628 ///
629 /// # Safety
630 ///
631 /// This method must only be called if the thread logically holds a write lock.
632 ///
633 /// Calling this function when a guard has already been produced is undefined behaviour unless
634 /// the guard was forgotten with `mem::forget`.
635 #[cfg(feature = "arc_lock")]
636 #[inline]
637 pub unsafe fn make_arc_write_guard_unchecked(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> {
638 ArcRwLockWriteGuard {
639 rwlock: self.clone(),
640 marker: PhantomData,
641 }
642 }
643
644 /// Locks this `RwLock` with read access, through an `Arc`.
645 ///
646 /// This method is similar to the `read` method; however, it requires the `RwLock` to be inside of an `Arc`
647 /// and the resulting read guard has no lifetime requirements.
648 #[cfg(feature = "arc_lock")]
649 #[inline]
650 #[track_caller]
651 pub fn read_arc(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
652 self.raw.lock_shared();
653 // SAFETY: locking guarantee is upheld
654 unsafe { self.make_arc_read_guard_unchecked() }
655 }
656
657 /// Attempts to lock this `RwLock` with read access, through an `Arc`.
658 ///
659 /// This method is similar to the `try_read` method; however, it requires the `RwLock` to be inside of an
660 /// `Arc` and the resulting read guard has no lifetime requirements.
661 #[cfg(feature = "arc_lock")]
662 #[inline]
663 #[track_caller]
664 pub fn try_read_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> {
665 if self.raw.try_lock_shared() {
666 // SAFETY: locking guarantee is upheld
667 Some(unsafe { self.make_arc_read_guard_unchecked() })
668 } else {
669 None
670 }
671 }
672
673 /// Locks this `RwLock` with write access, through an `Arc`.
674 ///
675 /// This method is similar to the `write` method; however, it requires the `RwLock` to be inside of an `Arc`
676 /// and the resulting write guard has no lifetime requirements.
677 #[cfg(feature = "arc_lock")]
678 #[inline]
679 #[track_caller]
680 pub fn write_arc(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> {
681 self.raw.lock_exclusive();
682 // SAFETY: locking guarantee is upheld
683 unsafe { self.make_arc_write_guard_unchecked() }
684 }
685
686 /// Attempts to lock this `RwLock` with writ access, through an `Arc`.
687 ///
688 /// This method is similar to the `try_write` method; however, it requires the `RwLock` to be inside of an
689 /// `Arc` and the resulting write guard has no lifetime requirements.
690 #[cfg(feature = "arc_lock")]
691 #[inline]
692 #[track_caller]
693 pub fn try_write_arc(self: &Arc<Self>) -> Option<ArcRwLockWriteGuard<R, T>> {
694 if self.raw.try_lock_exclusive() {
695 // SAFETY: locking guarantee is upheld
696 Some(unsafe { self.make_arc_write_guard_unchecked() })
697 } else {
698 None
699 }
700 }
701}
702
703impl<R: RawRwLockFair, T: ?Sized> RwLock<R, T> {
704 /// Forcibly unlocks a read lock using a fair unlock protocol.
705 ///
706 /// This is useful when combined with `mem::forget` to hold a lock without
707 /// the need to maintain a `RwLockReadGuard` object alive, for example when
708 /// dealing with FFI.
709 ///
710 /// # Safety
711 ///
712 /// This method must only be called if the current thread logically owns a
713 /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`.
714 /// Behavior is undefined if a rwlock is read-unlocked when not read-locked.
715 #[inline]
716 #[track_caller]
717 pub unsafe fn force_unlock_read_fair(&self) {
718 self.raw.unlock_shared_fair();
719 }
720
721 /// Forcibly unlocks a write lock using a fair unlock protocol.
722 ///
723 /// This is useful when combined with `mem::forget` to hold a lock without
724 /// the need to maintain a `RwLockWriteGuard` object alive, for example when
725 /// dealing with FFI.
726 ///
727 /// # Safety
728 ///
729 /// This method must only be called if the current thread logically owns a
730 /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`.
731 /// Behavior is undefined if a rwlock is write-unlocked when not write-locked.
732 #[inline]
733 #[track_caller]
734 pub unsafe fn force_unlock_write_fair(&self) {
735 self.raw.unlock_exclusive_fair();
736 }
737}
738
739impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
740 /// Attempts to acquire this `RwLock` with shared read access until a timeout
741 /// is reached.
742 ///
743 /// If the access could not be granted before the timeout expires, then
744 /// `None` is returned. Otherwise, an RAII guard is returned which will
745 /// release the shared access when it is dropped.
746 #[inline]
747 #[track_caller]
748 pub fn try_read_for(&self, timeout: R::Duration) -> Option<RwLockReadGuard<'_, R, T>> {
749 if self.raw.try_lock_shared_for(timeout) {
750 // SAFETY: The lock is held, as required.
751 Some(unsafe { self.make_read_guard_unchecked() })
752 } else {
753 None
754 }
755 }
756
757 /// Attempts to acquire this `RwLock` with shared read access until a timeout
758 /// is reached.
759 ///
760 /// If the access could not be granted before the timeout expires, then
761 /// `None` is returned. Otherwise, an RAII guard is returned which will
762 /// release the shared access when it is dropped.
763 #[inline]
764 #[track_caller]
765 pub fn try_read_until(&self, timeout: R::Instant) -> Option<RwLockReadGuard<'_, R, T>> {
766 if self.raw.try_lock_shared_until(timeout) {
767 // SAFETY: The lock is held, as required.
768 Some(unsafe { self.make_read_guard_unchecked() })
769 } else {
770 None
771 }
772 }
773
774 /// Attempts to acquire this `RwLock` with exclusive write access until a
775 /// timeout is reached.
776 ///
777 /// If the access could not be granted before the timeout expires, then
778 /// `None` is returned. Otherwise, an RAII guard is returned which will
779 /// release the exclusive access when it is dropped.
780 #[inline]
781 #[track_caller]
782 pub fn try_write_for(&self, timeout: R::Duration) -> Option<RwLockWriteGuard<'_, R, T>> {
783 if self.raw.try_lock_exclusive_for(timeout) {
784 // SAFETY: The lock is held, as required.
785 Some(unsafe { self.make_write_guard_unchecked() })
786 } else {
787 None
788 }
789 }
790
791 /// Attempts to acquire this `RwLock` with exclusive write access until a
792 /// timeout is reached.
793 ///
794 /// If the access could not be granted before the timeout expires, then
795 /// `None` is returned. Otherwise, an RAII guard is returned which will
796 /// release the exclusive access when it is dropped.
797 #[inline]
798 #[track_caller]
799 pub fn try_write_until(&self, timeout: R::Instant) -> Option<RwLockWriteGuard<'_, R, T>> {
800 if self.raw.try_lock_exclusive_until(timeout) {
801 // SAFETY: The lock is held, as required.
802 Some(unsafe { self.make_write_guard_unchecked() })
803 } else {
804 None
805 }
806 }
807
808 /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
809 ///
810 /// This method is similar to the `try_read_for` method; however, it requires the `RwLock` to be inside of an
811 /// `Arc` and the resulting read guard has no lifetime requirements.
812 #[cfg(feature = "arc_lock")]
813 #[inline]
814 #[track_caller]
815 pub fn try_read_arc_for(
816 self: &Arc<Self>,
817 timeout: R::Duration,
818 ) -> Option<ArcRwLockReadGuard<R, T>> {
819 if self.raw.try_lock_shared_for(timeout) {
820 // SAFETY: locking guarantee is upheld
821 Some(unsafe { self.make_arc_read_guard_unchecked() })
822 } else {
823 None
824 }
825 }
826
827 /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
828 ///
829 /// This method is similar to the `try_read_until` method; however, it requires the `RwLock` to be inside of
830 /// an `Arc` and the resulting read guard has no lifetime requirements.
831 #[cfg(feature = "arc_lock")]
832 #[inline]
833 #[track_caller]
834 pub fn try_read_arc_until(
835 self: &Arc<Self>,
836 timeout: R::Instant,
837 ) -> Option<ArcRwLockReadGuard<R, T>> {
838 if self.raw.try_lock_shared_until(timeout) {
839 // SAFETY: locking guarantee is upheld
840 Some(unsafe { self.make_arc_read_guard_unchecked() })
841 } else {
842 None
843 }
844 }
845
846 /// Attempts to acquire this `RwLock` with write access until a timeout is reached, through an `Arc`.
847 ///
848 /// This method is similar to the `try_write_for` method; however, it requires the `RwLock` to be inside of
849 /// an `Arc` and the resulting write guard has no lifetime requirements.
850 #[cfg(feature = "arc_lock")]
851 #[inline]
852 #[track_caller]
853 pub fn try_write_arc_for(
854 self: &Arc<Self>,
855 timeout: R::Duration,
856 ) -> Option<ArcRwLockWriteGuard<R, T>> {
857 if self.raw.try_lock_exclusive_for(timeout) {
858 // SAFETY: locking guarantee is upheld
859 Some(unsafe { self.make_arc_write_guard_unchecked() })
860 } else {
861 None
862 }
863 }
864
865 /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
866 ///
867 /// This method is similar to the `try_write_until` method; however, it requires the `RwLock` to be inside of
868 /// an `Arc` and the resulting read guard has no lifetime requirements.
869 #[cfg(feature = "arc_lock")]
870 #[inline]
871 #[track_caller]
872 pub fn try_write_arc_until(
873 self: &Arc<Self>,
874 timeout: R::Instant,
875 ) -> Option<ArcRwLockWriteGuard<R, T>> {
876 if self.raw.try_lock_exclusive_until(timeout) {
877 // SAFETY: locking guarantee is upheld
878 Some(unsafe { self.make_arc_write_guard_unchecked() })
879 } else {
880 None
881 }
882 }
883}
884
885impl<R: RawRwLockRecursive, T: ?Sized> RwLock<R, T> {
886 /// Locks this `RwLock` with shared read access, blocking the current thread
887 /// until it can be acquired.
888 ///
889 /// The calling thread will be blocked until there are no more writers which
890 /// hold the lock. There may be other readers currently inside the lock when
891 /// this method returns.
892 ///
893 /// Unlike `read`, this method is guaranteed to succeed without blocking if
894 /// another read lock is held at the time of the call. This allows a thread
895 /// to recursively lock a `RwLock`. However using this method can cause
896 /// writers to starve since readers no longer block if a writer is waiting
897 /// for the lock.
898 ///
899 /// Returns an RAII guard which will release this thread's shared access
900 /// once it is dropped.
901 #[inline]
902 #[track_caller]
903 pub fn read_recursive(&self) -> RwLockReadGuard<'_, R, T> {
904 self.raw.lock_shared_recursive();
905 // SAFETY: The lock is held, as required.
906 unsafe { self.make_read_guard_unchecked() }
907 }
908
909 /// Attempts to acquire this `RwLock` with shared read access.
910 ///
911 /// If the access could not be granted at this time, then `None` is returned.
912 /// Otherwise, an RAII guard is returned which will release the shared access
913 /// when it is dropped.
914 ///
915 /// This method is guaranteed to succeed if another read lock is held at the
916 /// time of the call. See the documentation for `read_recursive` for details.
917 ///
918 /// This function does not block.
919 #[inline]
920 #[track_caller]
921 pub fn try_read_recursive(&self) -> Option<RwLockReadGuard<'_, R, T>> {
922 if self.raw.try_lock_shared_recursive() {
923 // SAFETY: The lock is held, as required.
924 Some(unsafe { self.make_read_guard_unchecked() })
925 } else {
926 None
927 }
928 }
929
930 /// Locks this `RwLock` with shared read access, through an `Arc`.
931 ///
932 /// This method is similar to the `read_recursive` method; however, it requires the `RwLock` to be inside of
933 /// an `Arc` and the resulting read guard has no lifetime requirements.
934 #[cfg(feature = "arc_lock")]
935 #[inline]
936 #[track_caller]
937 pub fn read_arc_recursive(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
938 self.raw.lock_shared_recursive();
939 // SAFETY: locking guarantee is upheld
940 unsafe { self.make_arc_read_guard_unchecked() }
941 }
942
943 /// Attempts to lock this `RwLock` with shared read access, through an `Arc`.
944 ///
945 /// This method is similar to the `try_read_recursive` method; however, it requires the `RwLock` to be inside
946 /// of an `Arc` and the resulting read guard has no lifetime requirements.
947 #[cfg(feature = "arc_lock")]
948 #[inline]
949 #[track_caller]
950 pub fn try_read_recursive_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> {
951 if self.raw.try_lock_shared_recursive() {
952 // SAFETY: locking guarantee is upheld
953 Some(unsafe { self.make_arc_read_guard_unchecked() })
954 } else {
955 None
956 }
957 }
958}
959
960impl<R: RawRwLockRecursiveTimed, T: ?Sized> RwLock<R, T> {
961 /// Attempts to acquire this `RwLock` with shared read access until a timeout
962 /// is reached.
963 ///
964 /// If the access could not be granted before the timeout expires, then
965 /// `None` is returned. Otherwise, an RAII guard is returned which will
966 /// release the shared access when it is dropped.
967 ///
968 /// This method is guaranteed to succeed without blocking if another read
969 /// lock is held at the time of the call. See the documentation for
970 /// `read_recursive` for details.
971 #[inline]
972 #[track_caller]
973 pub fn try_read_recursive_for(
974 &self,
975 timeout: R::Duration,
976 ) -> Option<RwLockReadGuard<'_, R, T>> {
977 if self.raw.try_lock_shared_recursive_for(timeout) {
978 // SAFETY: The lock is held, as required.
979 Some(unsafe { self.make_read_guard_unchecked() })
980 } else {
981 None
982 }
983 }
984
985 /// Attempts to acquire this `RwLock` with shared read access until a timeout
986 /// is reached.
987 ///
988 /// If the access could not be granted before the timeout expires, then
989 /// `None` is returned. Otherwise, an RAII guard is returned which will
990 /// release the shared access when it is dropped.
991 #[inline]
992 #[track_caller]
993 pub fn try_read_recursive_until(
994 &self,
995 timeout: R::Instant,
996 ) -> Option<RwLockReadGuard<'_, R, T>> {
997 if self.raw.try_lock_shared_recursive_until(timeout) {
998 // SAFETY: The lock is held, as required.
999 Some(unsafe { self.make_read_guard_unchecked() })
1000 } else {
1001 None
1002 }
1003 }
1004
1005 /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`.
1006 ///
1007 /// This method is similar to the `try_read_recursive_for` method; however, it requires the `RwLock` to be
1008 /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1009 #[cfg(feature = "arc_lock")]
1010 #[inline]
1011 #[track_caller]
1012 pub fn try_read_arc_recursive_for(
1013 self: &Arc<Self>,
1014 timeout: R::Duration,
1015 ) -> Option<ArcRwLockReadGuard<R, T>> {
1016 if self.raw.try_lock_shared_recursive_for(timeout) {
1017 // SAFETY: locking guarantee is upheld
1018 Some(unsafe { self.make_arc_read_guard_unchecked() })
1019 } else {
1020 None
1021 }
1022 }
1023
1024 /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`.
1025 ///
1026 /// This method is similar to the `try_read_recursive_until` method; however, it requires the `RwLock` to be
1027 /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1028 #[cfg(feature = "arc_lock")]
1029 #[inline]
1030 #[track_caller]
1031 pub fn try_read_arc_recursive_until(
1032 self: &Arc<Self>,
1033 timeout: R::Instant,
1034 ) -> Option<ArcRwLockReadGuard<R, T>> {
1035 if self.raw.try_lock_shared_recursive_until(timeout) {
1036 // SAFETY: locking guarantee is upheld
1037 Some(unsafe { self.make_arc_read_guard_unchecked() })
1038 } else {
1039 None
1040 }
1041 }
1042}
1043
1044impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> {
1045 /// Creates a new `RwLockUpgradableReadGuard` without checking if the lock is held.
1046 ///
1047 /// # Safety
1048 ///
1049 /// This method must only be called if the thread logically holds an upgradable read lock.
1050 ///
1051 /// This function does not increment the read count of the lock. Calling this function when a
1052 /// guard has already been produced is undefined behaviour unless the guard was forgotten
1053 /// with `mem::forget`.
1054 #[inline]
1055 pub unsafe fn make_upgradable_guard_unchecked(&self) -> RwLockUpgradableReadGuard<'_, R, T> {
1056 RwLockUpgradableReadGuard {
1057 rwlock: self,
1058 marker: PhantomData,
1059 }
1060 }
1061
1062 /// Locks this `RwLock` with upgradable read access, blocking the current thread
1063 /// until it can be acquired.
1064 ///
1065 /// The calling thread will be blocked until there are no more writers or other
1066 /// upgradable reads which hold the lock. There may be other readers currently
1067 /// inside the lock when this method returns.
1068 ///
1069 /// Returns an RAII guard which will release this thread's shared access
1070 /// once it is dropped.
1071 #[inline]
1072 #[track_caller]
1073 pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<'_, R, T> {
1074 self.raw.lock_upgradable();
1075 // SAFETY: The lock is held, as required.
1076 unsafe { self.make_upgradable_guard_unchecked() }
1077 }
1078
1079 /// Attempts to acquire this `RwLock` with upgradable read access.
1080 ///
1081 /// If the access could not be granted at this time, then `None` is returned.
1082 /// Otherwise, an RAII guard is returned which will release the shared access
1083 /// when it is dropped.
1084 ///
1085 /// This function does not block.
1086 #[inline]
1087 #[track_caller]
1088 pub fn try_upgradable_read(&self) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
1089 if self.raw.try_lock_upgradable() {
1090 // SAFETY: The lock is held, as required.
1091 Some(unsafe { self.make_upgradable_guard_unchecked() })
1092 } else {
1093 None
1094 }
1095 }
1096
1097 /// Creates a new `ArcRwLockUpgradableReadGuard` without checking if the lock is held.
1098 ///
1099 /// # Safety
1100 ///
1101 /// This method must only be called if the thread logically holds an upgradable read lock.
1102 ///
1103 /// This function does not increment the read count of the lock. Calling this function when a
1104 /// guard has already been produced is undefined behaviour unless the guard was forgotten
1105 /// with `mem::forget`.`
1106 #[cfg(feature = "arc_lock")]
1107 #[inline]
1108 pub unsafe fn make_upgradable_arc_guard_unchecked(
1109 self: &Arc<Self>,
1110 ) -> ArcRwLockUpgradableReadGuard<R, T> {
1111 ArcRwLockUpgradableReadGuard {
1112 rwlock: self.clone(),
1113 marker: PhantomData,
1114 }
1115 }
1116
1117 /// Locks this `RwLock` with upgradable read access, through an `Arc`.
1118 ///
1119 /// This method is similar to the `upgradable_read` method; however, it requires the `RwLock` to be
1120 /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1121 #[cfg(feature = "arc_lock")]
1122 #[inline]
1123 #[track_caller]
1124 pub fn upgradable_read_arc(self: &Arc<Self>) -> ArcRwLockUpgradableReadGuard<R, T> {
1125 self.raw.lock_upgradable();
1126 // SAFETY: locking guarantee is upheld
1127 unsafe { self.make_upgradable_arc_guard_unchecked() }
1128 }
1129
1130 /// Attempts to lock this `RwLock` with upgradable read access, through an `Arc`.
1131 ///
1132 /// This method is similar to the `try_upgradable_read` method; however, it requires the `RwLock` to be
1133 /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1134 #[cfg(feature = "arc_lock")]
1135 #[inline]
1136 #[track_caller]
1137 pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
1138 if self.raw.try_lock_upgradable() {
1139 // SAFETY: locking guarantee is upheld
1140 Some(unsafe { self.make_upgradable_arc_guard_unchecked() })
1141 } else {
1142 None
1143 }
1144 }
1145}
1146
1147impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> {
1148 /// Attempts to acquire this `RwLock` with upgradable read access until a timeout
1149 /// is reached.
1150 ///
1151 /// If the access could not be granted before the timeout expires, then
1152 /// `None` is returned. Otherwise, an RAII guard is returned which will
1153 /// release the shared access when it is dropped.
1154 #[inline]
1155 #[track_caller]
1156 pub fn try_upgradable_read_for(
1157 &self,
1158 timeout: R::Duration,
1159 ) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
1160 if self.raw.try_lock_upgradable_for(timeout) {
1161 // SAFETY: The lock is held, as required.
1162 Some(unsafe { self.make_upgradable_guard_unchecked() })
1163 } else {
1164 None
1165 }
1166 }
1167
1168 /// Attempts to acquire this `RwLock` with upgradable read access until a timeout
1169 /// is reached.
1170 ///
1171 /// If the access could not be granted before the timeout expires, then
1172 /// `None` is returned. Otherwise, an RAII guard is returned which will
1173 /// release the shared access when it is dropped.
1174 #[inline]
1175 #[track_caller]
1176 pub fn try_upgradable_read_until(
1177 &self,
1178 timeout: R::Instant,
1179 ) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
1180 if self.raw.try_lock_upgradable_until(timeout) {
1181 // SAFETY: The lock is held, as required.
1182 Some(unsafe { self.make_upgradable_guard_unchecked() })
1183 } else {
1184 None
1185 }
1186 }
1187
1188 /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`.
1189 ///
1190 /// This method is similar to the `try_upgradable_read_for` method; however, it requires the `RwLock` to be
1191 /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1192 #[cfg(feature = "arc_lock")]
1193 #[inline]
1194 #[track_caller]
1195 pub fn try_upgradable_read_arc_for(
1196 self: &Arc<Self>,
1197 timeout: R::Duration,
1198 ) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
1199 if self.raw.try_lock_upgradable_for(timeout) {
1200 // SAFETY: locking guarantee is upheld
1201 Some(unsafe { self.make_upgradable_arc_guard_unchecked() })
1202 } else {
1203 None
1204 }
1205 }
1206
1207 /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`.
1208 ///
1209 /// This method is similar to the `try_upgradable_read_until` method; however, it requires the `RwLock` to be
1210 /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1211 #[cfg(feature = "arc_lock")]
1212 #[inline]
1213 #[track_caller]
1214 pub fn try_upgradable_read_arc_until(
1215 self: &Arc<Self>,
1216 timeout: R::Instant,
1217 ) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
1218 if self.raw.try_lock_upgradable_until(timeout) {
1219 // SAFETY: locking guarantee is upheld
1220 Some(unsafe { self.make_upgradable_arc_guard_unchecked() })
1221 } else {
1222 None
1223 }
1224 }
1225}
1226
1227impl<R: RawRwLock, T: ?Sized + Default> Default for RwLock<R, T> {
1228 #[inline]
1229 fn default() -> RwLock<R, T> {
1230 RwLock::new(Default::default())
1231 }
1232}
1233
1234impl<R: RawRwLock, T> From<T> for RwLock<R, T> {
1235 #[inline]
1236 fn from(t: T) -> RwLock<R, T> {
1237 RwLock::new(t)
1238 }
1239}
1240
1241impl<R: RawRwLock, T: ?Sized + fmt::Debug> fmt::Debug for RwLock<R, T> {
1242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1243 let mut d = f.debug_struct("RwLock");
1244 match self.try_read() {
1245 Some(guard) => d.field("data", &&*guard),
1246 None => {
1247 // Additional format_args! here is to remove quotes around <locked> in debug output.
1248 d.field("data", &format_args!("<locked>"))
1249 }
1250 };
1251 d.finish()
1252 }
1253}
1254
1255/// RAII structure used to release the shared read access of a lock when
1256/// dropped.
1257#[clippy::has_significant_drop]
1258#[must_use = "if unused the RwLock will immediately unlock"]
1259pub struct RwLockReadGuard<'a, R: RawRwLock, T: ?Sized> {
1260 rwlock: &'a RwLock<R, T>,
1261 marker: PhantomData<(&'a T, R::GuardMarker)>,
1262}
1263
1264unsafe impl<R: RawRwLock + Sync, T: Sync + ?Sized> Sync for RwLockReadGuard<'_, R, T> {}
1265
1266impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
1267 /// Returns a reference to the original reader-writer lock object.
1268 pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
1269 s.rwlock
1270 }
1271
1272 /// Make a new `MappedRwLockReadGuard` for a component of the locked data.
1273 ///
1274 /// This operation cannot fail as the `RwLockReadGuard` passed
1275 /// in already locked the data.
1276 ///
1277 /// This is an associated function that needs to be
1278 /// used as `RwLockReadGuard::map(...)`. A method would interfere with methods of
1279 /// the same name on the contents of the locked data.
1280 #[inline]
1281 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U>
1282 where
1283 F: FnOnce(&T) -> &U,
1284 {
1285 let raw = &s.rwlock.raw;
1286 let data = f(unsafe { &*s.rwlock.data.get() });
1287 mem::forget(s);
1288 MappedRwLockReadGuard {
1289 raw,
1290 data,
1291 marker: PhantomData,
1292 }
1293 }
1294
1295 /// Attempts to make a new `MappedRwLockReadGuard` for a component of the
1296 /// locked data. Returns the original guard if the closure returns `None`.
1297 ///
1298 /// This operation cannot fail as the `RwLockReadGuard` passed
1299 /// in already locked the data.
1300 ///
1301 /// This is an associated function that needs to be
1302 /// used as `RwLockReadGuard::try_map(...)`. A method would interfere with methods of
1303 /// the same name on the contents of the locked data.
1304 #[inline]
1305 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
1306 where
1307 F: FnOnce(&T) -> Option<&U>,
1308 {
1309 let raw = &s.rwlock.raw;
1310 let data = match f(unsafe { &*s.rwlock.data.get() }) {
1311 Some(data) => data,
1312 None => return Err(s),
1313 };
1314 mem::forget(s);
1315 Ok(MappedRwLockReadGuard {
1316 raw,
1317 data,
1318 marker: PhantomData,
1319 })
1320 }
1321
1322 /// Attempts to make a new `MappedRwLockReadGuard` for a component of the
1323 /// locked data. The original guard is returned alongside arbitrary user data
1324 /// if the closure returns `Err`.
1325 ///
1326 /// This operation cannot fail as the `RwLockReadGuard` passed
1327 /// in already locked the data.
1328 ///
1329 /// This is an associated function that needs to be
1330 /// used as `RwLockReadGuard::try_map_or_err(...)`. A method would interfere with methods of
1331 /// the same name on the contents of the locked data.
1332 #[inline]
1333 pub fn try_map_or_err<U: ?Sized, F, E>(
1334 s: Self,
1335 f: F,
1336 ) -> Result<MappedRwLockReadGuard<'a, R, U>, (Self, E)>
1337 where
1338 F: FnOnce(&T) -> Result<&U, E>,
1339 {
1340 let raw = &s.rwlock.raw;
1341 let data = match f(unsafe { &*s.rwlock.data.get() }) {
1342 Ok(data) => data,
1343 Err(e) => return Err((s, e)),
1344 };
1345 mem::forget(s);
1346 Ok(MappedRwLockReadGuard {
1347 raw,
1348 data,
1349 marker: PhantomData,
1350 })
1351 }
1352
1353 /// Temporarily unlocks the `RwLock` to execute the given function.
1354 ///
1355 /// This is safe because `&mut` guarantees that there exist no other
1356 /// references to the data protected by the `RwLock`.
1357 #[inline]
1358 #[track_caller]
1359 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1360 where
1361 F: FnOnce() -> U,
1362 {
1363 // Safety: An RwLockReadGuard always holds a shared lock.
1364 unsafe {
1365 s.rwlock.raw.unlock_shared();
1366 }
1367 defer!(s.rwlock.raw.lock_shared());
1368 f()
1369 }
1370}
1371
1372impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
1373 /// Unlocks the `RwLock` using a fair unlock protocol.
1374 ///
1375 /// By default, `RwLock` is unfair and allow the current thread to re-lock
1376 /// the `RwLock` before another has the chance to acquire the lock, even if
1377 /// that thread has been blocked on the `RwLock` for a long time. This is
1378 /// the default because it allows much higher throughput as it avoids
1379 /// forcing a context switch on every `RwLock` unlock. This can result in one
1380 /// thread acquiring a `RwLock` many more times than other threads.
1381 ///
1382 /// However in some cases it can be beneficial to ensure fairness by forcing
1383 /// the lock to pass on to a waiting thread if there is one. This is done by
1384 /// using this method instead of dropping the `RwLockReadGuard` normally.
1385 #[inline]
1386 #[track_caller]
1387 pub fn unlock_fair(s: Self) {
1388 // Safety: An RwLockReadGuard always holds a shared lock.
1389 unsafe {
1390 s.rwlock.raw.unlock_shared_fair();
1391 }
1392 mem::forget(s);
1393 }
1394
1395 /// Temporarily unlocks the `RwLock` to execute the given function.
1396 ///
1397 /// The `RwLock` is unlocked a fair unlock protocol.
1398 ///
1399 /// This is safe because `&mut` guarantees that there exist no other
1400 /// references to the data protected by the `RwLock`.
1401 #[inline]
1402 #[track_caller]
1403 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1404 where
1405 F: FnOnce() -> U,
1406 {
1407 // Safety: An RwLockReadGuard always holds a shared lock.
1408 unsafe {
1409 s.rwlock.raw.unlock_shared_fair();
1410 }
1411 defer!(s.rwlock.raw.lock_shared());
1412 f()
1413 }
1414
1415 /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1416 ///
1417 /// This method is functionally equivalent to calling `unlock_fair` followed
1418 /// by `read`, however it can be much more efficient in the case where there
1419 /// are no waiting threads.
1420 #[inline]
1421 #[track_caller]
1422 pub fn bump(s: &mut Self) {
1423 // Safety: An RwLockReadGuard always holds a shared lock.
1424 unsafe {
1425 s.rwlock.raw.bump_shared();
1426 }
1427 }
1428}
1429
1430impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockReadGuard<'a, R, T> {
1431 type Target = T;
1432 #[inline]
1433 fn deref(&self) -> &T {
1434 unsafe { &*self.rwlock.data.get() }
1435 }
1436}
1437
1438impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockReadGuard<'a, R, T> {
1439 #[inline]
1440 fn drop(&mut self) {
1441 // Safety: An RwLockReadGuard always holds a shared lock.
1442 unsafe {
1443 self.rwlock.raw.unlock_shared();
1444 }
1445 }
1446}
1447
1448impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockReadGuard<'a, R, T> {
1449 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1450 fmt::Debug::fmt(&**self, f)
1451 }
1452}
1453
1454impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
1455 for RwLockReadGuard<'a, R, T>
1456{
1457 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1458 (**self).fmt(f)
1459 }
1460}
1461
1462#[cfg(feature = "owning_ref")]
1463unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {}
1464
1465/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
1466///
1467/// This is similar to the `RwLockReadGuard` struct, except instead of using a reference to unlock the `RwLock`
1468/// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime.
1469#[cfg(feature = "arc_lock")]
1470#[clippy::has_significant_drop]
1471#[must_use = "if unused the RwLock will immediately unlock"]
1472pub struct ArcRwLockReadGuard<R: RawRwLock, T: ?Sized> {
1473 rwlock: Arc<RwLock<R, T>>,
1474 marker: PhantomData<R::GuardMarker>,
1475}
1476
1477#[cfg(feature = "arc_lock")]
1478impl<R: RawRwLock, T: ?Sized> ArcRwLockReadGuard<R, T> {
1479 /// Returns a reference to the rwlock, contained in its `Arc`.
1480 pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
1481 &s.rwlock
1482 }
1483
1484 /// Unlocks the `RwLock` and returns the `Arc` that was held by the [`ArcRwLockReadGuard`].
1485 #[inline]
1486 pub fn into_arc(s: Self) -> Arc<RwLock<R, T>> {
1487 // SAFETY: Skip our Drop impl and manually unlock the rwlock.
1488 let s = ManuallyDrop::new(s);
1489 unsafe {
1490 s.rwlock.raw.unlock_shared();
1491 ptr::read(&s.rwlock)
1492 }
1493 }
1494
1495 /// Temporarily unlocks the `RwLock` to execute the given function.
1496 ///
1497 /// This is functionally identical to the `unlocked` method on [`RwLockReadGuard`].
1498 #[inline]
1499 #[track_caller]
1500 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1501 where
1502 F: FnOnce() -> U,
1503 {
1504 // Safety: An RwLockReadGuard always holds a shared lock.
1505 unsafe {
1506 s.rwlock.raw.unlock_shared();
1507 }
1508 defer!(s.rwlock.raw.lock_shared());
1509 f()
1510 }
1511}
1512
1513#[cfg(feature = "arc_lock")]
1514impl<R: RawRwLockFair, T: ?Sized> ArcRwLockReadGuard<R, T> {
1515 /// Unlocks the `RwLock` using a fair unlock protocol.
1516 ///
1517 /// This is functionally identical to the `unlock_fair` method on [`RwLockReadGuard`].
1518 #[inline]
1519 #[track_caller]
1520 pub fn unlock_fair(s: Self) {
1521 drop(Self::into_arc_fair(s));
1522 }
1523
1524 /// Unlocks the `RwLock` using a fair unlock protocol and returns the `Arc` that was held by the [`ArcRwLockReadGuard`].
1525 #[inline]
1526 pub fn into_arc_fair(s: Self) -> Arc<RwLock<R, T>> {
1527 // SAFETY: Skip our Drop impl and manually unlock the rwlock.
1528 let s = ManuallyDrop::new(s);
1529 unsafe {
1530 s.rwlock.raw.unlock_shared_fair();
1531 ptr::read(&s.rwlock)
1532 }
1533 }
1534
1535 /// Temporarily unlocks the `RwLock` to execute the given function.
1536 ///
1537 /// This is functionally identical to the `unlocked_fair` method on [`RwLockReadGuard`].
1538 #[inline]
1539 #[track_caller]
1540 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1541 where
1542 F: FnOnce() -> U,
1543 {
1544 // Safety: An RwLockReadGuard always holds a shared lock.
1545 unsafe {
1546 s.rwlock.raw.unlock_shared_fair();
1547 }
1548 defer!(s.rwlock.raw.lock_shared());
1549 f()
1550 }
1551
1552 /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1553 ///
1554 /// This is functionally identical to the `bump` method on [`RwLockReadGuard`].
1555 #[inline]
1556 #[track_caller]
1557 pub fn bump(s: &mut Self) {
1558 // Safety: An RwLockReadGuard always holds a shared lock.
1559 unsafe {
1560 s.rwlock.raw.bump_shared();
1561 }
1562 }
1563}
1564
1565#[cfg(feature = "arc_lock")]
1566impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockReadGuard<R, T> {
1567 type Target = T;
1568 #[inline]
1569 fn deref(&self) -> &T {
1570 unsafe { &*self.rwlock.data.get() }
1571 }
1572}
1573
1574#[cfg(feature = "arc_lock")]
1575impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockReadGuard<R, T> {
1576 #[inline]
1577 fn drop(&mut self) {
1578 // Safety: An RwLockReadGuard always holds a shared lock.
1579 unsafe {
1580 self.rwlock.raw.unlock_shared();
1581 }
1582 }
1583}
1584
1585#[cfg(feature = "arc_lock")]
1586impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockReadGuard<R, T> {
1587 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1588 fmt::Debug::fmt(&**self, f)
1589 }
1590}
1591
1592#[cfg(feature = "arc_lock")]
1593impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockReadGuard<R, T> {
1594 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1595 (**self).fmt(f)
1596 }
1597}
1598
1599/// RAII structure used to release the exclusive write access of a lock when
1600/// dropped.
1601#[clippy::has_significant_drop]
1602#[must_use = "if unused the RwLock will immediately unlock"]
1603pub struct RwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> {
1604 rwlock: &'a RwLock<R, T>,
1605 marker: PhantomData<(&'a mut T, R::GuardMarker)>,
1606}
1607
1608unsafe impl<R: RawRwLock + Sync, T: Sync + ?Sized> Sync for RwLockWriteGuard<'_, R, T> {}
1609
1610impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1611 /// Returns a reference to the original reader-writer lock object.
1612 pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
1613 s.rwlock
1614 }
1615
1616 /// Make a new `MappedRwLockWriteGuard` for a component of the locked data.
1617 ///
1618 /// This operation cannot fail as the `RwLockWriteGuard` passed
1619 /// in already locked the data.
1620 ///
1621 /// This is an associated function that needs to be
1622 /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of
1623 /// the same name on the contents of the locked data.
1624 #[inline]
1625 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U>
1626 where
1627 F: FnOnce(&mut T) -> &mut U,
1628 {
1629 let raw = &s.rwlock.raw;
1630 let data = f(unsafe { &mut *s.rwlock.data.get() });
1631 mem::forget(s);
1632 MappedRwLockWriteGuard {
1633 raw,
1634 data,
1635 marker: PhantomData,
1636 }
1637 }
1638
1639 /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the
1640 /// locked data. The original guard is return if the closure returns `None`.
1641 ///
1642 /// This operation cannot fail as the `RwLockWriteGuard` passed
1643 /// in already locked the data.
1644 ///
1645 /// This is an associated function that needs to be
1646 /// used as `RwLockWriteGuard::try_map(...)`. A method would interfere with methods of
1647 /// the same name on the contents of the locked data.
1648 #[inline]
1649 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
1650 where
1651 F: FnOnce(&mut T) -> Option<&mut U>,
1652 {
1653 let raw = &s.rwlock.raw;
1654 let data = match f(unsafe { &mut *s.rwlock.data.get() }) {
1655 Some(data) => data,
1656 None => return Err(s),
1657 };
1658 mem::forget(s);
1659 Ok(MappedRwLockWriteGuard {
1660 raw,
1661 data,
1662 marker: PhantomData,
1663 })
1664 }
1665
1666 /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the
1667 /// locked data. The original guard is returned alongside arbitrary user data
1668 /// if the closure returns `Err`.
1669 ///
1670 /// This operation cannot fail as the `RwLockWriteGuard` passed
1671 /// in already locked the data.
1672 ///
1673 /// This is an associated function that needs to be
1674 /// used as `RwLockWriteGuard::try_map_or_err(...)`. A method would interfere with methods of
1675 /// the same name on the contents of the locked data.
1676 #[inline]
1677 pub fn try_map_or_err<U: ?Sized, F, E>(
1678 s: Self,
1679 f: F,
1680 ) -> Result<MappedRwLockWriteGuard<'a, R, U>, (Self, E)>
1681 where
1682 F: FnOnce(&mut T) -> Result<&mut U, E>,
1683 {
1684 let raw = &s.rwlock.raw;
1685 let data = match f(unsafe { &mut *s.rwlock.data.get() }) {
1686 Ok(data) => data,
1687 Err(e) => return Err((s, e)),
1688 };
1689 mem::forget(s);
1690 Ok(MappedRwLockWriteGuard {
1691 raw,
1692 data,
1693 marker: PhantomData,
1694 })
1695 }
1696
1697 /// Temporarily unlocks the `RwLock` to execute the given function.
1698 ///
1699 /// This is safe because `&mut` guarantees that there exist no other
1700 /// references to the data protected by the `RwLock`.
1701 #[inline]
1702 #[track_caller]
1703 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1704 where
1705 F: FnOnce() -> U,
1706 {
1707 // Safety: An RwLockReadGuard always holds a shared lock.
1708 unsafe {
1709 s.rwlock.raw.unlock_exclusive();
1710 }
1711 defer!(s.rwlock.raw.lock_exclusive());
1712 f()
1713 }
1714}
1715
1716impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1717 /// Atomically downgrades a write lock into a read lock without allowing any
1718 /// writers to take exclusive access of the lock in the meantime.
1719 ///
1720 /// Note that if there are any writers currently waiting to take the lock
1721 /// then other readers may not be able to acquire the lock even if it was
1722 /// downgraded.
1723 #[track_caller]
1724 pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> {
1725 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1726 unsafe {
1727 s.rwlock.raw.downgrade();
1728 }
1729 let rwlock = s.rwlock;
1730 mem::forget(s);
1731 RwLockReadGuard {
1732 rwlock,
1733 marker: PhantomData,
1734 }
1735 }
1736}
1737
1738impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1739 /// Atomically downgrades a write lock into an upgradable read lock without allowing any
1740 /// writers to take exclusive access of the lock in the meantime.
1741 ///
1742 /// Note that if there are any writers currently waiting to take the lock
1743 /// then other readers may not be able to acquire the lock even if it was
1744 /// downgraded.
1745 #[track_caller]
1746 pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, R, T> {
1747 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1748 unsafe {
1749 s.rwlock.raw.downgrade_to_upgradable();
1750 }
1751 let rwlock = s.rwlock;
1752 mem::forget(s);
1753 RwLockUpgradableReadGuard {
1754 rwlock,
1755 marker: PhantomData,
1756 }
1757 }
1758}
1759
1760impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1761 /// Unlocks the `RwLock` using a fair unlock protocol.
1762 ///
1763 /// By default, `RwLock` is unfair and allow the current thread to re-lock
1764 /// the `RwLock` before another has the chance to acquire the lock, even if
1765 /// that thread has been blocked on the `RwLock` for a long time. This is
1766 /// the default because it allows much higher throughput as it avoids
1767 /// forcing a context switch on every `RwLock` unlock. This can result in one
1768 /// thread acquiring a `RwLock` many more times than other threads.
1769 ///
1770 /// However in some cases it can be beneficial to ensure fairness by forcing
1771 /// the lock to pass on to a waiting thread if there is one. This is done by
1772 /// using this method instead of dropping the `RwLockWriteGuard` normally.
1773 #[inline]
1774 #[track_caller]
1775 pub fn unlock_fair(s: Self) {
1776 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1777 unsafe {
1778 s.rwlock.raw.unlock_exclusive_fair();
1779 }
1780 mem::forget(s);
1781 }
1782
1783 /// Temporarily unlocks the `RwLock` to execute the given function.
1784 ///
1785 /// The `RwLock` is unlocked a fair unlock protocol.
1786 ///
1787 /// This is safe because `&mut` guarantees that there exist no other
1788 /// references to the data protected by the `RwLock`.
1789 #[inline]
1790 #[track_caller]
1791 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1792 where
1793 F: FnOnce() -> U,
1794 {
1795 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1796 unsafe {
1797 s.rwlock.raw.unlock_exclusive_fair();
1798 }
1799 defer!(s.rwlock.raw.lock_exclusive());
1800 f()
1801 }
1802
1803 /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1804 ///
1805 /// This method is functionally equivalent to calling `unlock_fair` followed
1806 /// by `write`, however it can be much more efficient in the case where there
1807 /// are no waiting threads.
1808 #[inline]
1809 #[track_caller]
1810 pub fn bump(s: &mut Self) {
1811 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1812 unsafe {
1813 s.rwlock.raw.bump_exclusive();
1814 }
1815 }
1816}
1817
1818impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockWriteGuard<'a, R, T> {
1819 type Target = T;
1820 #[inline]
1821 fn deref(&self) -> &T {
1822 unsafe { &*self.rwlock.data.get() }
1823 }
1824}
1825
1826impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for RwLockWriteGuard<'a, R, T> {
1827 #[inline]
1828 fn deref_mut(&mut self) -> &mut T {
1829 unsafe { &mut *self.rwlock.data.get() }
1830 }
1831}
1832
1833impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockWriteGuard<'a, R, T> {
1834 #[inline]
1835 fn drop(&mut self) {
1836 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1837 unsafe {
1838 self.rwlock.raw.unlock_exclusive();
1839 }
1840 }
1841}
1842
1843impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockWriteGuard<'a, R, T> {
1844 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1845 fmt::Debug::fmt(&**self, f)
1846 }
1847}
1848
1849impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
1850 for RwLockWriteGuard<'a, R, T>
1851{
1852 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1853 (**self).fmt(f)
1854 }
1855}
1856
1857#[cfg(feature = "owning_ref")]
1858unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {}
1859
1860/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
1861/// This is similar to the `RwLockWriteGuard` struct, except instead of using a reference to unlock the `RwLock`
1862/// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime.
1863#[cfg(feature = "arc_lock")]
1864#[clippy::has_significant_drop]
1865#[must_use = "if unused the RwLock will immediately unlock"]
1866pub struct ArcRwLockWriteGuard<R: RawRwLock, T: ?Sized> {
1867 rwlock: Arc<RwLock<R, T>>,
1868 marker: PhantomData<R::GuardMarker>,
1869}
1870
1871#[cfg(feature = "arc_lock")]
1872impl<R: RawRwLock, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1873 /// Returns a reference to the rwlock, contained in its `Arc`.
1874 pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
1875 &s.rwlock
1876 }
1877
1878 /// Unlocks the `RwLock` and returns the `Arc` that was held by the [`ArcRwLockWriteGuard`].
1879 #[inline]
1880 pub fn into_arc(s: Self) -> Arc<RwLock<R, T>> {
1881 // SAFETY: Skip our Drop impl and manually unlock the rwlock.
1882 let s = ManuallyDrop::new(s);
1883 unsafe {
1884 s.rwlock.raw.unlock_exclusive();
1885 ptr::read(&s.rwlock)
1886 }
1887 }
1888
1889 /// Temporarily unlocks the `RwLock` to execute the given function.
1890 ///
1891 /// This is functionally equivalent to the `unlocked` method on [`RwLockWriteGuard`].
1892 #[inline]
1893 #[track_caller]
1894 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1895 where
1896 F: FnOnce() -> U,
1897 {
1898 // Safety: An RwLockWriteGuard always holds a shared lock.
1899 unsafe {
1900 s.rwlock.raw.unlock_exclusive();
1901 }
1902 defer!(s.rwlock.raw.lock_exclusive());
1903 f()
1904 }
1905}
1906
1907#[cfg(feature = "arc_lock")]
1908impl<R: RawRwLockDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1909 /// Atomically downgrades a write lock into a read lock without allowing any
1910 /// writers to take exclusive access of the lock in the meantime.
1911 ///
1912 /// This is functionally equivalent to the `downgrade` method on [`RwLockWriteGuard`].
1913 #[track_caller]
1914 pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> {
1915 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1916 unsafe {
1917 s.rwlock.raw.downgrade();
1918 }
1919
1920 // SAFETY: prevent the arc's refcount from changing using ManuallyDrop and ptr::read
1921 let s = ManuallyDrop::new(s);
1922 let rwlock = unsafe { ptr::read(&s.rwlock) };
1923
1924 ArcRwLockReadGuard {
1925 rwlock,
1926 marker: PhantomData,
1927 }
1928 }
1929}
1930
1931#[cfg(feature = "arc_lock")]
1932impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1933 /// Atomically downgrades a write lock into an upgradable read lock without allowing any
1934 /// writers to take exclusive access of the lock in the meantime.
1935 ///
1936 /// This is functionally identical to the `downgrade_to_upgradable` method on [`RwLockWriteGuard`].
1937 #[track_caller]
1938 pub fn downgrade_to_upgradable(s: Self) -> ArcRwLockUpgradableReadGuard<R, T> {
1939 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1940 unsafe {
1941 s.rwlock.raw.downgrade_to_upgradable();
1942 }
1943
1944 // SAFETY: same as above
1945 let s = ManuallyDrop::new(s);
1946 let rwlock = unsafe { ptr::read(&s.rwlock) };
1947
1948 ArcRwLockUpgradableReadGuard {
1949 rwlock,
1950 marker: PhantomData,
1951 }
1952 }
1953}
1954
1955#[cfg(feature = "arc_lock")]
1956impl<R: RawRwLockFair, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1957 /// Unlocks the `RwLock` using a fair unlock protocol.
1958 ///
1959 /// This is functionally equivalent to the `unlock_fair` method on [`RwLockWriteGuard`].
1960 #[inline]
1961 #[track_caller]
1962 pub fn unlock_fair(s: Self) {
1963 drop(Self::into_arc_fair(s));
1964 }
1965
1966 /// Unlocks the `RwLock` using a fair unlock protocol and returns the `Arc` that was held by the [`ArcRwLockWriteGuard`].
1967 #[inline]
1968 pub fn into_arc_fair(s: Self) -> Arc<RwLock<R, T>> {
1969 // SAFETY: Skip our Drop impl and manually unlock the rwlock.
1970 let s = ManuallyDrop::new(s);
1971 unsafe {
1972 s.rwlock.raw.unlock_exclusive_fair();
1973 ptr::read(&s.rwlock)
1974 }
1975 }
1976
1977 /// Temporarily unlocks the `RwLock` to execute the given function.
1978 ///
1979 /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockWriteGuard`].
1980 #[inline]
1981 #[track_caller]
1982 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1983 where
1984 F: FnOnce() -> U,
1985 {
1986 // Safety: An RwLockWriteGuard always holds an exclusive lock.
1987 unsafe {
1988 s.rwlock.raw.unlock_exclusive_fair();
1989 }
1990 defer!(s.rwlock.raw.lock_exclusive());
1991 f()
1992 }
1993
1994 /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1995 ///
1996 /// This method is functionally equivalent to the `bump` method on [`RwLockWriteGuard`].
1997 #[inline]
1998 #[track_caller]
1999 pub fn bump(s: &mut Self) {
2000 // Safety: An RwLockWriteGuard always holds an exclusive lock.
2001 unsafe {
2002 s.rwlock.raw.bump_exclusive();
2003 }
2004 }
2005}
2006
2007#[cfg(feature = "arc_lock")]
2008impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockWriteGuard<R, T> {
2009 type Target = T;
2010 #[inline]
2011 fn deref(&self) -> &T {
2012 unsafe { &*self.rwlock.data.get() }
2013 }
2014}
2015
2016#[cfg(feature = "arc_lock")]
2017impl<R: RawRwLock, T: ?Sized> DerefMut for ArcRwLockWriteGuard<R, T> {
2018 #[inline]
2019 fn deref_mut(&mut self) -> &mut T {
2020 unsafe { &mut *self.rwlock.data.get() }
2021 }
2022}
2023
2024#[cfg(feature = "arc_lock")]
2025impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockWriteGuard<R, T> {
2026 #[inline]
2027 fn drop(&mut self) {
2028 // Safety: An RwLockWriteGuard always holds an exclusive lock.
2029 unsafe {
2030 self.rwlock.raw.unlock_exclusive();
2031 }
2032 }
2033}
2034
2035#[cfg(feature = "arc_lock")]
2036impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockWriteGuard<R, T> {
2037 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2038 fmt::Debug::fmt(&**self, f)
2039 }
2040}
2041
2042#[cfg(feature = "arc_lock")]
2043impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockWriteGuard<R, T> {
2044 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2045 (**self).fmt(f)
2046 }
2047}
2048
2049/// RAII structure used to release the upgradable read access of a lock when
2050/// dropped.
2051#[clippy::has_significant_drop]
2052#[must_use = "if unused the RwLock will immediately unlock"]
2053pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade, T: ?Sized> {
2054 rwlock: &'a RwLock<R, T>,
2055 marker: PhantomData<(&'a T, R::GuardMarker)>,
2056}
2057
2058unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + Sync + 'a> Sync
2059 for RwLockUpgradableReadGuard<'a, R, T>
2060{
2061}
2062
2063impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
2064 /// Returns a reference to the original reader-writer lock object.
2065 pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
2066 s.rwlock
2067 }
2068
2069 /// Temporarily unlocks the `RwLock` to execute the given function.
2070 ///
2071 /// This is safe because `&mut` guarantees that there exist no other
2072 /// references to the data protected by the `RwLock`.
2073 #[inline]
2074 #[track_caller]
2075 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
2076 where
2077 F: FnOnce() -> U,
2078 {
2079 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2080 unsafe {
2081 s.rwlock.raw.unlock_upgradable();
2082 }
2083 defer!(s.rwlock.raw.lock_upgradable());
2084 f()
2085 }
2086
2087 /// Atomically upgrades an upgradable read lock lock into an exclusive write lock,
2088 /// blocking the current thread until it can be acquired.
2089 #[track_caller]
2090 pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> {
2091 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2092 unsafe {
2093 s.rwlock.raw.upgrade();
2094 }
2095 let rwlock = s.rwlock;
2096 mem::forget(s);
2097 RwLockWriteGuard {
2098 rwlock,
2099 marker: PhantomData,
2100 }
2101 }
2102
2103 /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2104 ///
2105 /// If the access could not be granted at this time, then the current guard is returned.
2106 #[track_caller]
2107 pub fn try_upgrade(s: Self) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
2108 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2109 if unsafe { s.rwlock.raw.try_upgrade() } {
2110 let rwlock = s.rwlock;
2111 mem::forget(s);
2112 Ok(RwLockWriteGuard {
2113 rwlock,
2114 marker: PhantomData,
2115 })
2116 } else {
2117 Err(s)
2118 }
2119 }
2120}
2121
2122impl<'a, R: RawRwLockUpgradeFair + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
2123 /// Unlocks the `RwLock` using a fair unlock protocol.
2124 ///
2125 /// By default, `RwLock` is unfair and allow the current thread to re-lock
2126 /// the `RwLock` before another has the chance to acquire the lock, even if
2127 /// that thread has been blocked on the `RwLock` for a long time. This is
2128 /// the default because it allows much higher throughput as it avoids
2129 /// forcing a context switch on every `RwLock` unlock. This can result in one
2130 /// thread acquiring a `RwLock` many more times than other threads.
2131 ///
2132 /// However in some cases it can be beneficial to ensure fairness by forcing
2133 /// the lock to pass on to a waiting thread if there is one. This is done by
2134 /// using this method instead of dropping the `RwLockUpgradableReadGuard` normally.
2135 #[inline]
2136 #[track_caller]
2137 pub fn unlock_fair(s: Self) {
2138 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2139 unsafe {
2140 s.rwlock.raw.unlock_upgradable_fair();
2141 }
2142 mem::forget(s);
2143 }
2144
2145 /// Temporarily unlocks the `RwLock` to execute the given function.
2146 ///
2147 /// The `RwLock` is unlocked a fair unlock protocol.
2148 ///
2149 /// This is safe because `&mut` guarantees that there exist no other
2150 /// references to the data protected by the `RwLock`.
2151 #[inline]
2152 #[track_caller]
2153 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
2154 where
2155 F: FnOnce() -> U,
2156 {
2157 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2158 unsafe {
2159 s.rwlock.raw.unlock_upgradable_fair();
2160 }
2161 defer!(s.rwlock.raw.lock_upgradable());
2162 f()
2163 }
2164
2165 /// Temporarily yields the `RwLock` to a waiting thread if there is one.
2166 ///
2167 /// This method is functionally equivalent to calling `unlock_fair` followed
2168 /// by `upgradable_read`, however it can be much more efficient in the case where there
2169 /// are no waiting threads.
2170 #[inline]
2171 #[track_caller]
2172 pub fn bump(s: &mut Self) {
2173 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2174 unsafe {
2175 s.rwlock.raw.bump_upgradable();
2176 }
2177 }
2178}
2179
2180impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
2181 /// Atomically downgrades an upgradable read lock lock into a shared read lock
2182 /// without allowing any writers to take exclusive access of the lock in the
2183 /// meantime.
2184 ///
2185 /// Note that if there are any writers currently waiting to take the lock
2186 /// then other readers may not be able to acquire the lock even if it was
2187 /// downgraded.
2188 #[track_caller]
2189 pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> {
2190 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2191 unsafe {
2192 s.rwlock.raw.downgrade_upgradable();
2193 }
2194 let rwlock = s.rwlock;
2195 mem::forget(s);
2196 RwLockReadGuard {
2197 rwlock,
2198 marker: PhantomData,
2199 }
2200 }
2201
2202 /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock,
2203 /// blocking the current thread until it can be acquired.
2204 ///
2205 /// Then, calls the provided closure with an exclusive reference to the lock's data.
2206 ///
2207 /// Finally, atomically downgrades the lock back to an upgradable read lock.
2208 /// The closure's return value is wrapped in `Some` and returned.
2209 ///
2210 /// This function only requires a mutable reference to the guard, unlike
2211 /// `upgrade` which takes the guard by value.
2212 #[track_caller]
2213 pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret {
2214 unsafe {
2215 self.rwlock.raw.upgrade();
2216 }
2217
2218 // Safety: We just upgraded the lock, so we have mutable access to the data.
2219 // This will restore the state the lock was in at the start of the function.
2220 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2221
2222 // Safety: We upgraded the lock, so we have mutable access to the data.
2223 // When this function returns, whether by drop or panic,
2224 // the drop guard will downgrade it back to an upgradeable lock.
2225 f(unsafe { &mut *self.rwlock.data.get() })
2226 }
2227
2228 /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2229 ///
2230 /// If the access could not be granted at this time, then `None` is returned.
2231 ///
2232 /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2233 /// and finally downgrades the lock back to an upgradable read lock.
2234 /// The closure's return value is wrapped in `Some` and returned.
2235 ///
2236 /// This function only requires a mutable reference to the guard, unlike
2237 /// `try_upgrade` which takes the guard by value.
2238 #[track_caller]
2239 pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> {
2240 if unsafe { self.rwlock.raw.try_upgrade() } {
2241 // Safety: We just upgraded the lock, so we have mutable access to the data.
2242 // This will restore the state the lock was in at the start of the function.
2243 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2244
2245 // Safety: We upgraded the lock, so we have mutable access to the data.
2246 // When this function returns, whether by drop or panic,
2247 // the drop guard will downgrade it back to an upgradeable lock.
2248 Some(f(unsafe { &mut *self.rwlock.data.get() }))
2249 } else {
2250 None
2251 }
2252 }
2253}
2254
2255impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
2256 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2257 /// write lock, until a timeout is reached.
2258 ///
2259 /// If the access could not be granted before the timeout expires, then
2260 /// the current guard is returned.
2261 #[track_caller]
2262 pub fn try_upgrade_for(
2263 s: Self,
2264 timeout: R::Duration,
2265 ) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
2266 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2267 if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } {
2268 let rwlock = s.rwlock;
2269 mem::forget(s);
2270 Ok(RwLockWriteGuard {
2271 rwlock,
2272 marker: PhantomData,
2273 })
2274 } else {
2275 Err(s)
2276 }
2277 }
2278
2279 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2280 /// write lock, until a timeout is reached.
2281 ///
2282 /// If the access could not be granted before the timeout expires, then
2283 /// the current guard is returned.
2284 #[inline]
2285 #[track_caller]
2286 pub fn try_upgrade_until(
2287 s: Self,
2288 timeout: R::Instant,
2289 ) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
2290 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2291 if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } {
2292 let rwlock = s.rwlock;
2293 mem::forget(s);
2294 Ok(RwLockWriteGuard {
2295 rwlock,
2296 marker: PhantomData,
2297 })
2298 } else {
2299 Err(s)
2300 }
2301 }
2302}
2303
2304impl<'a, R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a>
2305 RwLockUpgradableReadGuard<'a, R, T>
2306{
2307 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2308 /// write lock, until a timeout is reached.
2309 ///
2310 /// If the access could not be granted before the timeout expires, then
2311 /// `None` is returned.
2312 ///
2313 /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2314 /// and finally downgrades the lock back to an upgradable read lock.
2315 /// The closure's return value is wrapped in `Some` and returned.
2316 ///
2317 /// This function only requires a mutable reference to the guard, unlike
2318 /// `try_upgrade_for` which takes the guard by value.
2319 #[track_caller]
2320 pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>(
2321 &mut self,
2322 timeout: R::Duration,
2323 f: F,
2324 ) -> Option<Ret> {
2325 if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } {
2326 // Safety: We just upgraded the lock, so we have mutable access to the data.
2327 // This will restore the state the lock was in at the start of the function.
2328 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2329
2330 // Safety: We upgraded the lock, so we have mutable access to the data.
2331 // When this function returns, whether by drop or panic,
2332 // the drop guard will downgrade it back to an upgradeable lock.
2333 Some(f(unsafe { &mut *self.rwlock.data.get() }))
2334 } else {
2335 None
2336 }
2337 }
2338
2339 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2340 /// write lock, until a timeout is reached.
2341 ///
2342 /// If the access could not be granted before the timeout expires, then
2343 /// `None` is returned.
2344 ///
2345 /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2346 /// and finally downgrades the lock back to an upgradable read lock.
2347 /// The closure's return value is wrapped in `Some` and returned.
2348 ///
2349 /// This function only requires a mutable reference to the guard, unlike
2350 /// `try_upgrade_until` which takes the guard by value.
2351 #[track_caller]
2352 pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>(
2353 &mut self,
2354 timeout: R::Instant,
2355 f: F,
2356 ) -> Option<Ret> {
2357 if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } {
2358 // Safety: We just upgraded the lock, so we have mutable access to the data.
2359 // This will restore the state the lock was in at the start of the function.
2360 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2361
2362 // Safety: We upgraded the lock, so we have mutable access to the data.
2363 // When this function returns, whether by drop or panic,
2364 // the drop guard will downgrade it back to an upgradeable lock.
2365 Some(f(unsafe { &mut *self.rwlock.data.get() }))
2366 } else {
2367 None
2368 }
2369 }
2370}
2371
2372impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Deref for RwLockUpgradableReadGuard<'a, R, T> {
2373 type Target = T;
2374 #[inline]
2375 fn deref(&self) -> &T {
2376 unsafe { &*self.rwlock.data.get() }
2377 }
2378}
2379
2380impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Drop for RwLockUpgradableReadGuard<'a, R, T> {
2381 #[inline]
2382 fn drop(&mut self) {
2383 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2384 unsafe {
2385 self.rwlock.raw.unlock_upgradable();
2386 }
2387 }
2388}
2389
2390impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
2391 for RwLockUpgradableReadGuard<'a, R, T>
2392{
2393 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2394 fmt::Debug::fmt(&**self, f)
2395 }
2396}
2397
2398impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
2399 for RwLockUpgradableReadGuard<'a, R, T>
2400{
2401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2402 (**self).fmt(f)
2403 }
2404}
2405
2406#[cfg(feature = "owning_ref")]
2407unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress
2408 for RwLockUpgradableReadGuard<'a, R, T>
2409{
2410}
2411
2412/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
2413/// This is similar to the `RwLockUpgradableReadGuard` struct, except instead of using a reference to unlock the
2414/// `RwLock` it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static`
2415/// lifetime.
2416#[cfg(feature = "arc_lock")]
2417#[clippy::has_significant_drop]
2418#[must_use = "if unused the RwLock will immediately unlock"]
2419pub struct ArcRwLockUpgradableReadGuard<R: RawRwLockUpgrade, T: ?Sized> {
2420 rwlock: Arc<RwLock<R, T>>,
2421 marker: PhantomData<R::GuardMarker>,
2422}
2423
2424#[cfg(feature = "arc_lock")]
2425impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2426 /// Returns a reference to the rwlock, contained in its original `Arc`.
2427 pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
2428 &s.rwlock
2429 }
2430
2431 /// Unlocks the `RwLock` and returns the `Arc` that was held by the [`ArcRwLockUpgradableReadGuard`].
2432 #[inline]
2433 pub fn into_arc(s: Self) -> Arc<RwLock<R, T>> {
2434 // SAFETY: Skip our Drop impl and manually unlock the rwlock.
2435 let s = ManuallyDrop::new(s);
2436 unsafe {
2437 s.rwlock.raw.unlock_upgradable();
2438 ptr::read(&s.rwlock)
2439 }
2440 }
2441
2442 /// Temporarily unlocks the `RwLock` to execute the given function.
2443 ///
2444 /// This is functionally identical to the `unlocked` method on [`RwLockUpgradableReadGuard`].
2445 #[inline]
2446 #[track_caller]
2447 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
2448 where
2449 F: FnOnce() -> U,
2450 {
2451 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2452 unsafe {
2453 s.rwlock.raw.unlock_upgradable();
2454 }
2455 defer!(s.rwlock.raw.lock_upgradable());
2456 f()
2457 }
2458
2459 /// Atomically upgrades an upgradable read lock lock into an exclusive write lock,
2460 /// blocking the current thread until it can be acquired.
2461 #[track_caller]
2462 pub fn upgrade(s: Self) -> ArcRwLockWriteGuard<R, T> {
2463 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2464 unsafe {
2465 s.rwlock.raw.upgrade();
2466 }
2467
2468 // SAFETY: avoid incrementing or decrementing the refcount using ManuallyDrop and reading the Arc out
2469 // of the struct
2470 let s = ManuallyDrop::new(s);
2471 let rwlock = unsafe { ptr::read(&s.rwlock) };
2472
2473 ArcRwLockWriteGuard {
2474 rwlock,
2475 marker: PhantomData,
2476 }
2477 }
2478
2479 /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2480 ///
2481 /// If the access could not be granted at this time, then the current guard is returned.
2482 #[track_caller]
2483 pub fn try_upgrade(s: Self) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
2484 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2485 if unsafe { s.rwlock.raw.try_upgrade() } {
2486 // SAFETY: same as above
2487 let s = ManuallyDrop::new(s);
2488 let rwlock = unsafe { ptr::read(&s.rwlock) };
2489
2490 Ok(ArcRwLockWriteGuard {
2491 rwlock,
2492 marker: PhantomData,
2493 })
2494 } else {
2495 Err(s)
2496 }
2497 }
2498}
2499
2500#[cfg(feature = "arc_lock")]
2501impl<R: RawRwLockUpgradeFair, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2502 /// Unlocks the `RwLock` using a fair unlock protocol.
2503 ///
2504 /// This is functionally identical to the `unlock_fair` method on [`RwLockUpgradableReadGuard`].
2505 #[inline]
2506 #[track_caller]
2507 pub fn unlock_fair(s: Self) {
2508 drop(Self::into_arc_fair(s));
2509 }
2510
2511 /// Unlocks the `RwLock` using a fair unlock protocol and returns the `Arc` that was held by the [`ArcRwLockUpgradableReadGuard`].
2512 #[inline]
2513 pub fn into_arc_fair(s: Self) -> Arc<RwLock<R, T>> {
2514 // SAFETY: Skip our Drop impl and manually unlock the rwlock.
2515 let s = ManuallyDrop::new(s);
2516 unsafe {
2517 s.rwlock.raw.unlock_upgradable_fair();
2518 ptr::read(&s.rwlock)
2519 }
2520 }
2521
2522 /// Temporarily unlocks the `RwLock` to execute the given function.
2523 ///
2524 /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockUpgradableReadGuard`].
2525 #[inline]
2526 #[track_caller]
2527 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
2528 where
2529 F: FnOnce() -> U,
2530 {
2531 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2532 unsafe {
2533 s.rwlock.raw.unlock_upgradable_fair();
2534 }
2535 defer!(s.rwlock.raw.lock_upgradable());
2536 f()
2537 }
2538
2539 /// Temporarily yields the `RwLock` to a waiting thread if there is one.
2540 ///
2541 /// This method is functionally equivalent to calling `bump` on [`RwLockUpgradableReadGuard`].
2542 #[inline]
2543 #[track_caller]
2544 pub fn bump(s: &mut Self) {
2545 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2546 unsafe {
2547 s.rwlock.raw.bump_upgradable();
2548 }
2549 }
2550}
2551
2552#[cfg(feature = "arc_lock")]
2553impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2554 /// Atomically downgrades an upgradable read lock lock into a shared read lock
2555 /// without allowing any writers to take exclusive access of the lock in the
2556 /// meantime.
2557 ///
2558 /// Note that if there are any writers currently waiting to take the lock
2559 /// then other readers may not be able to acquire the lock even if it was
2560 /// downgraded.
2561 #[track_caller]
2562 pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> {
2563 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2564 unsafe {
2565 s.rwlock.raw.downgrade_upgradable();
2566 }
2567
2568 // SAFETY: use ManuallyDrop and ptr::read to ensure the refcount is not changed
2569 let s = ManuallyDrop::new(s);
2570 let rwlock = unsafe { ptr::read(&s.rwlock) };
2571
2572 ArcRwLockReadGuard {
2573 rwlock,
2574 marker: PhantomData,
2575 }
2576 }
2577
2578 /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock,
2579 /// blocking the current thread until it can be acquired.
2580 ///
2581 /// Then, calls the provided closure with an exclusive reference to the lock's data.
2582 ///
2583 /// Finally, atomically downgrades the lock back to an upgradable read lock.
2584 /// The closure's return value is returned.
2585 ///
2586 /// This function only requires a mutable reference to the guard, unlike
2587 /// `upgrade` which takes the guard by value.
2588 #[track_caller]
2589 pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret {
2590 unsafe {
2591 self.rwlock.raw.upgrade();
2592 }
2593
2594 // Safety: We just upgraded the lock, so we have mutable access to the data.
2595 // This will restore the state the lock was in at the start of the function.
2596 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2597
2598 // Safety: We upgraded the lock, so we have mutable access to the data.
2599 // When this function returns, whether by drop or panic,
2600 // the drop guard will downgrade it back to an upgradeable lock.
2601 f(unsafe { &mut *self.rwlock.data.get() })
2602 }
2603
2604 /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2605 ///
2606 /// If the access could not be granted at this time, then `None` is returned.
2607 ///
2608 /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2609 /// and finally downgrades the lock back to an upgradable read lock.
2610 /// The closure's return value is wrapped in `Some` and returned.
2611 ///
2612 /// This function only requires a mutable reference to the guard, unlike
2613 /// `try_upgrade` which takes the guard by value.
2614 #[track_caller]
2615 pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> {
2616 if unsafe { self.rwlock.raw.try_upgrade() } {
2617 // Safety: We just upgraded the lock, so we have mutable access to the data.
2618 // This will restore the state the lock was in at the start of the function.
2619 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2620
2621 // Safety: We upgraded the lock, so we have mutable access to the data.
2622 // When this function returns, whether by drop or panic,
2623 // the drop guard will downgrade it back to an upgradeable lock.
2624 Some(f(unsafe { &mut *self.rwlock.data.get() }))
2625 } else {
2626 None
2627 }
2628 }
2629}
2630
2631#[cfg(feature = "arc_lock")]
2632impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2633 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2634 /// write lock, until a timeout is reached.
2635 ///
2636 /// If the access could not be granted before the timeout expires, then
2637 /// the current guard is returned.
2638 #[track_caller]
2639 pub fn try_upgrade_for(
2640 s: Self,
2641 timeout: R::Duration,
2642 ) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
2643 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2644 if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } {
2645 // SAFETY: same as above
2646 let s = ManuallyDrop::new(s);
2647 let rwlock = unsafe { ptr::read(&s.rwlock) };
2648
2649 Ok(ArcRwLockWriteGuard {
2650 rwlock,
2651 marker: PhantomData,
2652 })
2653 } else {
2654 Err(s)
2655 }
2656 }
2657
2658 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2659 /// write lock, until a timeout is reached.
2660 ///
2661 /// If the access could not be granted before the timeout expires, then
2662 /// the current guard is returned.
2663 #[inline]
2664 #[track_caller]
2665 pub fn try_upgrade_until(
2666 s: Self,
2667 timeout: R::Instant,
2668 ) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
2669 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2670 if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } {
2671 // SAFETY: same as above
2672 let s = ManuallyDrop::new(s);
2673 let rwlock = unsafe { ptr::read(&s.rwlock) };
2674
2675 Ok(ArcRwLockWriteGuard {
2676 rwlock,
2677 marker: PhantomData,
2678 })
2679 } else {
2680 Err(s)
2681 }
2682 }
2683}
2684
2685#[cfg(feature = "arc_lock")]
2686impl<R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade, T: ?Sized>
2687 ArcRwLockUpgradableReadGuard<R, T>
2688{
2689 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2690 /// write lock, until a timeout is reached.
2691 ///
2692 /// If the access could not be granted before the timeout expires, then
2693 /// `None` is returned.
2694 ///
2695 /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2696 /// and finally downgrades the lock back to an upgradable read lock.
2697 /// The closure's return value is wrapped in `Some` and returned.
2698 ///
2699 /// This function only requires a mutable reference to the guard, unlike
2700 /// `try_upgrade_for` which takes the guard by value.
2701 #[track_caller]
2702 pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>(
2703 &mut self,
2704 timeout: R::Duration,
2705 f: F,
2706 ) -> Option<Ret> {
2707 if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } {
2708 // Safety: We just upgraded the lock, so we have mutable access to the data.
2709 // This will restore the state the lock was in at the start of the function.
2710 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2711
2712 // Safety: We upgraded the lock, so we have mutable access to the data.
2713 // When this function returns, whether by drop or panic,
2714 // the drop guard will downgrade it back to an upgradeable lock.
2715 Some(f(unsafe { &mut *self.rwlock.data.get() }))
2716 } else {
2717 None
2718 }
2719 }
2720
2721 /// Tries to atomically upgrade an upgradable read lock into an exclusive
2722 /// write lock, until a timeout is reached.
2723 ///
2724 /// If the access could not be granted before the timeout expires, then
2725 /// `None` is returned.
2726 ///
2727 /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2728 /// and finally downgrades the lock back to an upgradable read lock.
2729 /// The closure's return value is wrapped in `Some` and returned.
2730 ///
2731 /// This function only requires a mutable reference to the guard, unlike
2732 /// `try_upgrade_until` which takes the guard by value.
2733 #[track_caller]
2734 pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>(
2735 &mut self,
2736 timeout: R::Instant,
2737 f: F,
2738 ) -> Option<Ret> {
2739 if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } {
2740 // Safety: We just upgraded the lock, so we have mutable access to the data.
2741 // This will restore the state the lock was in at the start of the function.
2742 defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2743
2744 // Safety: We upgraded the lock, so we have mutable access to the data.
2745 // When this function returns, whether by drop or panic,
2746 // the drop guard will downgrade it back to an upgradeable lock.
2747 Some(f(unsafe { &mut *self.rwlock.data.get() }))
2748 } else {
2749 None
2750 }
2751 }
2752}
2753
2754#[cfg(feature = "arc_lock")]
2755impl<R: RawRwLockUpgrade, T: ?Sized> Deref for ArcRwLockUpgradableReadGuard<R, T> {
2756 type Target = T;
2757 #[inline]
2758 fn deref(&self) -> &T {
2759 unsafe { &*self.rwlock.data.get() }
2760 }
2761}
2762
2763#[cfg(feature = "arc_lock")]
2764impl<R: RawRwLockUpgrade, T: ?Sized> Drop for ArcRwLockUpgradableReadGuard<R, T> {
2765 #[inline]
2766 fn drop(&mut self) {
2767 // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2768 unsafe {
2769 self.rwlock.raw.unlock_upgradable();
2770 }
2771 }
2772}
2773
2774#[cfg(feature = "arc_lock")]
2775impl<R: RawRwLockUpgrade, T: fmt::Debug + ?Sized> fmt::Debug
2776 for ArcRwLockUpgradableReadGuard<R, T>
2777{
2778 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2779 fmt::Debug::fmt(&**self, f)
2780 }
2781}
2782
2783#[cfg(feature = "arc_lock")]
2784impl<R: RawRwLockUpgrade, T: fmt::Display + ?Sized> fmt::Display
2785 for ArcRwLockUpgradableReadGuard<R, T>
2786{
2787 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2788 (**self).fmt(f)
2789 }
2790}
2791
2792/// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a
2793/// subfield of the protected data.
2794///
2795/// The main difference between `MappedRwLockReadGuard` and `RwLockReadGuard` is that the
2796/// former doesn't support temporarily unlocking and re-locking, since that
2797/// could introduce soundness issues if the locked object is modified by another
2798/// thread.
2799#[clippy::has_significant_drop]
2800#[must_use = "if unused the RwLock will immediately unlock"]
2801pub struct MappedRwLockReadGuard<'a, R: RawRwLock, T: ?Sized> {
2802 raw: &'a R,
2803 data: *const T,
2804 marker: PhantomData<&'a T>,
2805}
2806
2807unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for MappedRwLockReadGuard<'a, R, T> {}
2808unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Send for MappedRwLockReadGuard<'a, R, T> where
2809 R::GuardMarker: Send
2810{
2811}
2812
2813impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
2814 /// Make a new `MappedRwLockReadGuard` for a component of the locked data.
2815 ///
2816 /// This operation cannot fail as the `MappedRwLockReadGuard` passed
2817 /// in already locked the data.
2818 ///
2819 /// This is an associated function that needs to be
2820 /// used as `MappedRwLockReadGuard::map(...)`. A method would interfere with methods of
2821 /// the same name on the contents of the locked data.
2822 #[inline]
2823 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U>
2824 where
2825 F: FnOnce(&T) -> &U,
2826 {
2827 let raw = s.raw;
2828 let data = f(unsafe { &*s.data });
2829 mem::forget(s);
2830 MappedRwLockReadGuard {
2831 raw,
2832 data,
2833 marker: PhantomData,
2834 }
2835 }
2836
2837 /// Attempts to make a new `MappedRwLockReadGuard` for a component of the
2838 /// locked data. The original guard is return if the closure returns `None`.
2839 ///
2840 /// This operation cannot fail as the `MappedRwLockReadGuard` passed
2841 /// in already locked the data.
2842 ///
2843 /// This is an associated function that needs to be
2844 /// used as `MappedRwLockReadGuard::try_map(...)`. A method would interfere with methods of
2845 /// the same name on the contents of the locked data.
2846 #[inline]
2847 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
2848 where
2849 F: FnOnce(&T) -> Option<&U>,
2850 {
2851 let raw = s.raw;
2852 let data = match f(unsafe { &*s.data }) {
2853 Some(data) => data,
2854 None => return Err(s),
2855 };
2856 mem::forget(s);
2857 Ok(MappedRwLockReadGuard {
2858 raw,
2859 data,
2860 marker: PhantomData,
2861 })
2862 }
2863
2864 /// Attempts to make a new `MappedRwLockReadGuard` for a component of the
2865 /// locked data. The original guard is returned alongside arbitrary user data
2866 /// if the closure returns `Err`.
2867 ///
2868 /// This operation cannot fail as the `MappedRwLockReadGuard` passed
2869 /// in already locked the data.
2870 ///
2871 /// This is an associated function that needs to be
2872 /// used as `MappedRwLockReadGuard::try_map_or_err(...)`. A method would interfere with methods of
2873 /// the same name on the contents of the locked data.
2874 #[inline]
2875 pub fn try_map_or_else<U: ?Sized, F, E>(
2876 s: Self,
2877 f: F,
2878 ) -> Result<MappedRwLockReadGuard<'a, R, U>, (Self, E)>
2879 where
2880 F: FnOnce(&T) -> Result<&U, E>,
2881 {
2882 let raw = s.raw;
2883 let data = match f(unsafe { &*s.data }) {
2884 Ok(data) => data,
2885 Err(e) => return Err((s, e)),
2886 };
2887 mem::forget(s);
2888 Ok(MappedRwLockReadGuard {
2889 raw,
2890 data,
2891 marker: PhantomData,
2892 })
2893 }
2894}
2895
2896impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
2897 /// Unlocks the `RwLock` using a fair unlock protocol.
2898 ///
2899 /// By default, `RwLock` is unfair and allow the current thread to re-lock
2900 /// the `RwLock` before another has the chance to acquire the lock, even if
2901 /// that thread has been blocked on the `RwLock` for a long time. This is
2902 /// the default because it allows much higher throughput as it avoids
2903 /// forcing a context switch on every `RwLock` unlock. This can result in one
2904 /// thread acquiring a `RwLock` many more times than other threads.
2905 ///
2906 /// However in some cases it can be beneficial to ensure fairness by forcing
2907 /// the lock to pass on to a waiting thread if there is one. This is done by
2908 /// using this method instead of dropping the `MappedRwLockReadGuard` normally.
2909 #[inline]
2910 #[track_caller]
2911 pub fn unlock_fair(s: Self) {
2912 // Safety: A MappedRwLockReadGuard always holds a shared lock.
2913 unsafe {
2914 s.raw.unlock_shared_fair();
2915 }
2916 mem::forget(s);
2917 }
2918}
2919
2920impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockReadGuard<'a, R, T> {
2921 type Target = T;
2922 #[inline]
2923 fn deref(&self) -> &T {
2924 unsafe { &*self.data }
2925 }
2926}
2927
2928impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockReadGuard<'a, R, T> {
2929 #[inline]
2930 fn drop(&mut self) {
2931 // Safety: A MappedRwLockReadGuard always holds a shared lock.
2932 unsafe {
2933 self.raw.unlock_shared();
2934 }
2935 }
2936}
2937
2938impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
2939 for MappedRwLockReadGuard<'a, R, T>
2940{
2941 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2942 fmt::Debug::fmt(&**self, f)
2943 }
2944}
2945
2946impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
2947 for MappedRwLockReadGuard<'a, R, T>
2948{
2949 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2950 (**self).fmt(f)
2951 }
2952}
2953
2954#[cfg(feature = "owning_ref")]
2955unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress
2956 for MappedRwLockReadGuard<'a, R, T>
2957{
2958}
2959
2960/// An RAII write lock guard returned by `RwLockWriteGuard::map`, which can point to a
2961/// subfield of the protected data.
2962///
2963/// The main difference between `MappedRwLockWriteGuard` and `RwLockWriteGuard` is that the
2964/// former doesn't support temporarily unlocking and re-locking, since that
2965/// could introduce soundness issues if the locked object is modified by another
2966/// thread.
2967#[clippy::has_significant_drop]
2968#[must_use = "if unused the RwLock will immediately unlock"]
2969pub struct MappedRwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> {
2970 raw: &'a R,
2971 data: *mut T,
2972 marker: PhantomData<&'a mut T>,
2973}
2974
2975unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync
2976 for MappedRwLockWriteGuard<'a, R, T>
2977{
2978}
2979unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Send + 'a> Send for MappedRwLockWriteGuard<'a, R, T> where
2980 R::GuardMarker: Send
2981{
2982}
2983
2984impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
2985 /// Make a new `MappedRwLockWriteGuard` for a component of the locked data.
2986 ///
2987 /// This operation cannot fail as the `MappedRwLockWriteGuard` passed
2988 /// in already locked the data.
2989 ///
2990 /// This is an associated function that needs to be
2991 /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of
2992 /// the same name on the contents of the locked data.
2993 #[inline]
2994 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U>
2995 where
2996 F: FnOnce(&mut T) -> &mut U,
2997 {
2998 let raw = s.raw;
2999 let data = f(unsafe { &mut *s.data });
3000 mem::forget(s);
3001 MappedRwLockWriteGuard {
3002 raw,
3003 data,
3004 marker: PhantomData,
3005 }
3006 }
3007
3008 /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the
3009 /// locked data. The original guard is return if the closure returns `None`.
3010 ///
3011 /// This operation cannot fail as the `MappedRwLockWriteGuard` passed
3012 /// in already locked the data.
3013 ///
3014 /// This is an associated function that needs to be
3015 /// used as `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with methods of
3016 /// the same name on the contents of the locked data.
3017 #[inline]
3018 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
3019 where
3020 F: FnOnce(&mut T) -> Option<&mut U>,
3021 {
3022 let raw = s.raw;
3023 let data = match f(unsafe { &mut *s.data }) {
3024 Some(data) => data,
3025 None => return Err(s),
3026 };
3027 mem::forget(s);
3028 Ok(MappedRwLockWriteGuard {
3029 raw,
3030 data,
3031 marker: PhantomData,
3032 })
3033 }
3034
3035 /// Attempts to make a new `MappedRwLockWriteGuard` for a component of the
3036 /// locked data. The original guard is returned alongside arbitrary user data
3037 /// if the closure returns `Err`.
3038 ///
3039 /// This operation cannot fail as the `MappedRwLockWriteGuard` passed
3040 /// in already locked the data.
3041 ///
3042 /// This is an associated function that needs to be
3043 /// used as `MappedRwLockWriteGuard::try_map_or_err(...)`. A method would interfere with methods of
3044 /// the same name on the contents of the locked data.
3045 #[inline]
3046 pub fn try_map_or_err<U: ?Sized, F, E>(
3047 s: Self,
3048 f: F,
3049 ) -> Result<MappedRwLockWriteGuard<'a, R, U>, (Self, E)>
3050 where
3051 F: FnOnce(&mut T) -> Result<&mut U, E>,
3052 {
3053 let raw = s.raw;
3054 let data = match f(unsafe { &mut *s.data }) {
3055 Ok(data) => data,
3056 Err(e) => return Err((s, e)),
3057 };
3058 mem::forget(s);
3059 Ok(MappedRwLockWriteGuard {
3060 raw,
3061 data,
3062 marker: PhantomData,
3063 })
3064 }
3065}
3066
3067impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
3068 /// Unlocks the `RwLock` using a fair unlock protocol.
3069 ///
3070 /// By default, `RwLock` is unfair and allow the current thread to re-lock
3071 /// the `RwLock` before another has the chance to acquire the lock, even if
3072 /// that thread has been blocked on the `RwLock` for a long time. This is
3073 /// the default because it allows much higher throughput as it avoids
3074 /// forcing a context switch on every `RwLock` unlock. This can result in one
3075 /// thread acquiring a `RwLock` many more times than other threads.
3076 ///
3077 /// However in some cases it can be beneficial to ensure fairness by forcing
3078 /// the lock to pass on to a waiting thread if there is one. This is done by
3079 /// using this method instead of dropping the `MappedRwLockWriteGuard` normally.
3080 #[inline]
3081 #[track_caller]
3082 pub fn unlock_fair(s: Self) {
3083 // Safety: A MappedRwLockWriteGuard always holds an exclusive lock.
3084 unsafe {
3085 s.raw.unlock_exclusive_fair();
3086 }
3087 mem::forget(s);
3088 }
3089}
3090
3091impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockWriteGuard<'a, R, T> {
3092 type Target = T;
3093 #[inline]
3094 fn deref(&self) -> &T {
3095 unsafe { &*self.data }
3096 }
3097}
3098
3099impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for MappedRwLockWriteGuard<'a, R, T> {
3100 #[inline]
3101 fn deref_mut(&mut self) -> &mut T {
3102 unsafe { &mut *self.data }
3103 }
3104}
3105
3106impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockWriteGuard<'a, R, T> {
3107 #[inline]
3108 fn drop(&mut self) {
3109 // Safety: A MappedRwLockWriteGuard always holds an exclusive lock.
3110 unsafe {
3111 self.raw.unlock_exclusive();
3112 }
3113 }
3114}
3115
3116impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
3117 for MappedRwLockWriteGuard<'a, R, T>
3118{
3119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3120 fmt::Debug::fmt(&**self, f)
3121 }
3122}
3123
3124impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
3125 for MappedRwLockWriteGuard<'a, R, T>
3126{
3127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3128 (**self).fmt(f)
3129 }
3130}
3131
3132#[cfg(feature = "owning_ref")]
3133unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress
3134 for MappedRwLockWriteGuard<'a, R, T>
3135{
3136}