1// Copyright 2018 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 mutex.
28///
29/// Types implementing this trait can be used by `Mutex` to form a safe and
30/// fully-functioning mutex type.
31///
32/// # Safety
33///
34/// Implementations of this trait must ensure that the mutex is actually
35/// exclusive: a lock can't be acquired while the mutex is already locked.
36pub unsafe trait RawMutex {
37 /// Initial value for an unlocked mutex.
38 // A “non-constant” const item is a legacy way to supply an initialized value to downstream
39 // static items. Can hopefully be replaced with `const fn new() -> Self` at some point.
40 #[allow(clippy::declare_interior_mutable_const)]
41 const INIT: Self;
42
43 /// Marker type which determines whether a lock guard should be `Send`. Use
44 /// one of the `GuardSend` or `GuardNoSend` helper types here.
45 type GuardMarker;
46
47 /// Acquires this mutex, blocking the current thread until it is able to do so.
48 fn lock(&self);
49
50 /// Attempts to acquire this mutex without blocking. Returns `true`
51 /// if the lock was successfully acquired and `false` otherwise.
52 fn try_lock(&self) -> bool;
53
54 /// Unlocks this mutex.
55 ///
56 /// # Safety
57 ///
58 /// This method may only be called if the mutex is held in the current context, i.e. it must
59 /// be paired with a successful call to [`lock`], [`try_lock`], [`try_lock_for`] or [`try_lock_until`].
60 ///
61 /// [`lock`]: #tymethod.lock
62 /// [`try_lock`]: #tymethod.try_lock
63 /// [`try_lock_for`]: trait.RawMutexTimed.html#tymethod.try_lock_for
64 /// [`try_lock_until`]: trait.RawMutexTimed.html#tymethod.try_lock_until
65 unsafe fn unlock(&self);
66
67 /// Checks whether the mutex is currently locked.
68 #[inline]
69 fn is_locked(&self) -> bool {
70 let acquired_lock = self.try_lock();
71 if acquired_lock {
72 // Safety: The lock has been successfully acquired above.
73 unsafe {
74 self.unlock();
75 }
76 }
77 !acquired_lock
78 }
79}
80
81/// Additional methods for mutexes which support fair unlocking.
82///
83/// Fair unlocking means that a lock is handed directly over to the next waiting
84/// thread if there is one, without giving other threads the opportunity to
85/// "steal" the lock in the meantime. This is typically slower than unfair
86/// unlocking, but may be necessary in certain circumstances.
87pub unsafe trait RawMutexFair: RawMutex {
88 /// Unlocks this mutex using a fair unlock protocol.
89 ///
90 /// # Safety
91 ///
92 /// This method may only be called if the mutex is held in the current context, see
93 /// the documentation of [`unlock`].
94 ///
95 /// [`unlock`]: trait.RawMutex.html#tymethod.unlock
96 unsafe fn unlock_fair(&self);
97
98 /// Temporarily yields the mutex to a waiting thread if there is one.
99 ///
100 /// This method is functionally equivalent to calling `unlock_fair` followed
101 /// by `lock`, however it can be much more efficient in the case where there
102 /// are no waiting threads.
103 ///
104 /// # Safety
105 ///
106 /// This method may only be called if the mutex is held in the current context, see
107 /// the documentation of [`unlock`].
108 ///
109 /// [`unlock`]: trait.RawMutex.html#tymethod.unlock
110 unsafe fn bump(&self) {
111 self.unlock_fair();
112 self.lock();
113 }
114}
115
116/// Additional methods for mutexes which support locking with timeouts.
117///
118/// The `Duration` and `Instant` types are specified as associated types so that
119/// this trait is usable even in `no_std` environments.
120pub unsafe trait RawMutexTimed: RawMutex {
121 /// Duration type used for `try_lock_for`.
122 type Duration;
123
124 /// Instant type used for `try_lock_until`.
125 type Instant;
126
127 /// Attempts to acquire this lock until a timeout is reached.
128 fn try_lock_for(&self, timeout: Self::Duration) -> bool;
129
130 /// Attempts to acquire this lock until a timeout is reached.
131 fn try_lock_until(&self, timeout: Self::Instant) -> bool;
132}
133
134/// A mutual exclusion primitive useful for protecting shared data
135///
136/// This mutex will block threads waiting for the lock to become available. The
137/// mutex can also be statically initialized or created via a `new`
138/// constructor. Each mutex has a type parameter which represents the data that
139/// it is protecting. The data can only be accessed through the RAII guards
140/// returned from `lock` and `try_lock`, which guarantees that the data is only
141/// ever accessed when the mutex is locked.
142pub struct Mutex<R, T: ?Sized> {
143 raw: R,
144 data: UnsafeCell<T>,
145}
146
147unsafe impl<R: RawMutex + Send, T: ?Sized + Send> Send for Mutex<R, T> {}
148unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {}
149
150impl<R: RawMutex, T> Mutex<R, T> {
151 /// Creates a new mutex in an unlocked state ready for use.
152 #[cfg(has_const_fn_trait_bound)]
153 #[inline]
154 pub const fn new(val: T) -> Mutex<R, T> {
155 Mutex {
156 raw: R::INIT,
157 data: UnsafeCell::new(val),
158 }
159 }
160
161 /// Creates a new mutex in an unlocked state ready for use.
162 #[cfg(not(has_const_fn_trait_bound))]
163 #[inline]
164 pub fn new(val: T) -> Mutex<R, T> {
165 Mutex {
166 raw: R::INIT,
167 data: UnsafeCell::new(val),
168 }
169 }
170
171 /// Consumes this mutex, returning the underlying data.
172 #[inline]
173 pub fn into_inner(self) -> T {
174 self.data.into_inner()
175 }
176}
177
178impl<R, T> Mutex<R, T> {
179 /// Creates a new mutex based on a pre-existing raw mutex.
180 ///
181 /// This allows creating a mutex in a constant context on stable Rust.
182 #[inline]
183 pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
184 Mutex {
185 raw: raw_mutex,
186 data: UnsafeCell::new(val),
187 }
188 }
189}
190
191impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
192 /// Creates a new `MutexGuard` without checking if the mutex is locked.
193 ///
194 /// # Safety
195 ///
196 /// This method must only be called if the thread logically holds the lock.
197 ///
198 /// Calling this function when a guard has already been produced is undefined behaviour unless
199 /// the guard was forgotten with `mem::forget`.
200 #[inline]
201 pub unsafe fn make_guard_unchecked(&self) -> MutexGuard<'_, R, T> {
202 MutexGuard {
203 mutex: self,
204 marker: PhantomData,
205 }
206 }
207
208 /// Acquires a mutex, blocking the current thread until it is able to do so.
209 ///
210 /// This function will block the local thread until it is available to acquire
211 /// the mutex. Upon returning, the thread is the only thread with the mutex
212 /// held. An RAII guard is returned to allow scoped unlock of the lock. When
213 /// the guard goes out of scope, the mutex will be unlocked.
214 ///
215 /// Attempts to lock a mutex in the thread which already holds the lock will
216 /// result in a deadlock.
217 #[inline]
218 pub fn lock(&self) -> MutexGuard<'_, R, T> {
219 self.raw.lock();
220 // SAFETY: The lock is held, as required.
221 unsafe { self.make_guard_unchecked() }
222 }
223
224 /// Attempts to acquire this lock.
225 ///
226 /// If the lock could not be acquired at this time, then `None` is returned.
227 /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
228 /// guard is dropped.
229 ///
230 /// This function does not block.
231 #[inline]
232 pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> {
233 if self.raw.try_lock() {
234 // SAFETY: The lock is held, as required.
235 Some(unsafe { self.make_guard_unchecked() })
236 } else {
237 None
238 }
239 }
240
241 /// Returns a mutable reference to the underlying data.
242 ///
243 /// Since this call borrows the `Mutex` mutably, no actual locking needs to
244 /// take place---the mutable borrow statically guarantees no locks exist.
245 #[inline]
246 pub fn get_mut(&mut self) -> &mut T {
247 unsafe { &mut *self.data.get() }
248 }
249
250 /// Checks whether the mutex is currently locked.
251 #[inline]
252 pub fn is_locked(&self) -> bool {
253 self.raw.is_locked()
254 }
255
256 /// Forcibly unlocks the mutex.
257 ///
258 /// This is useful when combined with `mem::forget` to hold a lock without
259 /// the need to maintain a `MutexGuard` object alive, for example when
260 /// dealing with FFI.
261 ///
262 /// # Safety
263 ///
264 /// This method must only be called if the current thread logically owns a
265 /// `MutexGuard` but that guard has been discarded using `mem::forget`.
266 /// Behavior is undefined if a mutex is unlocked when not locked.
267 #[inline]
268 pub unsafe fn force_unlock(&self) {
269 self.raw.unlock();
270 }
271
272 /// Returns the underlying raw mutex object.
273 ///
274 /// Note that you will most likely need to import the `RawMutex` trait from
275 /// `lock_api` to be able to call functions on the raw mutex.
276 ///
277 /// # Safety
278 ///
279 /// This method is unsafe because it allows unlocking a mutex while
280 /// still holding a reference to a `MutexGuard`.
281 #[inline]
282 pub unsafe fn raw(&self) -> &R {
283 &self.raw
284 }
285
286 /// Returns a raw pointer to the underlying data.
287 ///
288 /// This is useful when combined with `mem::forget` to hold a lock without
289 /// the need to maintain a `MutexGuard` object alive, for example when
290 /// dealing with FFI.
291 ///
292 /// # Safety
293 ///
294 /// You must ensure that there are no data races when dereferencing the
295 /// returned pointer, for example if the current thread logically owns
296 /// a `MutexGuard` but that guard has been discarded using `mem::forget`.
297 #[inline]
298 pub fn data_ptr(&self) -> *mut T {
299 self.data.get()
300 }
301
302 /// Creates a new `ArcMutexGuard` without checking if the mutex is locked.
303 ///
304 /// # Safety
305 ///
306 /// This method must only be called if the thread logically holds the lock.
307 ///
308 /// Calling this function when a guard has already been produced is undefined behaviour unless
309 /// the guard was forgotten with `mem::forget`.
310 #[cfg(feature = "arc_lock")]
311 #[inline]
312 unsafe fn make_arc_guard_unchecked(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
313 ArcMutexGuard {
314 mutex: self.clone(),
315 marker: PhantomData,
316 }
317 }
318
319 /// Acquires a lock through an `Arc`.
320 ///
321 /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc`
322 /// and the resulting mutex guard has no lifetime requirements.
323 #[cfg(feature = "arc_lock")]
324 #[inline]
325 pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
326 self.raw.lock();
327 // SAFETY: the locking guarantee is upheld
328 unsafe { self.make_arc_guard_unchecked() }
329 }
330
331 /// Attempts to acquire a lock through an `Arc`.
332 ///
333 /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an
334 /// `Arc` and the resulting mutex guard has no lifetime requirements.
335 #[cfg(feature = "arc_lock")]
336 #[inline]
337 pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> {
338 if self.raw.try_lock() {
339 // SAFETY: locking guarantee is upheld
340 Some(unsafe { self.make_arc_guard_unchecked() })
341 } else {
342 None
343 }
344 }
345}
346
347impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> {
348 /// Forcibly unlocks the mutex using a fair unlock procotol.
349 ///
350 /// This is useful when combined with `mem::forget` to hold a lock without
351 /// the need to maintain a `MutexGuard` object alive, for example when
352 /// dealing with FFI.
353 ///
354 /// # Safety
355 ///
356 /// This method must only be called if the current thread logically owns a
357 /// `MutexGuard` but that guard has been discarded using `mem::forget`.
358 /// Behavior is undefined if a mutex is unlocked when not locked.
359 #[inline]
360 pub unsafe fn force_unlock_fair(&self) {
361 self.raw.unlock_fair();
362 }
363}
364
365impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
366 /// Attempts to acquire this lock until a timeout is reached.
367 ///
368 /// If the lock could not be acquired before the timeout expired, then
369 /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
370 /// be unlocked when the guard is dropped.
371 #[inline]
372 pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> {
373 if self.raw.try_lock_for(timeout) {
374 // SAFETY: The lock is held, as required.
375 Some(unsafe { self.make_guard_unchecked() })
376 } else {
377 None
378 }
379 }
380
381 /// Attempts to acquire this lock until a timeout is reached.
382 ///
383 /// If the lock could not be acquired before the timeout expired, then
384 /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
385 /// be unlocked when the guard is dropped.
386 #[inline]
387 pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> {
388 if self.raw.try_lock_until(timeout) {
389 // SAFETY: The lock is held, as required.
390 Some(unsafe { self.make_guard_unchecked() })
391 } else {
392 None
393 }
394 }
395
396 /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
397 ///
398 /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an
399 /// `Arc` and the resulting mutex guard has no lifetime requirements.
400 #[cfg(feature = "arc_lock")]
401 #[inline]
402 pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> {
403 if self.raw.try_lock_for(timeout) {
404 // SAFETY: locking guarantee is upheld
405 Some(unsafe { self.make_arc_guard_unchecked() })
406 } else {
407 None
408 }
409 }
410
411 /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
412 ///
413 /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of
414 /// an `Arc` and the resulting mutex guard has no lifetime requirements.
415 #[cfg(feature = "arc_lock")]
416 #[inline]
417 pub fn try_lock_arc_until(
418 self: &Arc<Self>,
419 timeout: R::Instant,
420 ) -> Option<ArcMutexGuard<R, T>> {
421 if self.raw.try_lock_until(timeout) {
422 // SAFETY: locking guarantee is upheld
423 Some(unsafe { self.make_arc_guard_unchecked() })
424 } else {
425 None
426 }
427 }
428}
429
430impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> {
431 #[inline]
432 fn default() -> Mutex<R, T> {
433 Mutex::new(Default::default())
434 }
435}
436
437impl<R: RawMutex, T> From<T> for Mutex<R, T> {
438 #[inline]
439 fn from(t: T) -> Mutex<R, T> {
440 Mutex::new(t)
441 }
442}
443
444impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> {
445 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446 match self.try_lock() {
447 Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
448 None => {
449 struct LockedPlaceholder;
450 impl fmt::Debug for LockedPlaceholder {
451 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
452 f.write_str("<locked>")
453 }
454 }
455
456 f.debug_struct("Mutex")
457 .field("data", &LockedPlaceholder)
458 .finish()
459 }
460 }
461 }
462}
463
464// Copied and modified from serde
465#[cfg(feature = "serde")]
466impl<R, T> Serialize for Mutex<R, T>
467where
468 R: RawMutex,
469 T: Serialize + ?Sized,
470{
471 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
472 where
473 S: Serializer,
474 {
475 self.lock().serialize(serializer)
476 }
477}
478
479#[cfg(feature = "serde")]
480impl<'de, R, T> Deserialize<'de> for Mutex<R, T>
481where
482 R: RawMutex,
483 T: Deserialize<'de> + ?Sized,
484{
485 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
486 where
487 D: Deserializer<'de>,
488 {
489 Deserialize::deserialize(deserializer).map(Mutex::new)
490 }
491}
492
493/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
494/// dropped (falls out of scope), the lock will be unlocked.
495///
496/// The data protected by the mutex can be accessed through this guard via its
497/// `Deref` and `DerefMut` implementations.
498#[clippy::has_significant_drop]
499#[must_use = "if unused the Mutex will immediately unlock"]
500pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> {
501 mutex: &'a Mutex<R, T>,
502 marker: PhantomData<(&'a mut T, R::GuardMarker)>,
503}
504
505unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {}
506
507impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
508 /// Returns a reference to the original `Mutex` object.
509 pub fn mutex(s: &Self) -> &'a Mutex<R, T> {
510 s.mutex
511 }
512
513 /// Makes a new `MappedMutexGuard` for a component of the locked data.
514 ///
515 /// This operation cannot fail as the `MutexGuard` passed
516 /// in already locked the mutex.
517 ///
518 /// This is an associated function that needs to be
519 /// used as `MutexGuard::map(...)`. A method would interfere with methods of
520 /// the same name on the contents of the locked data.
521 #[inline]
522 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
523 where
524 F: FnOnce(&mut T) -> &mut U,
525 {
526 let raw = &s.mutex.raw;
527 let data = f(unsafe { &mut *s.mutex.data.get() });
528 mem::forget(s);
529 MappedMutexGuard {
530 raw,
531 data,
532 marker: PhantomData,
533 }
534 }
535
536 /// Attempts to make a new `MappedMutexGuard` for a component of the
537 /// locked data. The original guard is returned if the closure returns `None`.
538 ///
539 /// This operation cannot fail as the `MutexGuard` passed
540 /// in already locked the mutex.
541 ///
542 /// This is an associated function that needs to be
543 /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of
544 /// the same name on the contents of the locked data.
545 #[inline]
546 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
547 where
548 F: FnOnce(&mut T) -> Option<&mut U>,
549 {
550 let raw = &s.mutex.raw;
551 let data = match f(unsafe { &mut *s.mutex.data.get() }) {
552 Some(data) => data,
553 None => return Err(s),
554 };
555 mem::forget(s);
556 Ok(MappedMutexGuard {
557 raw,
558 data,
559 marker: PhantomData,
560 })
561 }
562
563 /// Temporarily unlocks the mutex to execute the given function.
564 ///
565 /// This is safe because `&mut` guarantees that there exist no other
566 /// references to the data protected by the mutex.
567 #[inline]
568 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
569 where
570 F: FnOnce() -> U,
571 {
572 // Safety: A MutexGuard always holds the lock.
573 unsafe {
574 s.mutex.raw.unlock();
575 }
576 defer!(s.mutex.raw.lock());
577 f()
578 }
579
580 /// Leaks the mutex guard and returns a mutable reference to the data
581 /// protected by the mutex.
582 ///
583 /// This will leave the `Mutex` in a locked state.
584 #[inline]
585 pub fn leak(s: Self) -> &'a mut T {
586 let r = unsafe { &mut *s.mutex.data.get() };
587 mem::forget(s);
588 r
589 }
590}
591
592impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
593 /// Unlocks the mutex using a fair unlock protocol.
594 ///
595 /// By default, mutexes are unfair and allow the current thread to re-lock
596 /// the mutex before another has the chance to acquire the lock, even if
597 /// that thread has been blocked on the mutex for a long time. This is the
598 /// default because it allows much higher throughput as it avoids forcing a
599 /// context switch on every mutex unlock. This can result in one thread
600 /// acquiring a mutex many more times than other threads.
601 ///
602 /// However in some cases it can be beneficial to ensure fairness by forcing
603 /// the lock to pass on to a waiting thread if there is one. This is done by
604 /// using this method instead of dropping the `MutexGuard` normally.
605 #[inline]
606 pub fn unlock_fair(s: Self) {
607 // Safety: A MutexGuard always holds the lock.
608 unsafe {
609 s.mutex.raw.unlock_fair();
610 }
611 mem::forget(s);
612 }
613
614 /// Temporarily unlocks the mutex to execute the given function.
615 ///
616 /// The mutex is unlocked using a fair unlock protocol.
617 ///
618 /// This is safe because `&mut` guarantees that there exist no other
619 /// references to the data protected by the mutex.
620 #[inline]
621 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
622 where
623 F: FnOnce() -> U,
624 {
625 // Safety: A MutexGuard always holds the lock.
626 unsafe {
627 s.mutex.raw.unlock_fair();
628 }
629 defer!(s.mutex.raw.lock());
630 f()
631 }
632
633 /// Temporarily yields the mutex to a waiting thread if there is one.
634 ///
635 /// This method is functionally equivalent to calling `unlock_fair` followed
636 /// by `lock`, however it can be much more efficient in the case where there
637 /// are no waiting threads.
638 #[inline]
639 pub fn bump(s: &mut Self) {
640 // Safety: A MutexGuard always holds the lock.
641 unsafe {
642 s.mutex.raw.bump();
643 }
644 }
645}
646
647impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> {
648 type Target = T;
649 #[inline]
650 fn deref(&self) -> &T {
651 unsafe { &*self.mutex.data.get() }
652 }
653}
654
655impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> {
656 #[inline]
657 fn deref_mut(&mut self) -> &mut T {
658 unsafe { &mut *self.mutex.data.get() }
659 }
660}
661
662impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> {
663 #[inline]
664 fn drop(&mut self) {
665 // Safety: A MutexGuard always holds the lock.
666 unsafe {
667 self.mutex.raw.unlock();
668 }
669 }
670}
671
672impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> {
673 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
674 fmt::Debug::fmt(&**self, f)
675 }
676}
677
678impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> {
679 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
680 (**self).fmt(f)
681 }
682}
683
684#[cfg(feature = "owning_ref")]
685unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {}
686
687/// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`.
688///
689/// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it
690/// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime.
691#[cfg(feature = "arc_lock")]
692#[clippy::has_significant_drop]
693#[must_use = "if unused the Mutex will immediately unlock"]
694pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> {
695 mutex: Arc<Mutex<R, T>>,
696 marker: PhantomData<*const ()>,
697}
698
699#[cfg(feature = "arc_lock")]
700unsafe impl<R: RawMutex + Send + Sync, T: Send + ?Sized> Send for ArcMutexGuard<R, T> where
701 R::GuardMarker: Send
702{
703}
704#[cfg(feature = "arc_lock")]
705unsafe impl<R: RawMutex + Sync, T: Sync + ?Sized> Sync for ArcMutexGuard<R, T> where
706 R::GuardMarker: Sync
707{
708}
709
710#[cfg(feature = "arc_lock")]
711impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> {
712 /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`.
713 #[inline]
714 pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> {
715 &s.mutex
716 }
717
718 /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`].
719 #[inline]
720 pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> {
721 // Safety: Skip our Drop impl and manually unlock the mutex.
722 let arc = unsafe { ptr::read(&s.mutex) };
723 mem::forget(s);
724 unsafe {
725 arc.raw.unlock();
726 }
727 arc
728 }
729
730 /// Temporarily unlocks the mutex to execute the given function.
731 ///
732 /// This is safe because `&mut` guarantees that there exist no other
733 /// references to the data protected by the mutex.
734 #[inline]
735 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
736 where
737 F: FnOnce() -> U,
738 {
739 // Safety: A MutexGuard always holds the lock.
740 unsafe {
741 s.mutex.raw.unlock();
742 }
743 defer!(s.mutex.raw.lock());
744 f()
745 }
746}
747
748#[cfg(feature = "arc_lock")]
749impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> {
750 /// Unlocks the mutex using a fair unlock protocol.
751 ///
752 /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`].
753 #[inline]
754 pub fn unlock_fair(s: Self) {
755 // Safety: A MutexGuard always holds the lock.
756 unsafe {
757 s.mutex.raw.unlock_fair();
758 }
759
760 // SAFETY: make sure the Arc gets it reference decremented
761 let mut s = ManuallyDrop::new(s);
762 unsafe { ptr::drop_in_place(&mut s.mutex) };
763 }
764
765 /// Temporarily unlocks the mutex to execute the given function.
766 ///
767 /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`].
768 #[inline]
769 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
770 where
771 F: FnOnce() -> U,
772 {
773 // Safety: A MutexGuard always holds the lock.
774 unsafe {
775 s.mutex.raw.unlock_fair();
776 }
777 defer!(s.mutex.raw.lock());
778 f()
779 }
780
781 /// Temporarily yields the mutex to a waiting thread if there is one.
782 ///
783 /// This is functionally identical to the `bump` method on [`MutexGuard`].
784 #[inline]
785 pub fn bump(s: &mut Self) {
786 // Safety: A MutexGuard always holds the lock.
787 unsafe {
788 s.mutex.raw.bump();
789 }
790 }
791}
792
793#[cfg(feature = "arc_lock")]
794impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> {
795 type Target = T;
796 #[inline]
797 fn deref(&self) -> &T {
798 unsafe { &*self.mutex.data.get() }
799 }
800}
801
802#[cfg(feature = "arc_lock")]
803impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> {
804 #[inline]
805 fn deref_mut(&mut self) -> &mut T {
806 unsafe { &mut *self.mutex.data.get() }
807 }
808}
809
810#[cfg(feature = "arc_lock")]
811impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> {
812 #[inline]
813 fn drop(&mut self) {
814 // Safety: A MutexGuard always holds the lock.
815 unsafe {
816 self.mutex.raw.unlock();
817 }
818 }
819}
820
821/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
822/// subfield of the protected data.
823///
824/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
825/// former doesn't support temporarily unlocking and re-locking, since that
826/// could introduce soundness issues if the locked object is modified by another
827/// thread.
828#[clippy::has_significant_drop]
829#[must_use = "if unused the Mutex will immediately unlock"]
830pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> {
831 raw: &'a R,
832 data: *mut T,
833 marker: PhantomData<&'a mut T>,
834}
835
836unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync
837 for MappedMutexGuard<'a, R, T>
838{
839}
840unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send + 'a> Send for MappedMutexGuard<'a, R, T> where
841 R::GuardMarker: Send
842{
843}
844
845impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
846 /// Makes a new `MappedMutexGuard` for a component of the locked data.
847 ///
848 /// This operation cannot fail as the `MappedMutexGuard` passed
849 /// in already locked the mutex.
850 ///
851 /// This is an associated function that needs to be
852 /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of
853 /// the same name on the contents of the locked data.
854 #[inline]
855 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
856 where
857 F: FnOnce(&mut T) -> &mut U,
858 {
859 let raw = s.raw;
860 let data = f(unsafe { &mut *s.data });
861 mem::forget(s);
862 MappedMutexGuard {
863 raw,
864 data,
865 marker: PhantomData,
866 }
867 }
868
869 /// Attempts to make a new `MappedMutexGuard` for a component of the
870 /// locked data. The original guard is returned if the closure returns `None`.
871 ///
872 /// This operation cannot fail as the `MappedMutexGuard` passed
873 /// in already locked the mutex.
874 ///
875 /// This is an associated function that needs to be
876 /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of
877 /// the same name on the contents of the locked data.
878 #[inline]
879 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
880 where
881 F: FnOnce(&mut T) -> Option<&mut U>,
882 {
883 let raw = s.raw;
884 let data = match f(unsafe { &mut *s.data }) {
885 Some(data) => data,
886 None => return Err(s),
887 };
888 mem::forget(s);
889 Ok(MappedMutexGuard {
890 raw,
891 data,
892 marker: PhantomData,
893 })
894 }
895}
896
897impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
898 /// Unlocks the mutex using a fair unlock protocol.
899 ///
900 /// By default, mutexes are unfair and allow the current thread to re-lock
901 /// the mutex before another has the chance to acquire the lock, even if
902 /// that thread has been blocked on the mutex for a long time. This is the
903 /// default because it allows much higher throughput as it avoids forcing a
904 /// context switch on every mutex unlock. This can result in one thread
905 /// acquiring a mutex many more times than other threads.
906 ///
907 /// However in some cases it can be beneficial to ensure fairness by forcing
908 /// the lock to pass on to a waiting thread if there is one. This is done by
909 /// using this method instead of dropping the `MutexGuard` normally.
910 #[inline]
911 pub fn unlock_fair(s: Self) {
912 // Safety: A MutexGuard always holds the lock.
913 unsafe {
914 s.raw.unlock_fair();
915 }
916 mem::forget(s);
917 }
918}
919
920impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> {
921 type Target = T;
922 #[inline]
923 fn deref(&self) -> &T {
924 unsafe { &*self.data }
925 }
926}
927
928impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> {
929 #[inline]
930 fn deref_mut(&mut self) -> &mut T {
931 unsafe { &mut *self.data }
932 }
933}
934
935impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> {
936 #[inline]
937 fn drop(&mut self) {
938 // Safety: A MappedMutexGuard always holds the lock.
939 unsafe {
940 self.raw.unlock();
941 }
942 }
943}
944
945impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> {
946 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
947 fmt::Debug::fmt(&**self, f)
948 }
949}
950
951impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
952 for MappedMutexGuard<'a, R, T>
953{
954 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
955 (**self).fmt(f)
956 }
957}
958
959#[cfg(feature = "owning_ref")]
960unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {}
961