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 RwLocks 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 RwLocks 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 RwLocks 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 RwLocks 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 RwLocks 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 RwLocks 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 RwLocks 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 RwLocks 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 RwLocks 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    #[cfg(has_const_fn_trait_bound)]
370    #[inline]
371    pub const fn new(val: T) -> RwLock<R, T> {
372        RwLock {
373            data: UnsafeCell::new(val),
374            raw: R::INIT,
375        }
376    }
377
378    /// Creates a new instance of an `RwLock<T>` which is unlocked.
379    #[cfg(not(has_const_fn_trait_bound))]
380    #[inline]
381    pub fn new(val: T) -> RwLock<R, T> {
382        RwLock {
383            data: UnsafeCell::new(val),
384            raw: R::INIT,
385        }
386    }
387
388    /// Consumes this `RwLock`, returning the underlying data.
389    #[inline]
390    #[allow(unused_unsafe)]
391    pub fn into_inner(self) -> T {
392        unsafe { self.data.into_inner() }
393    }
394}
395
396impl<R, T> RwLock<R, T> {
397    /// Creates a new new instance of an `RwLock<T>` based on a pre-existing
398    /// `RawRwLock<T>`.
399    ///
400    /// This allows creating a `RwLock<T>` in a constant context on stable
401    /// Rust.
402    #[inline]
403    pub const fn const_new(raw_rwlock: R, val: T) -> RwLock<R, T> {
404        RwLock {
405            data: UnsafeCell::new(val),
406            raw: raw_rwlock,
407        }
408    }
409}
410
411impl<R: RawRwLock, T: ?Sized> RwLock<R, T> {
412    /// Creates a new `RwLockReadGuard` without checking if the lock is held.
413    ///
414    /// # Safety
415    ///
416    /// This method must only be called if the thread logically holds a read lock.
417    ///
418    /// This function does not increment the read count of the lock. Calling this function when a
419    /// guard has already been produced is undefined behaviour unless the guard was forgotten
420    /// with `mem::forget`.`
421    #[inline]
422    pub unsafe fn make_read_guard_unchecked(&self) -> RwLockReadGuard<'_, R, T> {
423        RwLockReadGuard {
424            rwlock: self,
425            marker: PhantomData,
426        }
427    }
428
429    /// Creates a new `RwLockReadGuard` without checking if the lock is held.
430    ///
431    /// # Safety
432    ///
433    /// This method must only be called if the thread logically holds a write lock.
434    ///
435    /// Calling this function when a guard has already been produced is undefined behaviour unless
436    /// the guard was forgotten with `mem::forget`.
437    #[inline]
438    pub unsafe fn make_write_guard_unchecked(&self) -> RwLockWriteGuard<'_, R, T> {
439        RwLockWriteGuard {
440            rwlock: self,
441            marker: PhantomData,
442        }
443    }
444
445    /// Locks this `RwLock` with shared read access, blocking the current thread
446    /// until it can be acquired.
447    ///
448    /// The calling thread will be blocked until there are no more writers which
449    /// hold the lock. There may be other readers currently inside the lock when
450    /// this method returns.
451    ///
452    /// Note that attempts to recursively acquire a read lock on a `RwLock` when
453    /// the current thread already holds one may result in a deadlock.
454    ///
455    /// Returns an RAII guard which will release this thread's shared access
456    /// once it is dropped.
457    #[inline]
458    pub fn read(&self) -> RwLockReadGuard<'_, R, T> {
459        self.raw.lock_shared();
460        // SAFETY: The lock is held, as required.
461        unsafe { self.make_read_guard_unchecked() }
462    }
463
464    /// Attempts to acquire this `RwLock` with shared read access.
465    ///
466    /// If the access could not be granted at this time, then `None` is returned.
467    /// Otherwise, an RAII guard is returned which will release the shared access
468    /// when it is dropped.
469    ///
470    /// This function does not block.
471    #[inline]
472    pub fn try_read(&self) -> Option<RwLockReadGuard<'_, R, T>> {
473        if self.raw.try_lock_shared() {
474            // SAFETY: The lock is held, as required.
475            Some(unsafe { self.make_read_guard_unchecked() })
476        } else {
477            None
478        }
479    }
480
481    /// Locks this `RwLock` with exclusive write access, blocking the current
482    /// thread until it can be acquired.
483    ///
484    /// This function will not return while other writers or other readers
485    /// currently have access to the lock.
486    ///
487    /// Returns an RAII guard which will drop the write access of this `RwLock`
488    /// when dropped.
489    #[inline]
490    pub fn write(&self) -> RwLockWriteGuard<'_, R, T> {
491        self.raw.lock_exclusive();
492        // SAFETY: The lock is held, as required.
493        unsafe { self.make_write_guard_unchecked() }
494    }
495
496    /// Attempts to lock this `RwLock` with exclusive write access.
497    ///
498    /// If the lock could not be acquired at this time, then `None` is returned.
499    /// Otherwise, an RAII guard is returned which will release the lock when
500    /// it is dropped.
501    ///
502    /// This function does not block.
503    #[inline]
504    pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, R, T>> {
505        if self.raw.try_lock_exclusive() {
506            // SAFETY: The lock is held, as required.
507            Some(unsafe { self.make_write_guard_unchecked() })
508        } else {
509            None
510        }
511    }
512
513    /// Returns a mutable reference to the underlying data.
514    ///
515    /// Since this call borrows the `RwLock` mutably, no actual locking needs to
516    /// take place---the mutable borrow statically guarantees no locks exist.
517    #[inline]
518    pub fn get_mut(&mut self) -> &mut T {
519        unsafe { &mut *self.data.get() }
520    }
521
522    /// Checks whether this `RwLock` is currently locked in any way.
523    #[inline]
524    pub fn is_locked(&self) -> bool {
525        self.raw.is_locked()
526    }
527
528    /// Check if this `RwLock` is currently exclusively locked.
529    #[inline]
530    pub fn is_locked_exclusive(&self) -> bool {
531        self.raw.is_locked_exclusive()
532    }
533
534    /// Forcibly unlocks a read lock.
535    ///
536    /// This is useful when combined with `mem::forget` to hold a lock without
537    /// the need to maintain a `RwLockReadGuard` object alive, for example when
538    /// dealing with FFI.
539    ///
540    /// # Safety
541    ///
542    /// This method must only be called if the current thread logically owns a
543    /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`.
544    /// Behavior is undefined if a rwlock is read-unlocked when not read-locked.
545    #[inline]
546    pub unsafe fn force_unlock_read(&self) {
547        self.raw.unlock_shared();
548    }
549
550    /// Forcibly unlocks a write lock.
551    ///
552    /// This is useful when combined with `mem::forget` to hold a lock without
553    /// the need to maintain a `RwLockWriteGuard` object alive, for example when
554    /// dealing with FFI.
555    ///
556    /// # Safety
557    ///
558    /// This method must only be called if the current thread logically owns a
559    /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`.
560    /// Behavior is undefined if a rwlock is write-unlocked when not write-locked.
561    #[inline]
562    pub unsafe fn force_unlock_write(&self) {
563        self.raw.unlock_exclusive();
564    }
565
566    /// Returns the underlying raw reader-writer lock object.
567    ///
568    /// Note that you will most likely need to import the `RawRwLock` trait from
569    /// `lock_api` to be able to call functions on the raw
570    /// reader-writer lock.
571    ///
572    /// # Safety
573    ///
574    /// This method is unsafe because it allows unlocking a mutex while
575    /// still holding a reference to a lock guard.
576    pub unsafe fn raw(&self) -> &R {
577        &self.raw
578    }
579
580    /// Returns a raw pointer to the underlying data.
581    ///
582    /// This is useful when combined with `mem::forget` to hold a lock without
583    /// the need to maintain a `RwLockReadGuard` or `RwLockWriteGuard` object
584    /// alive, for example when dealing with FFI.
585    ///
586    /// # Safety
587    ///
588    /// You must ensure that there are no data races when dereferencing the
589    /// returned pointer, for example if the current thread logically owns a
590    /// `RwLockReadGuard` or `RwLockWriteGuard` but that guard has been discarded
591    /// using `mem::forget`.
592    #[inline]
593    pub fn data_ptr(&self) -> *mut T {
594        self.data.get()
595    }
596
597    /// Creates a new `RwLockReadGuard` without checking if the lock is held.
598    ///
599    /// # Safety
600    ///
601    /// This method must only be called if the thread logically holds a read lock.
602    ///
603    /// This function does not increment the read count of the lock. Calling this function when a
604    /// guard has already been produced is undefined behaviour unless the guard was forgotten
605    /// with `mem::forget`.`
606    #[cfg(feature = "arc_lock")]
607    #[inline]
608    pub unsafe fn make_arc_read_guard_unchecked(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
609        ArcRwLockReadGuard {
610            rwlock: self.clone(),
611            marker: PhantomData,
612        }
613    }
614
615    /// Creates a new `RwLockWriteGuard` without checking if the lock is held.
616    ///
617    /// # Safety
618    ///
619    /// This method must only be called if the thread logically holds a write lock.
620    ///
621    /// Calling this function when a guard has already been produced is undefined behaviour unless
622    /// the guard was forgotten with `mem::forget`.
623    #[cfg(feature = "arc_lock")]
624    #[inline]
625    pub unsafe fn make_arc_write_guard_unchecked(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> {
626        ArcRwLockWriteGuard {
627            rwlock: self.clone(),
628            marker: PhantomData,
629        }
630    }
631
632    /// Locks this `RwLock` with read access, through an `Arc`.
633    ///
634    /// This method is similar to the `read` method; however, it requires the `RwLock` to be inside of an `Arc`
635    /// and the resulting read guard has no lifetime requirements.
636    #[cfg(feature = "arc_lock")]
637    #[inline]
638    pub fn read_arc(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
639        self.raw.lock_shared();
640        // SAFETY: locking guarantee is upheld
641        unsafe { self.make_arc_read_guard_unchecked() }
642    }
643
644    /// Attempts to lock this `RwLock` with read access, through an `Arc`.
645    ///
646    /// This method is similar to the `try_read` method; however, it requires the `RwLock` to be inside of an
647    /// `Arc` and the resulting read guard has no lifetime requirements.
648    #[cfg(feature = "arc_lock")]
649    #[inline]
650    pub fn try_read_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> {
651        if self.raw.try_lock_shared() {
652            // SAFETY: locking guarantee is upheld
653            Some(unsafe { self.make_arc_read_guard_unchecked() })
654        } else {
655            None
656        }
657    }
658
659    /// Locks this `RwLock` with write access, through an `Arc`.
660    ///
661    /// This method is similar to the `write` method; however, it requires the `RwLock` to be inside of an `Arc`
662    /// and the resulting write guard has no lifetime requirements.
663    #[cfg(feature = "arc_lock")]
664    #[inline]
665    pub fn write_arc(self: &Arc<Self>) -> ArcRwLockWriteGuard<R, T> {
666        self.raw.lock_exclusive();
667        // SAFETY: locking guarantee is upheld
668        unsafe { self.make_arc_write_guard_unchecked() }
669    }
670
671    /// Attempts to lock this `RwLock` with writ access, through an `Arc`.
672    ///
673    /// This method is similar to the `try_write` method; however, it requires the `RwLock` to be inside of an
674    /// `Arc` and the resulting write guard has no lifetime requirements.
675    #[cfg(feature = "arc_lock")]
676    #[inline]
677    pub fn try_write_arc(self: &Arc<Self>) -> Option<ArcRwLockWriteGuard<R, T>> {
678        if self.raw.try_lock_exclusive() {
679            // SAFETY: locking guarantee is upheld
680            Some(unsafe { self.make_arc_write_guard_unchecked() })
681        } else {
682            None
683        }
684    }
685}
686
687impl<R: RawRwLockFair, T: ?Sized> RwLock<R, T> {
688    /// Forcibly unlocks a read lock using a fair unlock procotol.
689    ///
690    /// This is useful when combined with `mem::forget` to hold a lock without
691    /// the need to maintain a `RwLockReadGuard` object alive, for example when
692    /// dealing with FFI.
693    ///
694    /// # Safety
695    ///
696    /// This method must only be called if the current thread logically owns a
697    /// `RwLockReadGuard` but that guard has be discarded using `mem::forget`.
698    /// Behavior is undefined if a rwlock is read-unlocked when not read-locked.
699    #[inline]
700    pub unsafe fn force_unlock_read_fair(&self) {
701        self.raw.unlock_shared_fair();
702    }
703
704    /// Forcibly unlocks a write lock using a fair unlock procotol.
705    ///
706    /// This is useful when combined with `mem::forget` to hold a lock without
707    /// the need to maintain a `RwLockWriteGuard` 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    /// `RwLockWriteGuard` but that guard has be discarded using `mem::forget`.
714    /// Behavior is undefined if a rwlock is write-unlocked when not write-locked.
715    #[inline]
716    pub unsafe fn force_unlock_write_fair(&self) {
717        self.raw.unlock_exclusive_fair();
718    }
719}
720
721impl<R: RawRwLockTimed, T: ?Sized> RwLock<R, T> {
722    /// Attempts to acquire this `RwLock` with shared read access until a timeout
723    /// is reached.
724    ///
725    /// If the access could not be granted before the timeout expires, then
726    /// `None` is returned. Otherwise, an RAII guard is returned which will
727    /// release the shared access when it is dropped.
728    #[inline]
729    pub fn try_read_for(&self, timeout: R::Duration) -> Option<RwLockReadGuard<'_, R, T>> {
730        if self.raw.try_lock_shared_for(timeout) {
731            // SAFETY: The lock is held, as required.
732            Some(unsafe { self.make_read_guard_unchecked() })
733        } else {
734            None
735        }
736    }
737
738    /// Attempts to acquire this `RwLock` with shared read access until a timeout
739    /// is reached.
740    ///
741    /// If the access could not be granted before the timeout expires, then
742    /// `None` is returned. Otherwise, an RAII guard is returned which will
743    /// release the shared access when it is dropped.
744    #[inline]
745    pub fn try_read_until(&self, timeout: R::Instant) -> Option<RwLockReadGuard<'_, R, T>> {
746        if self.raw.try_lock_shared_until(timeout) {
747            // SAFETY: The lock is held, as required.
748            Some(unsafe { self.make_read_guard_unchecked() })
749        } else {
750            None
751        }
752    }
753
754    /// Attempts to acquire this `RwLock` with exclusive write access until a
755    /// timeout is reached.
756    ///
757    /// If the access could not be granted before the timeout expires, then
758    /// `None` is returned. Otherwise, an RAII guard is returned which will
759    /// release the exclusive access when it is dropped.
760    #[inline]
761    pub fn try_write_for(&self, timeout: R::Duration) -> Option<RwLockWriteGuard<'_, R, T>> {
762        if self.raw.try_lock_exclusive_for(timeout) {
763            // SAFETY: The lock is held, as required.
764            Some(unsafe { self.make_write_guard_unchecked() })
765        } else {
766            None
767        }
768    }
769
770    /// Attempts to acquire this `RwLock` with exclusive write access until a
771    /// timeout is reached.
772    ///
773    /// If the access could not be granted before the timeout expires, then
774    /// `None` is returned. Otherwise, an RAII guard is returned which will
775    /// release the exclusive access when it is dropped.
776    #[inline]
777    pub fn try_write_until(&self, timeout: R::Instant) -> Option<RwLockWriteGuard<'_, R, T>> {
778        if self.raw.try_lock_exclusive_until(timeout) {
779            // SAFETY: The lock is held, as required.
780            Some(unsafe { self.make_write_guard_unchecked() })
781        } else {
782            None
783        }
784    }
785
786    /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
787    ///
788    /// This method is similar to the `try_read_for` method; however, it requires the `RwLock` to be inside of an
789    /// `Arc` and the resulting read guard has no lifetime requirements.
790    #[cfg(feature = "arc_lock")]
791    #[inline]
792    pub fn try_read_arc_for(
793        self: &Arc<Self>,
794        timeout: R::Duration,
795    ) -> Option<ArcRwLockReadGuard<R, T>> {
796        if self.raw.try_lock_shared_for(timeout) {
797            // SAFETY: locking guarantee is upheld
798            Some(unsafe { self.make_arc_read_guard_unchecked() })
799        } else {
800            None
801        }
802    }
803
804    /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
805    ///
806    /// This method is similar to the `try_read_until` method; however, it requires the `RwLock` to be inside of
807    /// an `Arc` and the resulting read guard has no lifetime requirements.
808    #[cfg(feature = "arc_lock")]
809    #[inline]
810    pub fn try_read_arc_until(
811        self: &Arc<Self>,
812        timeout: R::Instant,
813    ) -> Option<ArcRwLockReadGuard<R, T>> {
814        if self.raw.try_lock_shared_until(timeout) {
815            // SAFETY: locking guarantee is upheld
816            Some(unsafe { self.make_arc_read_guard_unchecked() })
817        } else {
818            None
819        }
820    }
821
822    /// Attempts to acquire this `RwLock` with write access until a timeout is reached, through an `Arc`.
823    ///
824    /// This method is similar to the `try_write_for` method; however, it requires the `RwLock` to be inside of
825    /// an `Arc` and the resulting write guard has no lifetime requirements.
826    #[cfg(feature = "arc_lock")]
827    #[inline]
828    pub fn try_write_arc_for(
829        self: &Arc<Self>,
830        timeout: R::Duration,
831    ) -> Option<ArcRwLockWriteGuard<R, T>> {
832        if self.raw.try_lock_exclusive_for(timeout) {
833            // SAFETY: locking guarantee is upheld
834            Some(unsafe { self.make_arc_write_guard_unchecked() })
835        } else {
836            None
837        }
838    }
839
840    /// Attempts to acquire this `RwLock` with read access until a timeout is reached, through an `Arc`.
841    ///
842    /// This method is similar to the `try_write_until` method; however, it requires the `RwLock` to be inside of
843    /// an `Arc` and the resulting read guard has no lifetime requirements.
844    #[cfg(feature = "arc_lock")]
845    #[inline]
846    pub fn try_write_arc_until(
847        self: &Arc<Self>,
848        timeout: R::Instant,
849    ) -> Option<ArcRwLockWriteGuard<R, T>> {
850        if self.raw.try_lock_exclusive_until(timeout) {
851            // SAFETY: locking guarantee is upheld
852            Some(unsafe { self.make_arc_write_guard_unchecked() })
853        } else {
854            None
855        }
856    }
857}
858
859impl<R: RawRwLockRecursive, T: ?Sized> RwLock<R, T> {
860    /// Locks this `RwLock` with shared read access, blocking the current thread
861    /// until it can be acquired.
862    ///
863    /// The calling thread will be blocked until there are no more writers which
864    /// hold the lock. There may be other readers currently inside the lock when
865    /// this method returns.
866    ///
867    /// Unlike `read`, this method is guaranteed to succeed without blocking if
868    /// another read lock is held at the time of the call. This allows a thread
869    /// to recursively lock a `RwLock`. However using this method can cause
870    /// writers to starve since readers no longer block if a writer is waiting
871    /// for the lock.
872    ///
873    /// Returns an RAII guard which will release this thread's shared access
874    /// once it is dropped.
875    #[inline]
876    pub fn read_recursive(&self) -> RwLockReadGuard<'_, R, T> {
877        self.raw.lock_shared_recursive();
878        // SAFETY: The lock is held, as required.
879        unsafe { self.make_read_guard_unchecked() }
880    }
881
882    /// Attempts to acquire this `RwLock` with shared read access.
883    ///
884    /// If the access could not be granted at this time, then `None` is returned.
885    /// Otherwise, an RAII guard is returned which will release the shared access
886    /// when it is dropped.
887    ///
888    /// This method is guaranteed to succeed if another read lock is held at the
889    /// time of the call. See the documentation for `read_recursive` for details.
890    ///
891    /// This function does not block.
892    #[inline]
893    pub fn try_read_recursive(&self) -> Option<RwLockReadGuard<'_, R, T>> {
894        if self.raw.try_lock_shared_recursive() {
895            // SAFETY: The lock is held, as required.
896            Some(unsafe { self.make_read_guard_unchecked() })
897        } else {
898            None
899        }
900    }
901
902    /// Locks this `RwLock` with shared read access, through an `Arc`.
903    ///
904    /// This method is similar to the `read_recursive` method; however, it requires the `RwLock` to be inside of
905    /// an `Arc` and the resulting read guard has no lifetime requirements.
906    #[cfg(feature = "arc_lock")]
907    #[inline]
908    pub fn read_arc_recursive(self: &Arc<Self>) -> ArcRwLockReadGuard<R, T> {
909        self.raw.lock_shared_recursive();
910        // SAFETY: locking guarantee is upheld
911        unsafe { self.make_arc_read_guard_unchecked() }
912    }
913
914    /// Attempts to lock this `RwLock` with shared read access, through an `Arc`.
915    ///
916    /// This method is similar to the `try_read_recursive` method; however, it requires the `RwLock` to be inside
917    /// of an `Arc` and the resulting read guard has no lifetime requirements.
918    #[cfg(feature = "arc_lock")]
919    #[inline]
920    pub fn try_read_recursive_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<R, T>> {
921        if self.raw.try_lock_shared_recursive() {
922            // SAFETY: locking guarantee is upheld
923            Some(unsafe { self.make_arc_read_guard_unchecked() })
924        } else {
925            None
926        }
927    }
928}
929
930impl<R: RawRwLockRecursiveTimed, T: ?Sized> RwLock<R, T> {
931    /// Attempts to acquire this `RwLock` with shared read access until a timeout
932    /// is reached.
933    ///
934    /// If the access could not be granted before the timeout expires, then
935    /// `None` is returned. Otherwise, an RAII guard is returned which will
936    /// release the shared access when it is dropped.
937    ///
938    /// This method is guaranteed to succeed without blocking if another read
939    /// lock is held at the time of the call. See the documentation for
940    /// `read_recursive` for details.
941    #[inline]
942    pub fn try_read_recursive_for(
943        &self,
944        timeout: R::Duration,
945    ) -> Option<RwLockReadGuard<'_, R, T>> {
946        if self.raw.try_lock_shared_recursive_for(timeout) {
947            // SAFETY: The lock is held, as required.
948            Some(unsafe { self.make_read_guard_unchecked() })
949        } else {
950            None
951        }
952    }
953
954    /// Attempts to acquire this `RwLock` with shared read access until a timeout
955    /// is reached.
956    ///
957    /// If the access could not be granted before the timeout expires, then
958    /// `None` is returned. Otherwise, an RAII guard is returned which will
959    /// release the shared access when it is dropped.
960    #[inline]
961    pub fn try_read_recursive_until(
962        &self,
963        timeout: R::Instant,
964    ) -> Option<RwLockReadGuard<'_, R, T>> {
965        if self.raw.try_lock_shared_recursive_until(timeout) {
966            // SAFETY: The lock is held, as required.
967            Some(unsafe { self.make_read_guard_unchecked() })
968        } else {
969            None
970        }
971    }
972
973    /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`.
974    ///
975    /// This method is similar to the `try_read_recursive_for` method; however, it requires the `RwLock` to be
976    /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
977    #[cfg(feature = "arc_lock")]
978    #[inline]
979    pub fn try_read_arc_recursive_for(
980        self: &Arc<Self>,
981        timeout: R::Duration,
982    ) -> Option<ArcRwLockReadGuard<R, T>> {
983        if self.raw.try_lock_shared_recursive_for(timeout) {
984            // SAFETY: locking guarantee is upheld
985            Some(unsafe { self.make_arc_read_guard_unchecked() })
986        } else {
987            None
988        }
989    }
990
991    /// Attempts to lock this `RwLock` with read access until a timeout is reached, through an `Arc`.
992    ///
993    /// This method is similar to the `try_read_recursive_until` method; however, it requires the `RwLock` to be
994    /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
995    #[cfg(feature = "arc_lock")]
996    #[inline]
997    pub fn try_read_arc_recursive_until(
998        self: &Arc<Self>,
999        timeout: R::Instant,
1000    ) -> Option<ArcRwLockReadGuard<R, T>> {
1001        if self.raw.try_lock_shared_recursive_until(timeout) {
1002            // SAFETY: locking guarantee is upheld
1003            Some(unsafe { self.make_arc_read_guard_unchecked() })
1004        } else {
1005            None
1006        }
1007    }
1008}
1009
1010impl<R: RawRwLockUpgrade, T: ?Sized> RwLock<R, T> {
1011    /// Creates a new `RwLockUpgradableReadGuard` without checking if the lock is held.
1012    ///
1013    /// # Safety
1014    ///
1015    /// This method must only be called if the thread logically holds an upgradable read lock.
1016    ///
1017    /// This function does not increment the read count of the lock. Calling this function when a
1018    /// guard has already been produced is undefined behaviour unless the guard was forgotten
1019    /// with `mem::forget`.`
1020    #[inline]
1021    pub unsafe fn make_upgradable_guard_unchecked(&self) -> RwLockUpgradableReadGuard<'_, R, T> {
1022        RwLockUpgradableReadGuard {
1023            rwlock: self,
1024            marker: PhantomData,
1025        }
1026    }
1027
1028    /// Locks this `RwLock` with upgradable read access, blocking the current thread
1029    /// until it can be acquired.
1030    ///
1031    /// The calling thread will be blocked until there are no more writers or other
1032    /// upgradable reads which hold the lock. There may be other readers currently
1033    /// inside the lock when this method returns.
1034    ///
1035    /// Returns an RAII guard which will release this thread's shared access
1036    /// once it is dropped.
1037    #[inline]
1038    pub fn upgradable_read(&self) -> RwLockUpgradableReadGuard<'_, R, T> {
1039        self.raw.lock_upgradable();
1040        // SAFETY: The lock is held, as required.
1041        unsafe { self.make_upgradable_guard_unchecked() }
1042    }
1043
1044    /// Attempts to acquire this `RwLock` with upgradable read access.
1045    ///
1046    /// If the access could not be granted at this time, then `None` is returned.
1047    /// Otherwise, an RAII guard is returned which will release the shared access
1048    /// when it is dropped.
1049    ///
1050    /// This function does not block.
1051    #[inline]
1052    pub fn try_upgradable_read(&self) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
1053        if self.raw.try_lock_upgradable() {
1054            // SAFETY: The lock is held, as required.
1055            Some(unsafe { self.make_upgradable_guard_unchecked() })
1056        } else {
1057            None
1058        }
1059    }
1060
1061    /// Creates a new `ArcRwLockUpgradableReadGuard` without checking if the lock is held.
1062    ///
1063    /// # Safety
1064    ///
1065    /// This method must only be called if the thread logically holds an upgradable read lock.
1066    ///
1067    /// This function does not increment the read count of the lock. Calling this function when a
1068    /// guard has already been produced is undefined behaviour unless the guard was forgotten
1069    /// with `mem::forget`.`
1070    #[cfg(feature = "arc_lock")]
1071    #[inline]
1072    pub unsafe fn make_upgradable_arc_guard_unchecked(
1073        self: &Arc<Self>,
1074    ) -> ArcRwLockUpgradableReadGuard<R, T> {
1075        ArcRwLockUpgradableReadGuard {
1076            rwlock: self.clone(),
1077            marker: PhantomData,
1078        }
1079    }
1080
1081    /// Locks this `RwLock` with upgradable read access, through an `Arc`.
1082    ///
1083    /// This method is similar to the `upgradable_read` method; however, it requires the `RwLock` to be
1084    /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1085    #[cfg(feature = "arc_lock")]
1086    #[inline]
1087    pub fn upgradable_read_arc(self: &Arc<Self>) -> ArcRwLockUpgradableReadGuard<R, T> {
1088        self.raw.lock_upgradable();
1089        // SAFETY: locking guarantee is upheld
1090        unsafe { self.make_upgradable_arc_guard_unchecked() }
1091    }
1092
1093    /// Attempts to lock this `RwLock` with upgradable read access, through an `Arc`.
1094    ///
1095    /// This method is similar to the `try_upgradable_read` method; however, it requires the `RwLock` to be
1096    /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1097    #[cfg(feature = "arc_lock")]
1098    #[inline]
1099    pub fn try_upgradable_read_arc(self: &Arc<Self>) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
1100        if self.raw.try_lock_upgradable() {
1101            // SAFETY: locking guarantee is upheld
1102            Some(unsafe { self.make_upgradable_arc_guard_unchecked() })
1103        } else {
1104            None
1105        }
1106    }
1107}
1108
1109impl<R: RawRwLockUpgradeTimed, T: ?Sized> RwLock<R, T> {
1110    /// Attempts to acquire this `RwLock` with upgradable read access until a timeout
1111    /// is reached.
1112    ///
1113    /// If the access could not be granted before the timeout expires, then
1114    /// `None` is returned. Otherwise, an RAII guard is returned which will
1115    /// release the shared access when it is dropped.
1116    #[inline]
1117    pub fn try_upgradable_read_for(
1118        &self,
1119        timeout: R::Duration,
1120    ) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
1121        if self.raw.try_lock_upgradable_for(timeout) {
1122            // SAFETY: The lock is held, as required.
1123            Some(unsafe { self.make_upgradable_guard_unchecked() })
1124        } else {
1125            None
1126        }
1127    }
1128
1129    /// Attempts to acquire this `RwLock` with upgradable read access until a timeout
1130    /// is reached.
1131    ///
1132    /// If the access could not be granted before the timeout expires, then
1133    /// `None` is returned. Otherwise, an RAII guard is returned which will
1134    /// release the shared access when it is dropped.
1135    #[inline]
1136    pub fn try_upgradable_read_until(
1137        &self,
1138        timeout: R::Instant,
1139    ) -> Option<RwLockUpgradableReadGuard<'_, R, T>> {
1140        if self.raw.try_lock_upgradable_until(timeout) {
1141            // SAFETY: The lock is held, as required.
1142            Some(unsafe { self.make_upgradable_guard_unchecked() })
1143        } else {
1144            None
1145        }
1146    }
1147
1148    /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`.
1149    ///
1150    /// This method is similar to the `try_upgradable_read_for` method; however, it requires the `RwLock` to be
1151    /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1152    #[cfg(feature = "arc_lock")]
1153    #[inline]
1154    pub fn try_upgradable_read_arc_for(
1155        self: &Arc<Self>,
1156        timeout: R::Duration,
1157    ) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
1158        if self.raw.try_lock_upgradable_for(timeout) {
1159            // SAFETY: locking guarantee is upheld
1160            Some(unsafe { self.make_upgradable_arc_guard_unchecked() })
1161        } else {
1162            None
1163        }
1164    }
1165
1166    /// Attempts to lock this `RwLock` with upgradable access until a timeout is reached, through an `Arc`.
1167    ///
1168    /// This method is similar to the `try_upgradable_read_until` method; however, it requires the `RwLock` to be
1169    /// inside of an `Arc` and the resulting read guard has no lifetime requirements.
1170    #[cfg(feature = "arc_lock")]
1171    #[inline]
1172    pub fn try_upgradable_read_arc_until(
1173        self: &Arc<Self>,
1174        timeout: R::Instant,
1175    ) -> Option<ArcRwLockUpgradableReadGuard<R, T>> {
1176        if self.raw.try_lock_upgradable_until(timeout) {
1177            // SAFETY: locking guarantee is upheld
1178            Some(unsafe { self.make_upgradable_arc_guard_unchecked() })
1179        } else {
1180            None
1181        }
1182    }
1183}
1184
1185impl<R: RawRwLock, T: ?Sized + Default> Default for RwLock<R, T> {
1186    #[inline]
1187    fn default() -> RwLock<R, T> {
1188        RwLock::new(Default::default())
1189    }
1190}
1191
1192impl<R: RawRwLock, T> From<T> for RwLock<R, T> {
1193    #[inline]
1194    fn from(t: T) -> RwLock<R, T> {
1195        RwLock::new(t)
1196    }
1197}
1198
1199impl<R: RawRwLock, T: ?Sized + fmt::Debug> fmt::Debug for RwLock<R, T> {
1200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1201        match self.try_read() {
1202            Some(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(),
1203            None => {
1204                struct LockedPlaceholder;
1205                impl fmt::Debug for LockedPlaceholder {
1206                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1207                        f.write_str("<locked>")
1208                    }
1209                }
1210
1211                f.debug_struct("RwLock")
1212                    .field("data", &LockedPlaceholder)
1213                    .finish()
1214            }
1215        }
1216    }
1217}
1218
1219/// RAII structure used to release the shared read access of a lock when
1220/// dropped.
1221#[clippy::has_significant_drop]
1222#[must_use = "if unused the RwLock will immediately unlock"]
1223pub struct RwLockReadGuard<'a, R: RawRwLock, T: ?Sized> {
1224    rwlock: &'a RwLock<R, T>,
1225    marker: PhantomData<(&'a T, R::GuardMarker)>,
1226}
1227
1228unsafe impl<R: RawRwLock + Sync, T: Sync + ?Sized> Sync for RwLockReadGuard<'_, R, T> {}
1229
1230impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
1231    /// Returns a reference to the original reader-writer lock object.
1232    pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
1233        s.rwlock
1234    }
1235
1236    /// Make a new `MappedRwLockReadGuard` for a component of the locked data.
1237    ///
1238    /// This operation cannot fail as the `RwLockReadGuard` passed
1239    /// in already locked the data.
1240    ///
1241    /// This is an associated function that needs to be
1242    /// used as `RwLockReadGuard::map(...)`. A method would interfere with methods of
1243    /// the same name on the contents of the locked data.
1244    #[inline]
1245    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U>
1246    where
1247        F: FnOnce(&T) -> &U,
1248    {
1249        let raw = &s.rwlock.raw;
1250        let data = f(unsafe { &*s.rwlock.data.get() });
1251        mem::forget(s);
1252        MappedRwLockReadGuard {
1253            raw,
1254            data,
1255            marker: PhantomData,
1256        }
1257    }
1258
1259    /// Attempts to make  a new `MappedRwLockReadGuard` for a component of the
1260    /// locked data. Returns the original guard if the closure returns `None`.
1261    ///
1262    /// This operation cannot fail as the `RwLockReadGuard` passed
1263    /// in already locked the data.
1264    ///
1265    /// This is an associated function that needs to be
1266    /// used as `RwLockReadGuard::try_map(...)`. A method would interfere with methods of
1267    /// the same name on the contents of the locked data.
1268    #[inline]
1269    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
1270    where
1271        F: FnOnce(&T) -> Option<&U>,
1272    {
1273        let raw = &s.rwlock.raw;
1274        let data = match f(unsafe { &*s.rwlock.data.get() }) {
1275            Some(data) => data,
1276            None => return Err(s),
1277        };
1278        mem::forget(s);
1279        Ok(MappedRwLockReadGuard {
1280            raw,
1281            data,
1282            marker: PhantomData,
1283        })
1284    }
1285
1286    /// Temporarily unlocks the `RwLock` to execute the given function.
1287    ///
1288    /// This is safe because `&mut` guarantees that there exist no other
1289    /// references to the data protected by the `RwLock`.
1290    #[inline]
1291    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1292    where
1293        F: FnOnce() -> U,
1294    {
1295        // Safety: An RwLockReadGuard always holds a shared lock.
1296        unsafe {
1297            s.rwlock.raw.unlock_shared();
1298        }
1299        defer!(s.rwlock.raw.lock_shared());
1300        f()
1301    }
1302}
1303
1304impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
1305    /// Unlocks the `RwLock` using a fair unlock protocol.
1306    ///
1307    /// By default, `RwLock` is unfair and allow the current thread to re-lock
1308    /// the `RwLock` before another has the chance to acquire the lock, even if
1309    /// that thread has been blocked on the `RwLock` for a long time. This is
1310    /// the default because it allows much higher throughput as it avoids
1311    /// forcing a context switch on every `RwLock` unlock. This can result in one
1312    /// thread acquiring a `RwLock` many more times than other threads.
1313    ///
1314    /// However in some cases it can be beneficial to ensure fairness by forcing
1315    /// the lock to pass on to a waiting thread if there is one. This is done by
1316    /// using this method instead of dropping the `RwLockReadGuard` normally.
1317    #[inline]
1318    pub fn unlock_fair(s: Self) {
1319        // Safety: An RwLockReadGuard always holds a shared lock.
1320        unsafe {
1321            s.rwlock.raw.unlock_shared_fair();
1322        }
1323        mem::forget(s);
1324    }
1325
1326    /// Temporarily unlocks the `RwLock` to execute the given function.
1327    ///
1328    /// The `RwLock` is unlocked a fair unlock protocol.
1329    ///
1330    /// This is safe because `&mut` guarantees that there exist no other
1331    /// references to the data protected by the `RwLock`.
1332    #[inline]
1333    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1334    where
1335        F: FnOnce() -> U,
1336    {
1337        // Safety: An RwLockReadGuard always holds a shared lock.
1338        unsafe {
1339            s.rwlock.raw.unlock_shared_fair();
1340        }
1341        defer!(s.rwlock.raw.lock_shared());
1342        f()
1343    }
1344
1345    /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1346    ///
1347    /// This method is functionally equivalent to calling `unlock_fair` followed
1348    /// by `read`, however it can be much more efficient in the case where there
1349    /// are no waiting threads.
1350    #[inline]
1351    pub fn bump(s: &mut Self) {
1352        // Safety: An RwLockReadGuard always holds a shared lock.
1353        unsafe {
1354            s.rwlock.raw.bump_shared();
1355        }
1356    }
1357}
1358
1359impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockReadGuard<'a, R, T> {
1360    type Target = T;
1361    #[inline]
1362    fn deref(&self) -> &T {
1363        unsafe { &*self.rwlock.data.get() }
1364    }
1365}
1366
1367impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockReadGuard<'a, R, T> {
1368    #[inline]
1369    fn drop(&mut self) {
1370        // Safety: An RwLockReadGuard always holds a shared lock.
1371        unsafe {
1372            self.rwlock.raw.unlock_shared();
1373        }
1374    }
1375}
1376
1377impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockReadGuard<'a, R, T> {
1378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1379        fmt::Debug::fmt(&**self, f)
1380    }
1381}
1382
1383impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
1384    for RwLockReadGuard<'a, R, T>
1385{
1386    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1387        (**self).fmt(f)
1388    }
1389}
1390
1391#[cfg(feature = "owning_ref")]
1392unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockReadGuard<'a, R, T> {}
1393
1394/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
1395///
1396/// This is similar to the `RwLockReadGuard` struct, except instead of using a reference to unlock the `RwLock`
1397/// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime.
1398#[cfg(feature = "arc_lock")]
1399#[clippy::has_significant_drop]
1400#[must_use = "if unused the RwLock will immediately unlock"]
1401pub struct ArcRwLockReadGuard<R: RawRwLock, T: ?Sized> {
1402    rwlock: Arc<RwLock<R, T>>,
1403    marker: PhantomData<R::GuardMarker>,
1404}
1405
1406#[cfg(feature = "arc_lock")]
1407impl<R: RawRwLock, T: ?Sized> ArcRwLockReadGuard<R, T> {
1408    /// Returns a reference to the rwlock, contained in its `Arc`.
1409    pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
1410        &s.rwlock
1411    }
1412
1413    /// Temporarily unlocks the `RwLock` to execute the given function.
1414    ///
1415    /// This is functionally identical to the `unlocked` method on [`RwLockReadGuard`].
1416    #[inline]
1417    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1418    where
1419        F: FnOnce() -> U,
1420    {
1421        // Safety: An RwLockReadGuard always holds a shared lock.
1422        unsafe {
1423            s.rwlock.raw.unlock_shared();
1424        }
1425        defer!(s.rwlock.raw.lock_shared());
1426        f()
1427    }
1428}
1429
1430#[cfg(feature = "arc_lock")]
1431impl<R: RawRwLockFair, T: ?Sized> ArcRwLockReadGuard<R, T> {
1432    /// Unlocks the `RwLock` using a fair unlock protocol.
1433    ///
1434    /// This is functionally identical to the `unlock_fair` method on [`RwLockReadGuard`].
1435    #[inline]
1436    pub fn unlock_fair(s: Self) {
1437        // Safety: An RwLockReadGuard always holds a shared lock.
1438        unsafe {
1439            s.rwlock.raw.unlock_shared_fair();
1440        }
1441
1442        // SAFETY: ensure the Arc has its refcount decremented
1443        let mut s = ManuallyDrop::new(s);
1444        unsafe { ptr::drop_in_place(&mut s.rwlock) };
1445    }
1446
1447    /// Temporarily unlocks the `RwLock` to execute the given function.
1448    ///
1449    /// This is functionally identical to the `unlocked_fair` method on [`RwLockReadGuard`].
1450    #[inline]
1451    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1452    where
1453        F: FnOnce() -> U,
1454    {
1455        // Safety: An RwLockReadGuard always holds a shared lock.
1456        unsafe {
1457            s.rwlock.raw.unlock_shared_fair();
1458        }
1459        defer!(s.rwlock.raw.lock_shared());
1460        f()
1461    }
1462
1463    /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1464    ///
1465    /// This is functionally identical to the `bump` method on [`RwLockReadGuard`].
1466    #[inline]
1467    pub fn bump(s: &mut Self) {
1468        // Safety: An RwLockReadGuard always holds a shared lock.
1469        unsafe {
1470            s.rwlock.raw.bump_shared();
1471        }
1472    }
1473}
1474
1475#[cfg(feature = "arc_lock")]
1476impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockReadGuard<R, T> {
1477    type Target = T;
1478    #[inline]
1479    fn deref(&self) -> &T {
1480        unsafe { &*self.rwlock.data.get() }
1481    }
1482}
1483
1484#[cfg(feature = "arc_lock")]
1485impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockReadGuard<R, T> {
1486    #[inline]
1487    fn drop(&mut self) {
1488        // Safety: An RwLockReadGuard always holds a shared lock.
1489        unsafe {
1490            self.rwlock.raw.unlock_shared();
1491        }
1492    }
1493}
1494
1495#[cfg(feature = "arc_lock")]
1496impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockReadGuard<R, T> {
1497    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1498        fmt::Debug::fmt(&**self, f)
1499    }
1500}
1501
1502#[cfg(feature = "arc_lock")]
1503impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockReadGuard<R, T> {
1504    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1505        (**self).fmt(f)
1506    }
1507}
1508
1509/// RAII structure used to release the exclusive write access of a lock when
1510/// dropped.
1511#[clippy::has_significant_drop]
1512#[must_use = "if unused the RwLock will immediately unlock"]
1513pub struct RwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> {
1514    rwlock: &'a RwLock<R, T>,
1515    marker: PhantomData<(&'a mut T, R::GuardMarker)>,
1516}
1517
1518unsafe impl<R: RawRwLock + Sync, T: Sync + ?Sized> Sync for RwLockWriteGuard<'_, R, T> {}
1519
1520impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1521    /// Returns a reference to the original reader-writer lock object.
1522    pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
1523        s.rwlock
1524    }
1525
1526    /// Make a new `MappedRwLockWriteGuard` for a component of the locked data.
1527    ///
1528    /// This operation cannot fail as the `RwLockWriteGuard` passed
1529    /// in already locked the data.
1530    ///
1531    /// This is an associated function that needs to be
1532    /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of
1533    /// the same name on the contents of the locked data.
1534    #[inline]
1535    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U>
1536    where
1537        F: FnOnce(&mut T) -> &mut U,
1538    {
1539        let raw = &s.rwlock.raw;
1540        let data = f(unsafe { &mut *s.rwlock.data.get() });
1541        mem::forget(s);
1542        MappedRwLockWriteGuard {
1543            raw,
1544            data,
1545            marker: PhantomData,
1546        }
1547    }
1548
1549    /// Attempts to make  a new `MappedRwLockWriteGuard` for a component of the
1550    /// locked data. The original guard is return if the closure returns `None`.
1551    ///
1552    /// This operation cannot fail as the `RwLockWriteGuard` passed
1553    /// in already locked the data.
1554    ///
1555    /// This is an associated function that needs to be
1556    /// used as `RwLockWriteGuard::try_map(...)`. A method would interfere with methods of
1557    /// the same name on the contents of the locked data.
1558    #[inline]
1559    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
1560    where
1561        F: FnOnce(&mut T) -> Option<&mut U>,
1562    {
1563        let raw = &s.rwlock.raw;
1564        let data = match f(unsafe { &mut *s.rwlock.data.get() }) {
1565            Some(data) => data,
1566            None => return Err(s),
1567        };
1568        mem::forget(s);
1569        Ok(MappedRwLockWriteGuard {
1570            raw,
1571            data,
1572            marker: PhantomData,
1573        })
1574    }
1575
1576    /// Temporarily unlocks the `RwLock` to execute the given function.
1577    ///
1578    /// This is safe because `&mut` guarantees that there exist no other
1579    /// references to the data protected by the `RwLock`.
1580    #[inline]
1581    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1582    where
1583        F: FnOnce() -> U,
1584    {
1585        // Safety: An RwLockReadGuard always holds a shared lock.
1586        unsafe {
1587            s.rwlock.raw.unlock_exclusive();
1588        }
1589        defer!(s.rwlock.raw.lock_exclusive());
1590        f()
1591    }
1592}
1593
1594impl<'a, R: RawRwLockDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1595    /// Atomically downgrades a write lock into a read lock without allowing any
1596    /// writers to take exclusive access of the lock in the meantime.
1597    ///
1598    /// Note that if there are any writers currently waiting to take the lock
1599    /// then other readers may not be able to acquire the lock even if it was
1600    /// downgraded.
1601    pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> {
1602        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1603        unsafe {
1604            s.rwlock.raw.downgrade();
1605        }
1606        let rwlock = s.rwlock;
1607        mem::forget(s);
1608        RwLockReadGuard {
1609            rwlock,
1610            marker: PhantomData,
1611        }
1612    }
1613}
1614
1615impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1616    /// Atomically downgrades a write lock into an upgradable read lock without allowing any
1617    /// writers to take exclusive access of the lock in the meantime.
1618    ///
1619    /// Note that if there are any writers currently waiting to take the lock
1620    /// then other readers may not be able to acquire the lock even if it was
1621    /// downgraded.
1622    pub fn downgrade_to_upgradable(s: Self) -> RwLockUpgradableReadGuard<'a, R, T> {
1623        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1624        unsafe {
1625            s.rwlock.raw.downgrade_to_upgradable();
1626        }
1627        let rwlock = s.rwlock;
1628        mem::forget(s);
1629        RwLockUpgradableReadGuard {
1630            rwlock,
1631            marker: PhantomData,
1632        }
1633    }
1634}
1635
1636impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
1637    /// Unlocks the `RwLock` using a fair unlock protocol.
1638    ///
1639    /// By default, `RwLock` is unfair and allow the current thread to re-lock
1640    /// the `RwLock` before another has the chance to acquire the lock, even if
1641    /// that thread has been blocked on the `RwLock` for a long time. This is
1642    /// the default because it allows much higher throughput as it avoids
1643    /// forcing a context switch on every `RwLock` unlock. This can result in one
1644    /// thread acquiring a `RwLock` many more times than other threads.
1645    ///
1646    /// However in some cases it can be beneficial to ensure fairness by forcing
1647    /// the lock to pass on to a waiting thread if there is one. This is done by
1648    /// using this method instead of dropping the `RwLockWriteGuard` normally.
1649    #[inline]
1650    pub fn unlock_fair(s: Self) {
1651        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1652        unsafe {
1653            s.rwlock.raw.unlock_exclusive_fair();
1654        }
1655        mem::forget(s);
1656    }
1657
1658    /// Temporarily unlocks the `RwLock` to execute the given function.
1659    ///
1660    /// The `RwLock` is unlocked a fair unlock protocol.
1661    ///
1662    /// This is safe because `&mut` guarantees that there exist no other
1663    /// references to the data protected by the `RwLock`.
1664    #[inline]
1665    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1666    where
1667        F: FnOnce() -> U,
1668    {
1669        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1670        unsafe {
1671            s.rwlock.raw.unlock_exclusive_fair();
1672        }
1673        defer!(s.rwlock.raw.lock_exclusive());
1674        f()
1675    }
1676
1677    /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1678    ///
1679    /// This method is functionally equivalent to calling `unlock_fair` followed
1680    /// by `write`, however it can be much more efficient in the case where there
1681    /// are no waiting threads.
1682    #[inline]
1683    pub fn bump(s: &mut Self) {
1684        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1685        unsafe {
1686            s.rwlock.raw.bump_exclusive();
1687        }
1688    }
1689}
1690
1691impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for RwLockWriteGuard<'a, R, T> {
1692    type Target = T;
1693    #[inline]
1694    fn deref(&self) -> &T {
1695        unsafe { &*self.rwlock.data.get() }
1696    }
1697}
1698
1699impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for RwLockWriteGuard<'a, R, T> {
1700    #[inline]
1701    fn deref_mut(&mut self) -> &mut T {
1702        unsafe { &mut *self.rwlock.data.get() }
1703    }
1704}
1705
1706impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for RwLockWriteGuard<'a, R, T> {
1707    #[inline]
1708    fn drop(&mut self) {
1709        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1710        unsafe {
1711            self.rwlock.raw.unlock_exclusive();
1712        }
1713    }
1714}
1715
1716impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for RwLockWriteGuard<'a, R, T> {
1717    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1718        fmt::Debug::fmt(&**self, f)
1719    }
1720}
1721
1722impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
1723    for RwLockWriteGuard<'a, R, T>
1724{
1725    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1726        (**self).fmt(f)
1727    }
1728}
1729
1730#[cfg(feature = "owning_ref")]
1731unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress for RwLockWriteGuard<'a, R, T> {}
1732
1733/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
1734/// This is similar to the `RwLockWriteGuard` struct, except instead of using a reference to unlock the `RwLock`
1735/// it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static` lifetime.
1736#[cfg(feature = "arc_lock")]
1737#[clippy::has_significant_drop]
1738#[must_use = "if unused the RwLock will immediately unlock"]
1739pub struct ArcRwLockWriteGuard<R: RawRwLock, T: ?Sized> {
1740    rwlock: Arc<RwLock<R, T>>,
1741    marker: PhantomData<R::GuardMarker>,
1742}
1743
1744#[cfg(feature = "arc_lock")]
1745impl<R: RawRwLock, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1746    /// Returns a reference to the rwlock, contained in its `Arc`.
1747    pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
1748        &s.rwlock
1749    }
1750
1751    /// Temporarily unlocks the `RwLock` to execute the given function.
1752    ///
1753    /// This is functionally equivalent to the `unlocked` method on [`RwLockWriteGuard`].
1754    #[inline]
1755    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1756    where
1757        F: FnOnce() -> U,
1758    {
1759        // Safety: An RwLockWriteGuard always holds a shared lock.
1760        unsafe {
1761            s.rwlock.raw.unlock_exclusive();
1762        }
1763        defer!(s.rwlock.raw.lock_exclusive());
1764        f()
1765    }
1766}
1767
1768#[cfg(feature = "arc_lock")]
1769impl<R: RawRwLockDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1770    /// Atomically downgrades a write lock into a read lock without allowing any
1771    /// writers to take exclusive access of the lock in the meantime.
1772    ///
1773    /// This is functionally equivalent to the `downgrade` method on [`RwLockWriteGuard`].
1774    pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> {
1775        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1776        unsafe {
1777            s.rwlock.raw.downgrade();
1778        }
1779
1780        // SAFETY: prevent the arc's refcount from changing using ManuallyDrop and ptr::read
1781        let s = ManuallyDrop::new(s);
1782        let rwlock = unsafe { ptr::read(&s.rwlock) };
1783
1784        ArcRwLockReadGuard {
1785            rwlock,
1786            marker: PhantomData,
1787        }
1788    }
1789}
1790
1791#[cfg(feature = "arc_lock")]
1792impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1793    /// Atomically downgrades a write lock into an upgradable read lock without allowing any
1794    /// writers to take exclusive access of the lock in the meantime.
1795    ///
1796    /// This is functionally identical to the `downgrade_to_upgradable` method on [`RwLockWriteGuard`].
1797    pub fn downgrade_to_upgradable(s: Self) -> ArcRwLockUpgradableReadGuard<R, T> {
1798        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1799        unsafe {
1800            s.rwlock.raw.downgrade_to_upgradable();
1801        }
1802
1803        // SAFETY: same as above
1804        let s = ManuallyDrop::new(s);
1805        let rwlock = unsafe { ptr::read(&s.rwlock) };
1806
1807        ArcRwLockUpgradableReadGuard {
1808            rwlock,
1809            marker: PhantomData,
1810        }
1811    }
1812}
1813
1814#[cfg(feature = "arc_lock")]
1815impl<R: RawRwLockFair, T: ?Sized> ArcRwLockWriteGuard<R, T> {
1816    /// Unlocks the `RwLock` using a fair unlock protocol.
1817    ///
1818    /// This is functionally equivalent to the `unlock_fair` method on [`RwLockWriteGuard`].
1819    #[inline]
1820    pub fn unlock_fair(s: Self) {
1821        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1822        unsafe {
1823            s.rwlock.raw.unlock_exclusive_fair();
1824        }
1825
1826        // SAFETY: prevent the Arc from leaking memory
1827        let mut s = ManuallyDrop::new(s);
1828        unsafe { ptr::drop_in_place(&mut s.rwlock) };
1829    }
1830
1831    /// Temporarily unlocks the `RwLock` to execute the given function.
1832    ///
1833    /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockWriteGuard`].
1834    #[inline]
1835    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
1836    where
1837        F: FnOnce() -> U,
1838    {
1839        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1840        unsafe {
1841            s.rwlock.raw.unlock_exclusive_fair();
1842        }
1843        defer!(s.rwlock.raw.lock_exclusive());
1844        f()
1845    }
1846
1847    /// Temporarily yields the `RwLock` to a waiting thread if there is one.
1848    ///
1849    /// This method is functionally equivalent to the `bump` method on [`RwLockWriteGuard`].
1850    #[inline]
1851    pub fn bump(s: &mut Self) {
1852        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1853        unsafe {
1854            s.rwlock.raw.bump_exclusive();
1855        }
1856    }
1857}
1858
1859#[cfg(feature = "arc_lock")]
1860impl<R: RawRwLock, T: ?Sized> Deref for ArcRwLockWriteGuard<R, T> {
1861    type Target = T;
1862    #[inline]
1863    fn deref(&self) -> &T {
1864        unsafe { &*self.rwlock.data.get() }
1865    }
1866}
1867
1868#[cfg(feature = "arc_lock")]
1869impl<R: RawRwLock, T: ?Sized> DerefMut for ArcRwLockWriteGuard<R, T> {
1870    #[inline]
1871    fn deref_mut(&mut self) -> &mut T {
1872        unsafe { &mut *self.rwlock.data.get() }
1873    }
1874}
1875
1876#[cfg(feature = "arc_lock")]
1877impl<R: RawRwLock, T: ?Sized> Drop for ArcRwLockWriteGuard<R, T> {
1878    #[inline]
1879    fn drop(&mut self) {
1880        // Safety: An RwLockWriteGuard always holds an exclusive lock.
1881        unsafe {
1882            self.rwlock.raw.unlock_exclusive();
1883        }
1884    }
1885}
1886
1887#[cfg(feature = "arc_lock")]
1888impl<R: RawRwLock, T: fmt::Debug + ?Sized> fmt::Debug for ArcRwLockWriteGuard<R, T> {
1889    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1890        fmt::Debug::fmt(&**self, f)
1891    }
1892}
1893
1894#[cfg(feature = "arc_lock")]
1895impl<R: RawRwLock, T: fmt::Display + ?Sized> fmt::Display for ArcRwLockWriteGuard<R, T> {
1896    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1897        (**self).fmt(f)
1898    }
1899}
1900
1901/// RAII structure used to release the upgradable read access of a lock when
1902/// dropped.
1903#[clippy::has_significant_drop]
1904#[must_use = "if unused the RwLock will immediately unlock"]
1905pub struct RwLockUpgradableReadGuard<'a, R: RawRwLockUpgrade, T: ?Sized> {
1906    rwlock: &'a RwLock<R, T>,
1907    marker: PhantomData<(&'a T, R::GuardMarker)>,
1908}
1909
1910unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + Sync + 'a> Sync
1911    for RwLockUpgradableReadGuard<'a, R, T>
1912{
1913}
1914
1915impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
1916    /// Returns a reference to the original reader-writer lock object.
1917    pub fn rwlock(s: &Self) -> &'a RwLock<R, T> {
1918        s.rwlock
1919    }
1920
1921    /// Temporarily unlocks the `RwLock` to execute the given function.
1922    ///
1923    /// This is safe because `&mut` guarantees that there exist no other
1924    /// references to the data protected by the `RwLock`.
1925    #[inline]
1926    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
1927    where
1928        F: FnOnce() -> U,
1929    {
1930        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
1931        unsafe {
1932            s.rwlock.raw.unlock_upgradable();
1933        }
1934        defer!(s.rwlock.raw.lock_upgradable());
1935        f()
1936    }
1937
1938    /// Atomically upgrades an upgradable read lock lock into an exclusive write lock,
1939    /// blocking the current thread until it can be acquired.
1940    pub fn upgrade(s: Self) -> RwLockWriteGuard<'a, R, T> {
1941        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
1942        unsafe {
1943            s.rwlock.raw.upgrade();
1944        }
1945        let rwlock = s.rwlock;
1946        mem::forget(s);
1947        RwLockWriteGuard {
1948            rwlock,
1949            marker: PhantomData,
1950        }
1951    }
1952
1953    /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock.
1954    ///
1955    /// If the access could not be granted at this time, then the current guard is returned.
1956    pub fn try_upgrade(s: Self) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
1957        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
1958        if unsafe { s.rwlock.raw.try_upgrade() } {
1959            let rwlock = s.rwlock;
1960            mem::forget(s);
1961            Ok(RwLockWriteGuard {
1962                rwlock,
1963                marker: PhantomData,
1964            })
1965        } else {
1966            Err(s)
1967        }
1968    }
1969}
1970
1971impl<'a, R: RawRwLockUpgradeFair + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
1972    /// Unlocks the `RwLock` using a fair unlock protocol.
1973    ///
1974    /// By default, `RwLock` is unfair and allow the current thread to re-lock
1975    /// the `RwLock` before another has the chance to acquire the lock, even if
1976    /// that thread has been blocked on the `RwLock` for a long time. This is
1977    /// the default because it allows much higher throughput as it avoids
1978    /// forcing a context switch on every `RwLock` unlock. This can result in one
1979    /// thread acquiring a `RwLock` many more times than other threads.
1980    ///
1981    /// However in some cases it can be beneficial to ensure fairness by forcing
1982    /// the lock to pass on to a waiting thread if there is one. This is done by
1983    /// using this method instead of dropping the `RwLockUpgradableReadGuard` normally.
1984    #[inline]
1985    pub fn unlock_fair(s: Self) {
1986        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
1987        unsafe {
1988            s.rwlock.raw.unlock_upgradable_fair();
1989        }
1990        mem::forget(s);
1991    }
1992
1993    /// Temporarily unlocks the `RwLock` to execute the given function.
1994    ///
1995    /// The `RwLock` is unlocked a fair unlock protocol.
1996    ///
1997    /// This is safe because `&mut` guarantees that there exist no other
1998    /// references to the data protected by the `RwLock`.
1999    #[inline]
2000    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
2001    where
2002        F: FnOnce() -> U,
2003    {
2004        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2005        unsafe {
2006            s.rwlock.raw.unlock_upgradable_fair();
2007        }
2008        defer!(s.rwlock.raw.lock_upgradable());
2009        f()
2010    }
2011
2012    /// Temporarily yields the `RwLock` to a waiting thread if there is one.
2013    ///
2014    /// This method is functionally equivalent to calling `unlock_fair` followed
2015    /// by `upgradable_read`, however it can be much more efficient in the case where there
2016    /// are no waiting threads.
2017    #[inline]
2018    pub fn bump(s: &mut Self) {
2019        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2020        unsafe {
2021            s.rwlock.raw.bump_upgradable();
2022        }
2023    }
2024}
2025
2026impl<'a, R: RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
2027    /// Atomically downgrades an upgradable read lock lock into a shared read lock
2028    /// without allowing any writers to take exclusive access of the lock in the
2029    /// meantime.
2030    ///
2031    /// Note that if there are any writers currently waiting to take the lock
2032    /// then other readers may not be able to acquire the lock even if it was
2033    /// downgraded.
2034    pub fn downgrade(s: Self) -> RwLockReadGuard<'a, R, T> {
2035        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2036        unsafe {
2037            s.rwlock.raw.downgrade_upgradable();
2038        }
2039        let rwlock = s.rwlock;
2040        mem::forget(s);
2041        RwLockReadGuard {
2042            rwlock,
2043            marker: PhantomData,
2044        }
2045    }
2046
2047    /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock,
2048    /// blocking the current thread until it can be acquired.
2049    ///
2050    /// Then, calls the provided closure with an exclusive reference to the lock's data.
2051    ///
2052    /// Finally, atomically downgrades the lock back to an upgradable read lock.
2053    /// The closure's return value is wrapped in `Some` and returned.
2054    ///
2055    /// This function only requires a mutable reference to the guard, unlike
2056    /// `upgrade` which takes the guard by value.
2057    pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret {
2058        unsafe {
2059            self.rwlock.raw.upgrade();
2060        }
2061
2062        // Safety: We just upgraded the lock, so we have mutable access to the data.
2063        // This will restore the state the lock was in at the start of the function.
2064        defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2065
2066        // Safety: We upgraded the lock, so we have mutable access to the data.
2067        // When this function returns, whether by drop or panic,
2068        // the drop guard will downgrade it back to an upgradeable lock.
2069        f(unsafe { &mut *self.rwlock.data.get() })
2070    }
2071
2072    /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2073    ///
2074    /// If the access could not be granted at this time, then `None` is returned.
2075    ///
2076    /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2077    /// and finally downgrades the lock back to an upgradable read lock.
2078    /// The closure's return value is wrapped in `Some` and returned.
2079    ///
2080    /// This function only requires a mutable reference to the guard, unlike
2081    /// `try_upgrade` which takes the guard by value.
2082    pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> {
2083        if unsafe { self.rwlock.raw.try_upgrade() } {
2084            // Safety: We just upgraded the lock, so we have mutable access to the data.
2085            // This will restore the state the lock was in at the start of the function.
2086            defer!(unsafe { self.rwlock.raw.downgrade_to_upgradable() });
2087
2088            // Safety: We upgraded the lock, so we have mutable access to the data.
2089            // When this function returns, whether by drop or panic,
2090            // the drop guard will downgrade it back to an upgradeable lock.
2091            Some(f(unsafe { &mut *self.rwlock.data.get() }))
2092        } else {
2093            None
2094        }
2095    }
2096}
2097
2098impl<'a, R: RawRwLockUpgradeTimed + 'a, T: ?Sized + 'a> RwLockUpgradableReadGuard<'a, R, T> {
2099    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2100    /// write lock, until a timeout is reached.
2101    ///
2102    /// If the access could not be granted before the timeout expires, then
2103    /// the current guard is returned.
2104    pub fn try_upgrade_for(
2105        s: Self,
2106        timeout: R::Duration,
2107    ) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
2108        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2109        if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } {
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    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2122    /// write lock, until a timeout is reached.
2123    ///
2124    /// If the access could not be granted before the timeout expires, then
2125    /// the current guard is returned.
2126    #[inline]
2127    pub fn try_upgrade_until(
2128        s: Self,
2129        timeout: R::Instant,
2130    ) -> Result<RwLockWriteGuard<'a, R, T>, Self> {
2131        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2132        if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } {
2133            let rwlock = s.rwlock;
2134            mem::forget(s);
2135            Ok(RwLockWriteGuard {
2136                rwlock,
2137                marker: PhantomData,
2138            })
2139        } else {
2140            Err(s)
2141        }
2142    }
2143}
2144
2145impl<'a, R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade + 'a, T: ?Sized + 'a>
2146    RwLockUpgradableReadGuard<'a, R, T>
2147{
2148    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2149    /// write lock, until a timeout is reached.
2150    ///
2151    /// If the access could not be granted before the timeout expires, then
2152    /// `None` is returned.
2153    ///
2154    /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2155    /// and finally downgrades the lock back to an upgradable read lock.
2156    /// The closure's return value is wrapped in `Some` and returned.
2157    ///
2158    /// This function only requires a mutable reference to the guard, unlike
2159    /// `try_upgrade_for` which takes the guard by value.
2160    pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>(
2161        &mut self,
2162        timeout: R::Duration,
2163        f: F,
2164    ) -> Option<Ret> {
2165        if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } {
2166            // Safety: We just upgraded the lock, so we have mutable access to the data.
2167            // This will restore the state the lock was in at the start of the function.
2168            defer!(unsafe { self.rwlock.raw.downgrade_upgradable() });
2169
2170            // Safety: We upgraded the lock, so we have mutable access to the data.
2171            // When this function returns, whether by drop or panic,
2172            // the drop guard will downgrade it back to an upgradeable lock.
2173            Some(f(unsafe { &mut *self.rwlock.data.get() }))
2174        } else {
2175            None
2176        }
2177    }
2178
2179    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2180    /// write lock, until a timeout is reached.
2181    ///
2182    /// If the access could not be granted before the timeout expires, then
2183    /// `None` is returned.
2184    ///
2185    /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2186    /// and finally downgrades the lock back to an upgradable read lock.
2187    /// The closure's return value is wrapped in `Some` and returned.
2188    ///
2189    /// This function only requires a mutable reference to the guard, unlike
2190    /// `try_upgrade_until` which takes the guard by value.
2191    pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>(
2192        &mut self,
2193        timeout: R::Instant,
2194        f: F,
2195    ) -> Option<Ret> {
2196        if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } {
2197            // Safety: We just upgraded the lock, so we have mutable access to the data.
2198            // This will restore the state the lock was in at the start of the function.
2199            defer!(unsafe { self.rwlock.raw.downgrade_upgradable() });
2200
2201            // Safety: We upgraded the lock, so we have mutable access to the data.
2202            // When this function returns, whether by drop or panic,
2203            // the drop guard will downgrade it back to an upgradeable lock.
2204            Some(f(unsafe { &mut *self.rwlock.data.get() }))
2205        } else {
2206            None
2207        }
2208    }
2209}
2210
2211impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Deref for RwLockUpgradableReadGuard<'a, R, T> {
2212    type Target = T;
2213    #[inline]
2214    fn deref(&self) -> &T {
2215        unsafe { &*self.rwlock.data.get() }
2216    }
2217}
2218
2219impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> Drop for RwLockUpgradableReadGuard<'a, R, T> {
2220    #[inline]
2221    fn drop(&mut self) {
2222        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2223        unsafe {
2224            self.rwlock.raw.unlock_upgradable();
2225        }
2226    }
2227}
2228
2229impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
2230    for RwLockUpgradableReadGuard<'a, R, T>
2231{
2232    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2233        fmt::Debug::fmt(&**self, f)
2234    }
2235}
2236
2237impl<'a, R: RawRwLockUpgrade + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
2238    for RwLockUpgradableReadGuard<'a, R, T>
2239{
2240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2241        (**self).fmt(f)
2242    }
2243}
2244
2245#[cfg(feature = "owning_ref")]
2246unsafe impl<'a, R: RawRwLockUpgrade + 'a, T: ?Sized + 'a> StableAddress
2247    for RwLockUpgradableReadGuard<'a, R, T>
2248{
2249}
2250
2251/// An RAII rwlock guard returned by the `Arc` locking operations on `RwLock`.
2252/// This is similar to the `RwLockUpgradableReadGuard` struct, except instead of using a reference to unlock the
2253/// `RwLock` it uses an `Arc<RwLock>`. This has several advantages, most notably that it has an `'static`
2254/// lifetime.
2255#[cfg(feature = "arc_lock")]
2256#[clippy::has_significant_drop]
2257#[must_use = "if unused the RwLock will immediately unlock"]
2258pub struct ArcRwLockUpgradableReadGuard<R: RawRwLockUpgrade, T: ?Sized> {
2259    rwlock: Arc<RwLock<R, T>>,
2260    marker: PhantomData<R::GuardMarker>,
2261}
2262
2263#[cfg(feature = "arc_lock")]
2264impl<R: RawRwLockUpgrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2265    /// Returns a reference to the rwlock, contained in its original `Arc`.
2266    pub fn rwlock(s: &Self) -> &Arc<RwLock<R, T>> {
2267        &s.rwlock
2268    }
2269
2270    /// Temporarily unlocks the `RwLock` to execute the given function.
2271    ///
2272    /// This is functionally identical to the `unlocked` method on [`RwLockUpgradableReadGuard`].
2273    #[inline]
2274    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
2275    where
2276        F: FnOnce() -> U,
2277    {
2278        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2279        unsafe {
2280            s.rwlock.raw.unlock_upgradable();
2281        }
2282        defer!(s.rwlock.raw.lock_upgradable());
2283        f()
2284    }
2285
2286    /// Atomically upgrades an upgradable read lock lock into an exclusive write lock,
2287    /// blocking the current thread until it can be acquired.
2288    pub fn upgrade(s: Self) -> ArcRwLockWriteGuard<R, T> {
2289        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2290        unsafe {
2291            s.rwlock.raw.upgrade();
2292        }
2293
2294        // SAFETY: avoid incrementing or decrementing the refcount using ManuallyDrop and reading the Arc out
2295        //         of the struct
2296        let s = ManuallyDrop::new(s);
2297        let rwlock = unsafe { ptr::read(&s.rwlock) };
2298
2299        ArcRwLockWriteGuard {
2300            rwlock,
2301            marker: PhantomData,
2302        }
2303    }
2304
2305    /// Tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2306    ///
2307    /// If the access could not be granted at this time, then the current guard is returned.
2308    pub fn try_upgrade(s: Self) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
2309        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2310        if unsafe { s.rwlock.raw.try_upgrade() } {
2311            // SAFETY: same as above
2312            let s = ManuallyDrop::new(s);
2313            let rwlock = unsafe { ptr::read(&s.rwlock) };
2314
2315            Ok(ArcRwLockWriteGuard {
2316                rwlock,
2317                marker: PhantomData,
2318            })
2319        } else {
2320            Err(s)
2321        }
2322    }
2323}
2324
2325#[cfg(feature = "arc_lock")]
2326impl<R: RawRwLockUpgradeFair, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2327    /// Unlocks the `RwLock` using a fair unlock protocol.
2328    ///
2329    /// This is functionally identical to the `unlock_fair` method on [`RwLockUpgradableReadGuard`].
2330    #[inline]
2331    pub fn unlock_fair(s: Self) {
2332        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2333        unsafe {
2334            s.rwlock.raw.unlock_upgradable_fair();
2335        }
2336
2337        // SAFETY: make sure we decrement the refcount properly
2338        let mut s = ManuallyDrop::new(s);
2339        unsafe { ptr::drop_in_place(&mut s.rwlock) };
2340    }
2341
2342    /// Temporarily unlocks the `RwLock` to execute the given function.
2343    ///
2344    /// This is functionally equivalent to the `unlocked_fair` method on [`RwLockUpgradableReadGuard`].
2345    #[inline]
2346    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
2347    where
2348        F: FnOnce() -> U,
2349    {
2350        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2351        unsafe {
2352            s.rwlock.raw.unlock_upgradable_fair();
2353        }
2354        defer!(s.rwlock.raw.lock_upgradable());
2355        f()
2356    }
2357
2358    /// Temporarily yields the `RwLock` to a waiting thread if there is one.
2359    ///
2360    /// This method is functionally equivalent to calling `bump` on [`RwLockUpgradableReadGuard`].
2361    #[inline]
2362    pub fn bump(s: &mut Self) {
2363        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2364        unsafe {
2365            s.rwlock.raw.bump_upgradable();
2366        }
2367    }
2368}
2369
2370#[cfg(feature = "arc_lock")]
2371impl<R: RawRwLockUpgradeDowngrade, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2372    /// Atomically downgrades an upgradable read lock lock into a shared read lock
2373    /// without allowing any writers to take exclusive access of the lock in the
2374    /// meantime.
2375    ///
2376    /// Note that if there are any writers currently waiting to take the lock
2377    /// then other readers may not be able to acquire the lock even if it was
2378    /// downgraded.
2379    pub fn downgrade(s: Self) -> ArcRwLockReadGuard<R, T> {
2380        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2381        unsafe {
2382            s.rwlock.raw.downgrade_upgradable();
2383        }
2384
2385        // SAFETY: use ManuallyDrop and ptr::read to ensure the refcount is not changed
2386        let s = ManuallyDrop::new(s);
2387        let rwlock = unsafe { ptr::read(&s.rwlock) };
2388
2389        ArcRwLockReadGuard {
2390            rwlock,
2391            marker: PhantomData,
2392        }
2393    }
2394
2395    /// First, atomically upgrades an upgradable read lock lock into an exclusive write lock,
2396    /// blocking the current thread until it can be acquired.
2397    ///
2398    /// Then, calls the provided closure with an exclusive reference to the lock's data.
2399    ///
2400    /// Finally, atomically downgrades the lock back to an upgradable read lock.
2401    /// The closure's return value is returned.
2402    ///
2403    /// This function only requires a mutable reference to the guard, unlike
2404    /// `upgrade` which takes the guard by value.
2405    pub fn with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Ret {
2406        unsafe {
2407            self.rwlock.raw.upgrade();
2408        }
2409
2410        // Safety: We just upgraded the lock, so we have mutable access to the data.
2411        // This will restore the state the lock was in at the start of the function.
2412        defer!(unsafe { self.rwlock.raw.downgrade_upgradable() });
2413
2414        // Safety: We upgraded the lock, so we have mutable access to the data.
2415        // When this function returns, whether by drop or panic,
2416        // the drop guard will downgrade it back to an upgradeable lock.
2417        f(unsafe { &mut *self.rwlock.data.get() })
2418    }
2419
2420    /// First, tries to atomically upgrade an upgradable read lock into an exclusive write lock.
2421    ///
2422    /// If the access could not be granted at this time, then `None` is returned.
2423    ///
2424    /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2425    /// and finally downgrades the lock back to an upgradable read lock.
2426    /// The closure's return value is wrapped in `Some` and returned.
2427    ///
2428    /// This function only requires a mutable reference to the guard, unlike
2429    /// `try_upgrade` which takes the guard by value.
2430    pub fn try_with_upgraded<Ret, F: FnOnce(&mut T) -> Ret>(&mut self, f: F) -> Option<Ret> {
2431        if unsafe { self.rwlock.raw.try_upgrade() } {
2432            // Safety: We just upgraded the lock, so we have mutable access to the data.
2433            // This will restore the state the lock was in at the start of the function.
2434            defer!(unsafe { self.rwlock.raw.downgrade_upgradable() });
2435
2436            // Safety: We upgraded the lock, so we have mutable access to the data.
2437            // When this function returns, whether by drop or panic,
2438            // the drop guard will downgrade it back to an upgradeable lock.
2439            Some(f(unsafe { &mut *self.rwlock.data.get() }))
2440        } else {
2441            None
2442        }
2443    }
2444}
2445
2446#[cfg(feature = "arc_lock")]
2447impl<R: RawRwLockUpgradeTimed, T: ?Sized> ArcRwLockUpgradableReadGuard<R, T> {
2448    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2449    /// write lock, until a timeout is reached.
2450    ///
2451    /// If the access could not be granted before the timeout expires, then
2452    /// the current guard is returned.
2453    pub fn try_upgrade_for(
2454        s: Self,
2455        timeout: R::Duration,
2456    ) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
2457        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2458        if unsafe { s.rwlock.raw.try_upgrade_for(timeout) } {
2459            // SAFETY: same as above
2460            let s = ManuallyDrop::new(s);
2461            let rwlock = unsafe { ptr::read(&s.rwlock) };
2462
2463            Ok(ArcRwLockWriteGuard {
2464                rwlock,
2465                marker: PhantomData,
2466            })
2467        } else {
2468            Err(s)
2469        }
2470    }
2471
2472    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2473    /// write lock, until a timeout is reached.
2474    ///
2475    /// If the access could not be granted before the timeout expires, then
2476    /// the current guard is returned.
2477    #[inline]
2478    pub fn try_upgrade_until(
2479        s: Self,
2480        timeout: R::Instant,
2481    ) -> Result<ArcRwLockWriteGuard<R, T>, Self> {
2482        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2483        if unsafe { s.rwlock.raw.try_upgrade_until(timeout) } {
2484            // SAFETY: same as above
2485            let s = ManuallyDrop::new(s);
2486            let rwlock = unsafe { ptr::read(&s.rwlock) };
2487
2488            Ok(ArcRwLockWriteGuard {
2489                rwlock,
2490                marker: PhantomData,
2491            })
2492        } else {
2493            Err(s)
2494        }
2495    }
2496}
2497
2498#[cfg(feature = "arc_lock")]
2499impl<R: RawRwLockUpgradeTimed + RawRwLockUpgradeDowngrade, T: ?Sized>
2500    ArcRwLockUpgradableReadGuard<R, T>
2501{
2502    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2503    /// write lock, until a timeout is reached.
2504    ///
2505    /// If the access could not be granted before the timeout expires, then
2506    /// `None` is returned.
2507    ///
2508    /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2509    /// and finally downgrades the lock back to an upgradable read lock.
2510    /// The closure's return value is wrapped in `Some` and returned.
2511    ///
2512    /// This function only requires a mutable reference to the guard, unlike
2513    /// `try_upgrade_for` which takes the guard by value.
2514    pub fn try_with_upgraded_for<Ret, F: FnOnce(&mut T) -> Ret>(
2515        &mut self,
2516        timeout: R::Duration,
2517        f: F,
2518    ) -> Option<Ret> {
2519        if unsafe { self.rwlock.raw.try_upgrade_for(timeout) } {
2520            // Safety: We just upgraded the lock, so we have mutable access to the data.
2521            // This will restore the state the lock was in at the start of the function.
2522            defer!(unsafe { self.rwlock.raw.downgrade_upgradable() });
2523
2524            // Safety: We upgraded the lock, so we have mutable access to the data.
2525            // When this function returns, whether by drop or panic,
2526            // the drop guard will downgrade it back to an upgradeable lock.
2527            Some(f(unsafe { &mut *self.rwlock.data.get() }))
2528        } else {
2529            None
2530        }
2531    }
2532
2533    /// Tries to atomically upgrade an upgradable read lock into an exclusive
2534    /// write lock, until a timeout is reached.
2535    ///
2536    /// If the access could not be granted before the timeout expires, then
2537    /// `None` is returned.
2538    ///
2539    /// Otherwise, calls the provided closure with an exclusive reference to the lock's data,
2540    /// and finally downgrades the lock back to an upgradable read lock.
2541    /// The closure's return value is wrapped in `Some` and returned.
2542    ///
2543    /// This function only requires a mutable reference to the guard, unlike
2544    /// `try_upgrade_until` which takes the guard by value.
2545    pub fn try_with_upgraded_until<Ret, F: FnOnce(&mut T) -> Ret>(
2546        &mut self,
2547        timeout: R::Instant,
2548        f: F,
2549    ) -> Option<Ret> {
2550        if unsafe { self.rwlock.raw.try_upgrade_until(timeout) } {
2551            // Safety: We just upgraded the lock, so we have mutable access to the data.
2552            // This will restore the state the lock was in at the start of the function.
2553            defer!(unsafe { self.rwlock.raw.downgrade_upgradable() });
2554
2555            // Safety: We upgraded the lock, so we have mutable access to the data.
2556            // When this function returns, whether by drop or panic,
2557            // the drop guard will downgrade it back to an upgradeable lock.
2558            Some(f(unsafe { &mut *self.rwlock.data.get() }))
2559        } else {
2560            None
2561        }
2562    }
2563}
2564
2565#[cfg(feature = "arc_lock")]
2566impl<R: RawRwLockUpgrade, T: ?Sized> Deref for ArcRwLockUpgradableReadGuard<R, T> {
2567    type Target = T;
2568    #[inline]
2569    fn deref(&self) -> &T {
2570        unsafe { &*self.rwlock.data.get() }
2571    }
2572}
2573
2574#[cfg(feature = "arc_lock")]
2575impl<R: RawRwLockUpgrade, T: ?Sized> Drop for ArcRwLockUpgradableReadGuard<R, T> {
2576    #[inline]
2577    fn drop(&mut self) {
2578        // Safety: An RwLockUpgradableReadGuard always holds an upgradable lock.
2579        unsafe {
2580            self.rwlock.raw.unlock_upgradable();
2581        }
2582    }
2583}
2584
2585#[cfg(feature = "arc_lock")]
2586impl<R: RawRwLockUpgrade, T: fmt::Debug + ?Sized> fmt::Debug
2587    for ArcRwLockUpgradableReadGuard<R, T>
2588{
2589    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2590        fmt::Debug::fmt(&**self, f)
2591    }
2592}
2593
2594#[cfg(feature = "arc_lock")]
2595impl<R: RawRwLockUpgrade, T: fmt::Display + ?Sized> fmt::Display
2596    for ArcRwLockUpgradableReadGuard<R, T>
2597{
2598    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2599        (**self).fmt(f)
2600    }
2601}
2602
2603/// An RAII read lock guard returned by `RwLockReadGuard::map`, which can point to a
2604/// subfield of the protected data.
2605///
2606/// The main difference between `MappedRwLockReadGuard` and `RwLockReadGuard` is that the
2607/// former doesn't support temporarily unlocking and re-locking, since that
2608/// could introduce soundness issues if the locked object is modified by another
2609/// thread.
2610#[clippy::has_significant_drop]
2611#[must_use = "if unused the RwLock will immediately unlock"]
2612pub struct MappedRwLockReadGuard<'a, R: RawRwLock, T: ?Sized> {
2613    raw: &'a R,
2614    data: *const T,
2615    marker: PhantomData<&'a T>,
2616}
2617
2618unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync for MappedRwLockReadGuard<'a, R, T> {}
2619unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Send for MappedRwLockReadGuard<'a, R, T> where
2620    R::GuardMarker: Send
2621{
2622}
2623
2624impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
2625    /// Make a new `MappedRwLockReadGuard` for a component of the locked data.
2626    ///
2627    /// This operation cannot fail as the `MappedRwLockReadGuard` passed
2628    /// in already locked the data.
2629    ///
2630    /// This is an associated function that needs to be
2631    /// used as `MappedRwLockReadGuard::map(...)`. A method would interfere with methods of
2632    /// the same name on the contents of the locked data.
2633    #[inline]
2634    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockReadGuard<'a, R, U>
2635    where
2636        F: FnOnce(&T) -> &U,
2637    {
2638        let raw = s.raw;
2639        let data = f(unsafe { &*s.data });
2640        mem::forget(s);
2641        MappedRwLockReadGuard {
2642            raw,
2643            data,
2644            marker: PhantomData,
2645        }
2646    }
2647
2648    /// Attempts to make  a new `MappedRwLockReadGuard` for a component of the
2649    /// locked data. The original guard is return if the closure returns `None`.
2650    ///
2651    /// This operation cannot fail as the `MappedRwLockReadGuard` passed
2652    /// in already locked the data.
2653    ///
2654    /// This is an associated function that needs to be
2655    /// used as `MappedRwLockReadGuard::try_map(...)`. A method would interfere with methods of
2656    /// the same name on the contents of the locked data.
2657    #[inline]
2658    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
2659    where
2660        F: FnOnce(&T) -> Option<&U>,
2661    {
2662        let raw = s.raw;
2663        let data = match f(unsafe { &*s.data }) {
2664            Some(data) => data,
2665            None => return Err(s),
2666        };
2667        mem::forget(s);
2668        Ok(MappedRwLockReadGuard {
2669            raw,
2670            data,
2671            marker: PhantomData,
2672        })
2673    }
2674}
2675
2676impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
2677    /// Unlocks the `RwLock` using a fair unlock protocol.
2678    ///
2679    /// By default, `RwLock` is unfair and allow the current thread to re-lock
2680    /// the `RwLock` before another has the chance to acquire the lock, even if
2681    /// that thread has been blocked on the `RwLock` for a long time. This is
2682    /// the default because it allows much higher throughput as it avoids
2683    /// forcing a context switch on every `RwLock` unlock. This can result in one
2684    /// thread acquiring a `RwLock` many more times than other threads.
2685    ///
2686    /// However in some cases it can be beneficial to ensure fairness by forcing
2687    /// the lock to pass on to a waiting thread if there is one. This is done by
2688    /// using this method instead of dropping the `MappedRwLockReadGuard` normally.
2689    #[inline]
2690    pub fn unlock_fair(s: Self) {
2691        // Safety: A MappedRwLockReadGuard always holds a shared lock.
2692        unsafe {
2693            s.raw.unlock_shared_fair();
2694        }
2695        mem::forget(s);
2696    }
2697}
2698
2699impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockReadGuard<'a, R, T> {
2700    type Target = T;
2701    #[inline]
2702    fn deref(&self) -> &T {
2703        unsafe { &*self.data }
2704    }
2705}
2706
2707impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockReadGuard<'a, R, T> {
2708    #[inline]
2709    fn drop(&mut self) {
2710        // Safety: A MappedRwLockReadGuard always holds a shared lock.
2711        unsafe {
2712            self.raw.unlock_shared();
2713        }
2714    }
2715}
2716
2717impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
2718    for MappedRwLockReadGuard<'a, R, T>
2719{
2720    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2721        fmt::Debug::fmt(&**self, f)
2722    }
2723}
2724
2725impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
2726    for MappedRwLockReadGuard<'a, R, T>
2727{
2728    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2729        (**self).fmt(f)
2730    }
2731}
2732
2733#[cfg(feature = "owning_ref")]
2734unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress
2735    for MappedRwLockReadGuard<'a, R, T>
2736{
2737}
2738
2739/// An RAII write lock guard returned by `RwLockWriteGuard::map`, which can point to a
2740/// subfield of the protected data.
2741///
2742/// The main difference between `MappedRwLockWriteGuard` and `RwLockWriteGuard` is that the
2743/// former doesn't support temporarily unlocking and re-locking, since that
2744/// could introduce soundness issues if the locked object is modified by another
2745/// thread.
2746#[clippy::has_significant_drop]
2747#[must_use = "if unused the RwLock will immediately unlock"]
2748pub struct MappedRwLockWriteGuard<'a, R: RawRwLock, T: ?Sized> {
2749    raw: &'a R,
2750    data: *mut T,
2751    marker: PhantomData<&'a mut T>,
2752}
2753
2754unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Sync + 'a> Sync
2755    for MappedRwLockWriteGuard<'a, R, T>
2756{
2757}
2758unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + Send + 'a> Send for MappedRwLockWriteGuard<'a, R, T> where
2759    R::GuardMarker: Send
2760{
2761}
2762
2763impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
2764    /// Make a new `MappedRwLockWriteGuard` for a component of the locked data.
2765    ///
2766    /// This operation cannot fail as the `MappedRwLockWriteGuard` passed
2767    /// in already locked the data.
2768    ///
2769    /// This is an associated function that needs to be
2770    /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of
2771    /// the same name on the contents of the locked data.
2772    #[inline]
2773    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedRwLockWriteGuard<'a, R, U>
2774    where
2775        F: FnOnce(&mut T) -> &mut U,
2776    {
2777        let raw = s.raw;
2778        let data = f(unsafe { &mut *s.data });
2779        mem::forget(s);
2780        MappedRwLockWriteGuard {
2781            raw,
2782            data,
2783            marker: PhantomData,
2784        }
2785    }
2786
2787    /// Attempts to make  a new `MappedRwLockWriteGuard` for a component of the
2788    /// locked data. The original guard is return if the closure returns `None`.
2789    ///
2790    /// This operation cannot fail as the `MappedRwLockWriteGuard` passed
2791    /// in already locked the data.
2792    ///
2793    /// This is an associated function that needs to be
2794    /// used as `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with methods of
2795    /// the same name on the contents of the locked data.
2796    #[inline]
2797    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
2798    where
2799        F: FnOnce(&mut T) -> Option<&mut U>,
2800    {
2801        let raw = s.raw;
2802        let data = match f(unsafe { &mut *s.data }) {
2803            Some(data) => data,
2804            None => return Err(s),
2805        };
2806        mem::forget(s);
2807        Ok(MappedRwLockWriteGuard {
2808            raw,
2809            data,
2810            marker: PhantomData,
2811        })
2812    }
2813}
2814
2815impl<'a, R: RawRwLockFair + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
2816    /// Unlocks the `RwLock` using a fair unlock protocol.
2817    ///
2818    /// By default, `RwLock` is unfair and allow the current thread to re-lock
2819    /// the `RwLock` before another has the chance to acquire the lock, even if
2820    /// that thread has been blocked on the `RwLock` for a long time. This is
2821    /// the default because it allows much higher throughput as it avoids
2822    /// forcing a context switch on every `RwLock` unlock. This can result in one
2823    /// thread acquiring a `RwLock` many more times than other threads.
2824    ///
2825    /// However in some cases it can be beneficial to ensure fairness by forcing
2826    /// the lock to pass on to a waiting thread if there is one. This is done by
2827    /// using this method instead of dropping the `MappedRwLockWriteGuard` normally.
2828    #[inline]
2829    pub fn unlock_fair(s: Self) {
2830        // Safety: A MappedRwLockWriteGuard always holds an exclusive lock.
2831        unsafe {
2832            s.raw.unlock_exclusive_fair();
2833        }
2834        mem::forget(s);
2835    }
2836}
2837
2838impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Deref for MappedRwLockWriteGuard<'a, R, T> {
2839    type Target = T;
2840    #[inline]
2841    fn deref(&self) -> &T {
2842        unsafe { &*self.data }
2843    }
2844}
2845
2846impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> DerefMut for MappedRwLockWriteGuard<'a, R, T> {
2847    #[inline]
2848    fn deref_mut(&mut self) -> &mut T {
2849        unsafe { &mut *self.data }
2850    }
2851}
2852
2853impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> Drop for MappedRwLockWriteGuard<'a, R, T> {
2854    #[inline]
2855    fn drop(&mut self) {
2856        // Safety: A MappedRwLockWriteGuard always holds an exclusive lock.
2857        unsafe {
2858            self.raw.unlock_exclusive();
2859        }
2860    }
2861}
2862
2863impl<'a, R: RawRwLock + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug
2864    for MappedRwLockWriteGuard<'a, R, T>
2865{
2866    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2867        fmt::Debug::fmt(&**self, f)
2868    }
2869}
2870
2871impl<'a, R: RawRwLock + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
2872    for MappedRwLockWriteGuard<'a, R, T>
2873{
2874    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2875        (**self).fmt(f)
2876    }
2877}
2878
2879#[cfg(feature = "owning_ref")]
2880unsafe impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> StableAddress
2881    for MappedRwLockWriteGuard<'a, R, T>
2882{
2883}