lock_api/mutex.rs
1use core::cell::UnsafeCell;
2use core::fmt;
3use core::marker::PhantomData;
4use core::mem;
5use core::ops::{Deref, DerefMut};
6
7use crate::guard::{ExclusiveGuardData, abort_on_panic};
8
9#[cfg(feature = "arc_lock")]
10use alloc::sync::Arc;
11use core::mem::ManuallyDrop;
12use core::ptr;
13
14#[cfg(feature = "owning_ref")]
15use owning_ref::StableAddress;
16
17#[cfg(feature = "serde")]
18use serde::{Deserialize, Deserializer, Serialize, Serializer};
19
20/// Basic operations for a mutex.
21///
22/// Types implementing this trait can be used by `Mutex` to form a safe and
23/// fully-functioning mutex type.
24///
25/// # Safety
26///
27/// Implementations must provide mutual exclusion, with acquire semantics on
28/// successful locking and release semantics on unlocking. These requirements
29/// also apply to subtraits.
30///
31/// Each successful lock operation returns guard state representing ownership of
32/// the mutex. Operations on a locked mutex must receive the state for that
33/// acquisition. Unlocking consumes the state.
34///
35/// Guard state may unlock the mutex when dropped, but forgetting it must be
36/// safe. A caller with exclusive ownership of the mutex object may move or drop
37/// it even while it is locked; this must also be safe.
38///
39/// If a lock operation unwinds, it must not leave the caller holding a new
40/// acquisition. If an operation consuming guard state unwinds, it must release
41/// the acquisition represented by that state, even if it changed or re-acquired
42/// the lock before panicking. Neither case may release an acquisition held
43/// independently of the call.
44pub unsafe trait RawMutex {
45 /// Initial value for an unlocked mutex.
46 // A “non-constant” const item is a legacy way to supply an initialized value to downstream
47 // static items. Can hopefully be replaced with `const fn new() -> Self` at some point.
48 #[allow(clippy::declare_interior_mutable_const)]
49 const INIT: Self;
50
51 /// Per-acquisition state stored in the lock guard.
52 ///
53 /// This type also determines whether guards are `Send` and `Sync`.
54 /// Stateless implementations can use [`GuardSend`](crate::GuardSend) or
55 /// [`GuardNoSend`](crate::GuardNoSend).
56 type Guard;
57
58 /// Acquires this mutex, blocking the current thread until it is able to do so.
59 fn lock(&self) -> Self::Guard;
60
61 /// Attempts to acquire this mutex without blocking. Returns the guard state
62 /// if the lock was successfully acquired and `None` otherwise.
63 fn try_lock(&self) -> Option<Self::Guard>;
64
65 /// Unlocks this mutex.
66 ///
67 /// # Safety
68 ///
69 /// This method may only be called if the mutex is held in the current context, i.e. it must
70 /// be given the state returned by a successful call to [`lock`], [`try_lock`], [`try_lock_for`] or [`try_lock_until`].
71 ///
72 /// [`lock`]: RawMutex::lock
73 /// [`try_lock`]: RawMutex::try_lock
74 /// [`try_lock_for`]: RawMutexTimed::try_lock_for
75 /// [`try_lock_until`]: RawMutexTimed::try_lock_until
76 unsafe fn unlock(&self, guard: Self::Guard);
77
78 /// Checks whether the mutex is currently locked.
79 ///
80 /// The result is a momentary snapshot and may be stale by the time it is
81 /// returned.
82 fn is_locked(&self) -> bool;
83}
84
85/// Additional methods for mutexes which support fair unlocking.
86///
87/// Fair unlocking means that a lock is handed directly over to the next waiting
88/// thread if there is one, without giving other threads the opportunity to
89/// "steal" the lock in the meantime. This is typically slower than unfair
90/// unlocking, but may be necessary in certain circumstances.
91///
92/// # Safety
93///
94/// Implementations must uphold the safety requirements of [`RawMutex`] for
95/// the additional methods provided by this trait.
96pub unsafe trait RawMutexFair: RawMutex {
97 /// Unlocks this mutex using a fair unlock protocol.
98 ///
99 /// # Safety
100 ///
101 /// This method may only be called if the mutex is held in the current context, see
102 /// the documentation of [`unlock`](RawMutex::unlock).
103 unsafe fn unlock_fair(&self, guard: Self::Guard);
104
105 /// Temporarily yields the mutex to a waiting thread if there is one.
106 ///
107 /// This method is functionally equivalent to calling `unlock_fair` followed
108 /// by `lock`, however it can be much more efficient in the case where there
109 /// are no waiting threads.
110 ///
111 /// # Safety
112 ///
113 /// This method may only be called if the mutex is held in the current context, see
114 /// the documentation of [`unlock`](RawMutex::unlock).
115 ///
116 /// Implementations may unwind only with the mutex held and valid guard
117 /// state restored. If restoration fails, they must abort.
118 ///
119 /// # Aborts
120 ///
121 /// The default implementation aborts if re-locking the mutex panics.
122 unsafe fn bump(&self, guard: &mut Self::Guard) {
123 // Move the state out, then restore it on both normal return and unwind.
124 let state = unsafe { ptr::read(guard) };
125 defer!(abort_on_panic(|| unsafe { ptr::write(guard, self.lock()) }));
126 unsafe { self.unlock_fair(state) };
127 }
128}
129
130/// Additional methods for mutexes which support locking with timeouts.
131///
132/// The `Duration` and `Instant` types are specified as associated types so that
133/// this trait is usable even in `no_std` environments.
134///
135/// # Safety
136///
137/// Implementations must uphold the safety requirements of [`RawMutex`] for
138/// the additional methods provided by this trait.
139pub unsafe trait RawMutexTimed: RawMutex {
140 /// Duration type used for `try_lock_for`.
141 type Duration;
142
143 /// Instant type used for `try_lock_until`.
144 type Instant;
145
146 /// Attempts to acquire this lock until a timeout is reached.
147 ///
148 /// A successful operation may return early. An unsuccessful operation must
149 /// not return before the timeout, but may return later due to scheduling or
150 /// platform-specific behavior.
151 fn try_lock_for(&self, timeout: Self::Duration) -> Option<Self::Guard>;
152
153 /// Attempts to acquire this lock until a timeout is reached.
154 ///
155 /// A successful operation may return early. An unsuccessful operation must
156 /// not return before the timeout, but may return later due to scheduling or
157 /// platform-specific behavior.
158 fn try_lock_until(&self, timeout: Self::Instant) -> Option<Self::Guard>;
159}
160
161/// A mutual exclusion primitive useful for protecting shared data.
162///
163/// This mutex will block threads waiting for the lock to become available. The
164/// mutex can also be statically initialized or created via a `new`
165/// constructor. Each mutex has a type parameter which represents the data that
166/// it is protecting. The data can only be accessed through the RAII guards
167/// returned from `lock` and `try_lock`, which guarantees that the data is only
168/// ever accessed when the mutex is locked.
169pub struct Mutex<R, T: ?Sized> {
170 raw: R,
171 data: UnsafeCell<T>,
172}
173
174unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {}
175
176impl<R: RawMutex, T> Mutex<R, T> {
177 /// Creates a new mutex in an unlocked state ready for use.
178 #[inline]
179 pub const fn new(val: T) -> Mutex<R, T> {
180 Mutex {
181 raw: R::INIT,
182 data: UnsafeCell::new(val),
183 }
184 }
185
186 /// Consumes this mutex, returning the underlying data.
187 #[inline]
188 pub fn into_inner(self) -> T {
189 self.data.into_inner()
190 }
191}
192
193impl<R, T> Mutex<R, T> {
194 /// Creates a new mutex based on a pre-existing raw mutex.
195 #[inline]
196 pub const fn from_raw(raw_mutex: R, val: T) -> Mutex<R, T> {
197 Mutex {
198 raw: raw_mutex,
199 data: UnsafeCell::new(val),
200 }
201 }
202
203 /// Consumes this mutex, returning the underlying data and raw mutex.
204 #[inline]
205 pub fn into_inner_with_raw(self) -> (R, T) {
206 (self.raw, self.data.into_inner())
207 }
208}
209
210impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
211 /// Creates a new `MutexGuard` without checking if the mutex is locked.
212 ///
213 /// # Safety
214 ///
215 /// This method must only be called if the thread logically holds the lock.
216 ///
217 /// Calling this function when a guard has already been produced is undefined behavior unless
218 /// the guard was forgotten with `mem::forget`.
219 ///
220 /// The caller must ensure that existing references to the protected data
221 /// remain valid when the returned guard is used or dropped. In particular,
222 /// the returned guard must not permit accesses that conflict with existing
223 /// references.
224 ///
225 /// `guard` must be the state for this acquisition of this lock.
226 #[inline]
227 pub unsafe fn make_guard_unchecked(&self, guard: R::Guard) -> MutexGuard<'_, R, T> {
228 MutexGuard {
229 mutex: self,
230 marker: PhantomData,
231 guard: ManuallyDrop::new(guard),
232 }
233 }
234
235 /// Acquires a mutex, blocking the current thread until it is able to do so.
236 ///
237 /// This function will block the local thread until it is available to acquire
238 /// the mutex. Upon returning, the thread is the only thread with the mutex
239 /// held. An RAII guard is returned to allow scoped unlock of the lock. When
240 /// the guard goes out of scope, the mutex will be unlocked.
241 ///
242 /// The exact behavior when the current thread tries to acquire a mutex it
243 /// already holds is left unspecified. The second call will not return; it
244 /// may panic or deadlock, for example.
245 ///
246 /// # Panics
247 ///
248 /// This function may panic if the lock is already held by the current
249 /// thread.
250 #[inline]
251 #[track_caller]
252 pub fn lock(&self) -> MutexGuard<'_, R, T> {
253 let guard = self.raw.lock();
254 // SAFETY: The lock is held, as required.
255 unsafe { self.make_guard_unchecked(guard) }
256 }
257
258 /// Attempts to acquire this lock.
259 ///
260 /// If the lock could not be acquired at this time, then `None` is returned.
261 /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
262 /// guard is dropped.
263 ///
264 /// This function does not block.
265 #[inline]
266 #[track_caller]
267 pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> {
268 if let Some(guard) = self.raw.try_lock() {
269 // SAFETY: The lock is held, as required.
270 Some(unsafe { self.make_guard_unchecked(guard) })
271 } else {
272 None
273 }
274 }
275
276 /// Returns a mutable reference to the underlying data.
277 ///
278 /// Since this call borrows the `Mutex` mutably, no actual locking needs to
279 /// take place -- the mutable borrow statically guarantees no new locks can
280 /// be acquired while the reference exists. This method does not clear a
281 /// lock previously abandoned by forgetting a [`MutexGuard`].
282 #[inline]
283 pub const fn get_mut(&mut self) -> &mut T {
284 self.data.get_mut()
285 }
286
287 /// Checks whether the mutex is currently locked.
288 ///
289 /// The result is a momentary snapshot and may be stale by the time it is
290 /// returned.
291 #[inline]
292 #[track_caller]
293 pub fn is_locked(&self) -> bool {
294 self.raw.is_locked()
295 }
296
297 /// Forcibly unlocks the mutex.
298 ///
299 /// This is useful when the raw acquisition state is managed separately,
300 /// for example when dealing with FFI.
301 ///
302 /// # Safety
303 ///
304 /// The current context must hold the lock using the supplied acquisition
305 /// state, with no live guard responsible for unlocking it.
306 /// Behavior is undefined if a mutex is unlocked when not locked.
307 ///
308 /// The caller must ensure that releasing the lock does not invalidate any
309 /// outstanding references to the protected data. Any subsequent access
310 /// through previously obtained pointers must be properly synchronized.
311 ///
312 /// `guard` must be the state for this acquisition of this lock.
313 #[inline]
314 #[track_caller]
315 pub unsafe fn force_unlock(&self, guard: R::Guard) {
316 unsafe { self.raw.unlock(guard) };
317 }
318
319 /// Returns the underlying raw mutex object.
320 ///
321 /// Note that you will most likely need to import the `RawMutex` trait from
322 /// `lock_api` to be able to call functions on the raw mutex.
323 ///
324 /// # Safety
325 ///
326 /// The caller must ensure that operations on the raw lock preserve the
327 /// validity of all live guards and references to the protected data.
328 /// A guard must not be used or dropped while its lock is released, and any
329 /// access through previously obtained pointers must be properly synchronized.
330 #[inline]
331 pub unsafe fn raw(&self) -> &R {
332 &self.raw
333 }
334
335 /// Returns a raw pointer to the underlying data.
336 ///
337 /// The returned pointer is always non-null and properly aligned, but the
338 /// caller must ensure that reads and writes through it are properly
339 /// synchronized and that the pointer is not used after the mutex is
340 /// dropped.
341 #[inline]
342 pub const fn data_ptr(&self) -> *mut T {
343 self.data.get()
344 }
345
346 /// Creates a new `ArcMutexGuard` without checking if the mutex is locked.
347 ///
348 /// # Safety
349 ///
350 /// This method must only be called if the thread logically holds the lock.
351 ///
352 /// Calling this function when a guard has already been produced is undefined behavior unless
353 /// the guard was forgotten with `mem::forget`.
354 ///
355 /// The caller must ensure that existing references to the protected data
356 /// remain valid when the returned guard is used or dropped. In particular,
357 /// the returned guard must not permit accesses that conflict with existing
358 /// references.
359 ///
360 /// `guard` must be the state for this acquisition of this lock.
361 #[cfg(feature = "arc_lock")]
362 #[inline]
363 unsafe fn make_arc_guard_unchecked(self: &Arc<Self>, guard: R::Guard) -> ArcMutexGuard<R, T> {
364 ArcMutexGuard {
365 mutex: self.clone(),
366 data_marker: PhantomData,
367 guard: ManuallyDrop::new(guard),
368 }
369 }
370
371 /// Acquires a lock through an `Arc`.
372 ///
373 /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc`
374 /// and the resulting mutex guard owns a clone of the `Arc` instead of borrowing the lock.
375 #[cfg(feature = "arc_lock")]
376 #[inline]
377 #[track_caller]
378 pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
379 let guard = self.raw.lock();
380 // SAFETY: the locking guarantee is upheld
381 unsafe { self.make_arc_guard_unchecked(guard) }
382 }
383
384 /// Attempts to acquire a lock through an `Arc`.
385 ///
386 /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an
387 /// `Arc` and the resulting mutex guard owns a clone of the `Arc` instead of borrowing the lock.
388 #[cfg(feature = "arc_lock")]
389 #[inline]
390 #[track_caller]
391 pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> {
392 if let Some(guard) = self.raw.try_lock() {
393 // SAFETY: locking guarantee is upheld
394 Some(unsafe { self.make_arc_guard_unchecked(guard) })
395 } else {
396 None
397 }
398 }
399}
400
401impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> {
402 /// Forcibly unlocks the mutex using a fair unlock protocol.
403 ///
404 /// This is useful when the raw acquisition state is managed separately,
405 /// for example when dealing with FFI.
406 ///
407 /// # Safety
408 ///
409 /// The current context must hold the lock using the supplied acquisition
410 /// state, with no live guard responsible for unlocking it.
411 /// Behavior is undefined if a mutex is unlocked when not locked.
412 ///
413 /// The caller must ensure that releasing the lock does not invalidate any
414 /// outstanding references to the protected data. Any subsequent access
415 /// through previously obtained pointers must be properly synchronized.
416 ///
417 /// `guard` must be the state for this acquisition of this lock.
418 #[inline]
419 #[track_caller]
420 pub unsafe fn force_unlock_fair(&self, guard: R::Guard) {
421 unsafe { self.raw.unlock_fair(guard) };
422 }
423}
424
425impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
426 /// Attempts to acquire this lock until a timeout is reached.
427 ///
428 /// If the lock could not be acquired before the timeout expired, then
429 /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
430 /// be unlocked when the guard is dropped.
431 ///
432 /// A successful operation may return early. An unsuccessful operation will
433 /// not return before the timeout, but may return later due to scheduling or
434 /// platform-specific behavior.
435 #[inline]
436 #[track_caller]
437 pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> {
438 if let Some(guard) = self.raw.try_lock_for(timeout) {
439 // SAFETY: The lock is held, as required.
440 Some(unsafe { self.make_guard_unchecked(guard) })
441 } else {
442 None
443 }
444 }
445
446 /// Attempts to acquire this lock until a timeout is reached.
447 ///
448 /// If the lock could not be acquired before the timeout expired, then
449 /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
450 /// be unlocked when the guard is dropped.
451 ///
452 /// A successful operation may return early. An unsuccessful operation will
453 /// not return before the timeout, but may return later due to scheduling or
454 /// platform-specific behavior.
455 #[inline]
456 #[track_caller]
457 pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> {
458 if let Some(guard) = self.raw.try_lock_until(timeout) {
459 // SAFETY: The lock is held, as required.
460 Some(unsafe { self.make_guard_unchecked(guard) })
461 } else {
462 None
463 }
464 }
465
466 /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
467 ///
468 /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an
469 /// `Arc` and the resulting mutex guard owns a clone of the `Arc` instead of borrowing the lock.
470 ///
471 /// See [`try_lock_for`](Self::try_lock_for) for timeout behavior.
472 #[cfg(feature = "arc_lock")]
473 #[inline]
474 #[track_caller]
475 pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> {
476 if let Some(guard) = self.raw.try_lock_for(timeout) {
477 // SAFETY: locking guarantee is upheld
478 Some(unsafe { self.make_arc_guard_unchecked(guard) })
479 } else {
480 None
481 }
482 }
483
484 /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
485 ///
486 /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of
487 /// an `Arc` and the resulting mutex guard owns a clone of the `Arc` instead of borrowing the lock.
488 ///
489 /// See [`try_lock_until`](Self::try_lock_until) for timeout behavior.
490 #[cfg(feature = "arc_lock")]
491 #[inline]
492 #[track_caller]
493 pub fn try_lock_arc_until(
494 self: &Arc<Self>,
495 timeout: R::Instant,
496 ) -> Option<ArcMutexGuard<R, T>> {
497 if let Some(guard) = self.raw.try_lock_until(timeout) {
498 // SAFETY: locking guarantee is upheld
499 Some(unsafe { self.make_arc_guard_unchecked(guard) })
500 } else {
501 None
502 }
503 }
504}
505
506impl<R: RawMutex, T: Default> Default for Mutex<R, T> {
507 #[inline]
508 fn default() -> Mutex<R, T> {
509 Mutex::new(Default::default())
510 }
511}
512
513impl<R: RawMutex, T> From<T> for Mutex<R, T> {
514 #[inline]
515 fn from(t: T) -> Mutex<R, T> {
516 Mutex::new(t)
517 }
518}
519
520impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> {
521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 match self.try_lock() {
523 Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
524 None => {
525 struct LockedPlaceholder;
526 impl fmt::Debug for LockedPlaceholder {
527 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528 f.write_str("<locked>")
529 }
530 }
531
532 f.debug_struct("Mutex")
533 .field("data", &LockedPlaceholder)
534 .finish()
535 }
536 }
537 }
538}
539
540// Copied and modified from serde
541#[cfg(feature = "serde")]
542impl<R, T> Serialize for Mutex<R, T>
543where
544 R: RawMutex,
545 T: Serialize + ?Sized,
546{
547 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
548 where
549 S: Serializer,
550 {
551 self.lock().serialize(serializer)
552 }
553}
554
555#[cfg(feature = "serde")]
556impl<'de, R, T> Deserialize<'de> for Mutex<R, T>
557where
558 R: RawMutex,
559 T: Deserialize<'de>,
560{
561 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
562 where
563 D: Deserializer<'de>,
564 {
565 Deserialize::deserialize(deserializer).map(Mutex::new)
566 }
567}
568
569/// An RAII guard which unlocks the mutex when dropped.
570///
571/// The data protected by the mutex can be accessed through this guard via its
572/// [`Deref`] and [`DerefMut`] implementations.
573///
574/// This structure is created by the [`lock`](Mutex::lock) and
575/// [`try_lock`](Mutex::try_lock) methods on [`Mutex`].
576#[clippy::has_significant_drop]
577#[must_use = "if unused the Mutex will immediately unlock"]
578pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> {
579 mutex: &'a Mutex<R, T>,
580 marker: PhantomData<&'a mut T>,
581 // The raw unlock operation consumes this state in Drop.
582 pub(crate) guard: ManuallyDrop<R::Guard>,
583}
584
585impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
586 /// Returns a reference to the original `Mutex` object.
587 pub fn mutex(s: &Self) -> &'a Mutex<R, T> {
588 s.mutex
589 }
590
591 /// Makes a new `MappedMutexGuard` for a component of the locked data.
592 ///
593 /// This is an associated function that needs to be
594 /// used as `MutexGuard::map(...)`. A method would interfere with methods of
595 /// the same name on the contents of the locked data.
596 ///
597 /// # Panics
598 ///
599 /// If `f` panics, the original guard is dropped.
600 #[inline]
601 pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
602 where
603 F: FnOnce(&mut T) -> &mut U,
604 {
605 let raw = &s.mutex.raw;
606 let data = f(unsafe { s.mutex.data.get().as_mut_unchecked() });
607 let guard = unsafe { ptr::read(&s.guard) };
608 mem::forget(s);
609 MappedMutexGuard {
610 raw,
611 data: ExclusiveGuardData::new(data),
612 guard,
613 }
614 }
615
616 /// Attempts to make a new `MappedMutexGuard` for a component of the
617 /// locked data. The original guard is returned if the closure returns `None`.
618 ///
619 /// This is an associated function that needs to be
620 /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of
621 /// the same name on the contents of the locked data.
622 ///
623 /// # Panics
624 ///
625 /// If `f` panics, the original guard is dropped.
626 #[inline]
627 pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
628 where
629 F: FnOnce(&mut T) -> Option<&mut U>,
630 {
631 let raw = &s.mutex.raw;
632 let Some(data) = f(unsafe { s.mutex.data.get().as_mut_unchecked() }) else {
633 return Err(s);
634 };
635 let guard = unsafe { ptr::read(&s.guard) };
636 mem::forget(s);
637 Ok(MappedMutexGuard {
638 raw,
639 data: ExclusiveGuardData::new(data),
640 guard,
641 })
642 }
643
644 /// Attempts to make a new `MappedMutexGuard` for a component of the
645 /// locked data. The original guard is returned alongside arbitrary user data
646 /// if the closure returns `Err`.
647 ///
648 /// This is an associated function that needs to be
649 /// used as `MutexGuard::try_map_or_err(...)`. A method would interfere with methods of
650 /// the same name on the contents of the locked data.
651 ///
652 /// # Panics
653 ///
654 /// If `f` panics, the original guard is dropped.
655 #[inline]
656 pub fn try_map_or_err<U: ?Sized, F, E>(
657 s: Self,
658 f: F,
659 ) -> Result<MappedMutexGuard<'a, R, U>, (Self, E)>
660 where
661 F: FnOnce(&mut T) -> Result<&mut U, E>,
662 {
663 let raw = &s.mutex.raw;
664 let data = match f(unsafe { s.mutex.data.get().as_mut_unchecked() }) {
665 Ok(data) => data,
666 Err(e) => return Err((s, e)),
667 };
668 let guard = unsafe { ptr::read(&s.guard) };
669 mem::forget(s);
670 Ok(MappedMutexGuard {
671 raw,
672 data: ExclusiveGuardData::new(data),
673 guard,
674 })
675 }
676
677 /// Temporarily unlocks the mutex to execute the given function.
678 ///
679 /// This is safe because `&mut` guarantees that there exist no other
680 /// references to the data protected by the mutex.
681 ///
682 /// # Aborts
683 ///
684 /// Aborts if re-locking the mutex panics.
685 #[inline]
686 #[track_caller]
687 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
688 where
689 F: FnOnce() -> U,
690 {
691 // SAFETY: Valid mutex state; cleanup restores it before reuse or drop.
692 let state = unsafe { ManuallyDrop::take(&mut s.guard) };
693 // A panicking raw unlock releases the acquisition too.
694 defer!(abort_on_panic(
695 || s.guard = ManuallyDrop::new(s.mutex.raw.lock())
696 ));
697 // SAFETY: The state belongs to the acquisition held by this guard.
698 unsafe { s.mutex.raw.unlock(state) };
699 f()
700 }
701
702 /// Leaks the mutex guard and returns a mutable reference to the data
703 /// protected by the mutex.
704 ///
705 /// This will leave the `Mutex` in a locked state.
706 #[inline]
707 pub fn leak(s: Self) -> &'a mut T {
708 let r = unsafe { s.mutex.data.get().as_mut_unchecked() };
709 mem::forget(s);
710 r
711 }
712}
713
714impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
715 /// Unlocks the mutex using a fair unlock protocol.
716 ///
717 /// A fair unlock hands the mutex directly to a waiting thread instead of
718 /// allowing another thread to steal it. This can prevent starvation, but may
719 /// reduce throughput by forcing a context switch.
720 #[inline]
721 #[track_caller]
722 pub fn unlock_fair(s: Self) {
723 let mut s = ManuallyDrop::new(s);
724 // Safety: A MutexGuard always holds the lock.
725 unsafe {
726 s.mutex.raw.unlock_fair(ManuallyDrop::take(&mut s.guard));
727 }
728 }
729
730 /// Temporarily unlocks the mutex to execute the given function.
731 ///
732 /// The mutex is unlocked using a fair unlock protocol.
733 ///
734 /// This is safe because `&mut` guarantees that there exist no other
735 /// references to the data protected by the mutex.
736 ///
737 /// # Aborts
738 ///
739 /// Aborts if re-locking the mutex panics.
740 #[inline]
741 #[track_caller]
742 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
743 where
744 F: FnOnce() -> U,
745 {
746 // SAFETY: Valid mutex state; cleanup restores it before reuse or drop.
747 let state = unsafe { ManuallyDrop::take(&mut s.guard) };
748 // A panicking raw unlock releases the acquisition too.
749 defer!(abort_on_panic(
750 || s.guard = ManuallyDrop::new(s.mutex.raw.lock())
751 ));
752 // SAFETY: The state belongs to the acquisition held by this guard.
753 unsafe { s.mutex.raw.unlock_fair(state) };
754 f()
755 }
756
757 /// Temporarily yields the mutex to a waiting thread if there is one.
758 ///
759 /// This method is functionally equivalent to calling `unlock_fair` followed
760 /// by `lock`, however it can be much more efficient in the case where there
761 /// are no waiting threads.
762 #[inline]
763 #[track_caller]
764 pub fn bump(s: &mut Self) {
765 // SAFETY: Valid mutex state; bump preserves ownership even on unwind.
766 unsafe { s.mutex.raw.bump(&mut s.guard) };
767 }
768}
769
770impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> {
771 type Target = T;
772 #[inline]
773 fn deref(&self) -> &T {
774 unsafe { self.mutex.data.get().as_ref_unchecked() }
775 }
776}
777
778impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> {
779 #[inline]
780 fn deref_mut(&mut self) -> &mut T {
781 unsafe { self.mutex.data.get().as_mut_unchecked() }
782 }
783}
784
785impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> {
786 #[inline]
787 fn drop(&mut self) {
788 // Safety: A MutexGuard always holds the lock.
789 unsafe {
790 self.mutex.raw.unlock(ManuallyDrop::take(&mut self.guard));
791 }
792 }
793}
794
795impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> {
796 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797 fmt::Debug::fmt(&**self, f)
798 }
799}
800
801impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> {
802 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
803 (**self).fmt(f)
804 }
805}
806
807#[cfg(feature = "owning_ref")]
808unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {}
809
810/// An RAII mutex guard returned by the `Arc` locking operations on [`Mutex`].
811///
812/// Unlike [`MutexGuard`], this guard owns the [`Arc`] used to unlock the mutex
813/// instead of borrowing the mutex, so its lifetime is not tied to a lock
814/// reference.
815#[cfg(feature = "arc_lock")]
816#[clippy::has_significant_drop]
817#[must_use = "if unused the Mutex will immediately unlock"]
818pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> {
819 // The raw unlock operation consumes this state in Drop.
820 guard: ManuallyDrop<R::Guard>,
821 mutex: Arc<Mutex<R, T>>,
822 data_marker: PhantomData<T>,
823}
824
825#[cfg(feature = "arc_lock")]
826impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> {
827 /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`.
828 #[inline]
829 pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> {
830 &s.mutex
831 }
832
833 /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`].
834 #[inline]
835 #[track_caller]
836 pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> {
837 let mut s = ManuallyDrop::new(s);
838 // SAFETY: ManuallyDrop lets us move the Arc into a local that drops on unwind.
839 let mutex = unsafe { ptr::read(&s.mutex) };
840 // SAFETY: Valid mutex state; ManuallyDrop prevents a second release.
841 let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
842 // SAFETY: The state belongs to the acquisition held by this guard.
843 unsafe { mutex.raw.unlock(guard) };
844 mutex
845 }
846
847 /// Temporarily unlocks the mutex to execute the given function.
848 ///
849 /// This is safe because `&mut` guarantees that there exist no other
850 /// references to the data protected by the mutex.
851 ///
852 /// # Aborts
853 ///
854 /// Aborts if re-locking the mutex panics.
855 #[inline]
856 #[track_caller]
857 pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
858 where
859 F: FnOnce() -> U,
860 {
861 // SAFETY: Valid mutex state; cleanup restores it before reuse or drop.
862 let state = unsafe { ManuallyDrop::take(&mut s.guard) };
863 // A panicking raw unlock releases the acquisition too.
864 defer!(abort_on_panic(
865 || s.guard = ManuallyDrop::new(s.mutex.raw.lock())
866 ));
867 // SAFETY: The state belongs to the acquisition held by this guard.
868 unsafe { s.mutex.raw.unlock(state) };
869 f()
870 }
871}
872
873#[cfg(feature = "arc_lock")]
874impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> {
875 /// Unlocks the mutex using a fair unlock protocol.
876 ///
877 /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`].
878 #[inline]
879 #[track_caller]
880 pub fn unlock_fair(s: Self) {
881 drop(Self::into_arc_fair(s));
882 }
883
884 /// Unlocks the mutex using a fair unlock protocol and returns the `Arc` that was held by the [`ArcMutexGuard`].
885 #[inline]
886 pub fn into_arc_fair(s: Self) -> Arc<Mutex<R, T>> {
887 let mut s = ManuallyDrop::new(s);
888 // SAFETY: ManuallyDrop lets us move the Arc into a local that drops on unwind.
889 let mutex = unsafe { ptr::read(&s.mutex) };
890 // SAFETY: Valid mutex state; ManuallyDrop prevents a second release.
891 let guard = unsafe { ManuallyDrop::take(&mut s.guard) };
892 // SAFETY: The state belongs to the acquisition held by this guard.
893 unsafe { mutex.raw.unlock_fair(guard) };
894 mutex
895 }
896
897 /// Temporarily unlocks the mutex to execute the given function.
898 ///
899 /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`].
900 ///
901 /// # Aborts
902 ///
903 /// Aborts if re-locking the mutex panics.
904 #[inline]
905 #[track_caller]
906 pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
907 where
908 F: FnOnce() -> U,
909 {
910 // SAFETY: Valid mutex state; cleanup restores it before reuse or drop.
911 let state = unsafe { ManuallyDrop::take(&mut s.guard) };
912 // A panicking raw unlock releases the acquisition too.
913 defer!(abort_on_panic(
914 || s.guard = ManuallyDrop::new(s.mutex.raw.lock())
915 ));
916 // SAFETY: The state belongs to the acquisition held by this guard.
917 unsafe { s.mutex.raw.unlock_fair(state) };
918 f()
919 }
920
921 /// Temporarily yields the mutex to a waiting thread if there is one.
922 ///
923 /// This is functionally identical to the `bump` method on [`MutexGuard`].
924 #[inline]
925 #[track_caller]
926 pub fn bump(s: &mut Self) {
927 // SAFETY: Valid mutex state; bump preserves ownership even on unwind.
928 unsafe { s.mutex.raw.bump(&mut s.guard) };
929 }
930}
931
932#[cfg(feature = "arc_lock")]
933impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> {
934 type Target = T;
935 #[inline]
936 fn deref(&self) -> &T {
937 unsafe { self.mutex.data.get().as_ref_unchecked() }
938 }
939}
940
941#[cfg(feature = "arc_lock")]
942impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> {
943 #[inline]
944 fn deref_mut(&mut self) -> &mut T {
945 unsafe { self.mutex.data.get().as_mut_unchecked() }
946 }
947}
948
949#[cfg(feature = "arc_lock")]
950impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> {
951 #[inline]
952 fn drop(&mut self) {
953 // Safety: An ArcMutexGuard always holds the lock.
954 unsafe {
955 self.mutex.raw.unlock(ManuallyDrop::take(&mut self.guard));
956 }
957 }
958}
959
960/// An RAII mutex guard returned by [`MutexGuard::map`], which can point to a
961/// subfield of the protected data.
962///
963/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
964/// former doesn't support temporarily unlocking and re-locking, since that
965/// could introduce soundness issues if the locked object is modified by another
966/// thread.
967///
968/// This structure is created by the [`map`](MutexGuard::map) and
969/// [`try_map`](MutexGuard::try_map), and
970/// [`try_map_or_err`](MutexGuard::try_map_or_err) functions on [`MutexGuard`].
971#[clippy::has_significant_drop]
972#[must_use = "if unused the Mutex will immediately unlock"]
973pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized + 'a> {
974 raw: &'a R,
975 data: ExclusiveGuardData<T>,
976 // The raw unlock operation consumes this state in Drop.
977 guard: ManuallyDrop<R::Guard>,
978}
979
980impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
981 /// Makes a new `MappedMutexGuard` for a component of the locked data.
982 ///
983 /// This is an associated function that needs to be
984 /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of
985 /// the same name on the contents of the locked data.
986 ///
987 /// # Panics
988 ///
989 /// If `f` panics, the original guard is dropped.
990 #[inline]
991 pub fn map<U: ?Sized, F>(mut s: Self, f: F) -> MappedMutexGuard<'a, R, U>
992 where
993 F: FnOnce(&mut T) -> &mut U,
994 {
995 let raw = s.raw;
996 let data = ExclusiveGuardData::new(f(unsafe { s.data.as_mut() }));
997 let guard = unsafe { ptr::read(&s.guard) };
998 mem::forget(s);
999 MappedMutexGuard { raw, data, guard }
1000 }
1001
1002 /// Attempts to make a new `MappedMutexGuard` for a component of the
1003 /// locked data. The original guard is returned if the closure returns `None`.
1004 ///
1005 /// This is an associated function that needs to be
1006 /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of
1007 /// the same name on the contents of the locked data.
1008 ///
1009 /// # Panics
1010 ///
1011 /// If `f` panics, the original guard is dropped.
1012 #[inline]
1013 pub fn try_map<U: ?Sized, F>(mut s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
1014 where
1015 F: FnOnce(&mut T) -> Option<&mut U>,
1016 {
1017 let raw = s.raw;
1018 let Some(data) = f(unsafe { s.data.as_mut() }) else {
1019 return Err(s);
1020 };
1021 let data = ExclusiveGuardData::new(data);
1022 let guard = unsafe { ptr::read(&s.guard) };
1023 mem::forget(s);
1024 Ok(MappedMutexGuard { raw, data, guard })
1025 }
1026
1027 /// Attempts to make a new `MappedMutexGuard` for a component of the
1028 /// locked data. The original guard is returned alongside arbitrary user data
1029 /// if the closure returns `Err`.
1030 ///
1031 /// This is an associated function that needs to be
1032 /// used as `MappedMutexGuard::try_map_or_err(...)`. A method would interfere with methods of
1033 /// the same name on the contents of the locked data.
1034 ///
1035 /// # Panics
1036 ///
1037 /// If `f` panics, the original guard is dropped.
1038 #[inline]
1039 pub fn try_map_or_err<U: ?Sized, F, E>(
1040 mut s: Self,
1041 f: F,
1042 ) -> Result<MappedMutexGuard<'a, R, U>, (Self, E)>
1043 where
1044 F: FnOnce(&mut T) -> Result<&mut U, E>,
1045 {
1046 let raw = s.raw;
1047 let data = match f(unsafe { s.data.as_mut() }) {
1048 Ok(data) => data,
1049 Err(e) => return Err((s, e)),
1050 };
1051 let data = ExclusiveGuardData::new(data);
1052 let guard = unsafe { ptr::read(&s.guard) };
1053 mem::forget(s);
1054 Ok(MappedMutexGuard { raw, data, guard })
1055 }
1056}
1057
1058impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
1059 /// Unlocks the mutex using a fair unlock protocol.
1060 ///
1061 /// A fair unlock hands the mutex directly to a waiting thread instead of
1062 /// allowing another thread to steal it. This can prevent starvation, but may
1063 /// reduce throughput by forcing a context switch.
1064 #[inline]
1065 #[track_caller]
1066 pub fn unlock_fair(s: Self) {
1067 let mut s = ManuallyDrop::new(s);
1068 // Safety: A MappedMutexGuard always holds the lock.
1069 unsafe {
1070 s.raw.unlock_fair(ManuallyDrop::take(&mut s.guard));
1071 }
1072 }
1073}
1074
1075impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> {
1076 type Target = T;
1077 #[inline]
1078 fn deref(&self) -> &T {
1079 unsafe { self.data.as_ref() }
1080 }
1081}
1082
1083impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> {
1084 #[inline]
1085 fn deref_mut(&mut self) -> &mut T {
1086 unsafe { self.data.as_mut() }
1087 }
1088}
1089
1090impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> {
1091 #[inline]
1092 fn drop(&mut self) {
1093 // Safety: A MappedMutexGuard always holds the lock.
1094 unsafe {
1095 self.raw.unlock(ManuallyDrop::take(&mut self.guard));
1096 }
1097 }
1098}
1099
1100impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> {
1101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1102 fmt::Debug::fmt(&**self, f)
1103 }
1104}
1105
1106impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
1107 for MappedMutexGuard<'a, R, T>
1108{
1109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1110 (**self).fmt(f)
1111 }
1112}
1113
1114#[cfg(feature = "owning_ref")]
1115unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {}