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