Skip to main content

lock_api/
rwlock.rs

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