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