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