lock_api/
rwlock.rs

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