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