Skip to main content

lock_api/
rwlock.rs

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