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