std/sync/nonpoison/mutex.rs
1use crate::cell::UnsafeCell;
2use crate::fmt;
3use crate::marker::PhantomData;
4use crate::mem::{self, ManuallyDrop};
5use crate::ops::{Deref, DerefMut};
6use crate::ptr::NonNull;
7use crate::sync::nonpoison::{TryLockResult, WouldBlock};
8use crate::sys::sync as sys;
9
10/// A mutual exclusion primitive useful for protecting shared data that does not keep track of
11/// lock poisoning.
12///
13/// For more information about mutexes, check out the documentation for the poisoning variant of
14/// this lock at [`poison::Mutex`].
15///
16/// [`poison::Mutex`]: crate::sync::poison::Mutex
17///
18/// # Examples
19///
20/// Note that this `Mutex` does **not** propagate threads that panic while holding the lock via
21/// poisoning. If you need this functionality, see [`poison::Mutex`].
22///
23/// ```
24/// #![feature(nonpoison_mutex)]
25///
26/// use std::thread;
27/// use std::sync::{Arc, nonpoison::Mutex};
28///
29/// let mutex = Arc::new(Mutex::new(0u32));
30/// let mut handles = Vec::new();
31///
32/// for n in 0..10 {
33/// let m = Arc::clone(&mutex);
34/// let handle = thread::spawn(move || {
35/// let mut guard = m.lock();
36/// *guard += 1;
37/// panic!("panic from thread {n} {guard}")
38/// });
39/// handles.push(handle);
40/// }
41///
42/// for h in handles {
43/// let _ = h.join();
44/// }
45///
46/// println!("Finished, locked {} times", mutex.lock());
47/// ```
48#[unstable(feature = "nonpoison_mutex", issue = "134645")]
49#[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonMutex")]
50pub struct Mutex<#[rustc_assert_variance(invariant)] T: ?Sized> {
51 inner: sys::Mutex,
52 data: UnsafeCell<T>,
53}
54
55/// `T` must be `Send` for a [`Mutex`] to be `Send` because it is possible to acquire
56/// the owned `T` from the `Mutex` via [`into_inner`].
57///
58/// [`into_inner`]: Mutex::into_inner
59#[unstable(feature = "nonpoison_mutex", issue = "134645")]
60unsafe impl<T: ?Sized + Send> Send for Mutex<T> {}
61
62/// `T` must be `Send` for [`Mutex`] to be `Sync`.
63/// This ensures that the protected data can be accessed safely from multiple threads
64/// without causing data races or other unsafe behavior.
65///
66/// [`Mutex<T>`] provides mutable access to `T` to one thread at a time. However, it's essential
67/// for `T` to be `Send` because it's not safe for non-`Send` structures to be accessed in
68/// this manner. For instance, consider [`Rc`], a non-atomic reference counted smart pointer,
69/// which is not `Send`. With `Rc`, we can have multiple copies pointing to the same heap
70/// allocation with a non-atomic reference count. If we were to use `Mutex<Rc<_>>`, it would
71/// only protect one instance of `Rc` from shared access, leaving other copies vulnerable
72/// to potential data races.
73///
74/// Also note that it is not necessary for `T` to be `Sync` as `&T` is only made available
75/// to one thread at a time if `T` is not `Sync`.
76///
77/// [`Rc`]: crate::rc::Rc
78#[unstable(feature = "nonpoison_mutex", issue = "134645")]
79unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {}
80
81/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
82/// dropped (falls out of scope), the lock will be unlocked.
83///
84/// The data protected by the mutex can be accessed through this guard via its
85/// [`Deref`] and [`DerefMut`] implementations.
86///
87/// This structure is created by the [`lock`] and [`try_lock`] methods on
88/// [`Mutex`].
89///
90/// [`lock`]: Mutex::lock
91/// [`try_lock`]: Mutex::try_lock
92#[must_use = "if unused the Mutex will immediately unlock"]
93#[must_not_suspend = "holding a MutexGuard across suspend \
94 points can cause deadlocks, delays, \
95 and cause Futures to not implement `Send`"]
96#[unstable(feature = "nonpoison_mutex", issue = "134645")]
97#[clippy::has_significant_drop]
98#[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonMutexGuard")]
99pub struct MutexGuard<
100 #[rustc_assert_variance(covariant)] 'a,
101 #[rustc_assert_variance(invariant)] T: ?Sized + 'a,
102> {
103 lock: &'a Mutex<T>,
104}
105
106/// A [`MutexGuard`] is not `Send` to maximize platform portability.
107///
108/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to
109/// release mutex locks on the same thread they were acquired.
110/// For this reason, [`MutexGuard`] must not implement `Send` to prevent it being dropped from
111/// another thread.
112#[unstable(feature = "nonpoison_mutex", issue = "134645")]
113impl<T: ?Sized> !Send for MutexGuard<'_, T> {}
114
115/// `T` must be `Sync` for a [`MutexGuard<T>`] to be `Sync`
116/// because it is possible to get a `&T` from `&MutexGuard` (via `Deref`).
117#[unstable(feature = "nonpoison_mutex", issue = "134645")]
118unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {}
119
120/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
121/// subfield of the protected data. When this structure is dropped (falls out
122/// of scope), the lock will be unlocked.
123///
124/// The main difference between `MappedMutexGuard` and [`MutexGuard`] is that the
125/// former cannot be used with [`Condvar`], since that could introduce soundness issues if the
126/// locked object is modified by another thread while the `Mutex` is unlocked.
127///
128/// The data protected by the mutex can be accessed through this guard via its
129/// [`Deref`] and [`DerefMut`] implementations.
130///
131/// This structure is created by the [`map`] and [`filter_map`] methods on
132/// [`MutexGuard`].
133///
134/// [`map`]: MutexGuard::map
135/// [`filter_map`]: MutexGuard::filter_map
136/// [`Condvar`]: crate::sync::nonpoison::Condvar
137#[must_use = "if unused the Mutex will immediately unlock"]
138#[must_not_suspend = "holding a MappedMutexGuard across suspend \
139 points can cause deadlocks, delays, \
140 and cause Futures to not implement `Send`"]
141#[unstable(feature = "mapped_lock_guards", issue = "117108")]
142// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
143#[clippy::has_significant_drop]
144pub struct MappedMutexGuard<
145 #[rustc_assert_variance(covariant)] 'a,
146 #[rustc_assert_variance(invariant)] T: ?Sized + 'a,
147> {
148 // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a
149 // `MappedMutexGuard` argument doesn't hold uniqueness for its whole scope, only until it drops.
150 // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field
151 // below for the correct variance over `T` (invariance).
152 data: NonNull<T>,
153 inner: &'a sys::Mutex,
154 _variance: PhantomData<&'a mut T>,
155}
156
157#[unstable(feature = "mapped_lock_guards", issue = "117108")]
158// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
159impl<T: ?Sized> !Send for MappedMutexGuard<'_, T> {}
160#[unstable(feature = "mapped_lock_guards", issue = "117108")]
161// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
162unsafe impl<T: ?Sized + Sync> Sync for MappedMutexGuard<'_, T> {}
163
164impl<T> Mutex<T> {
165 /// Creates a new mutex in an unlocked state ready for use.
166 ///
167 /// # Examples
168 ///
169 /// ```
170 /// #![feature(nonpoison_mutex)]
171 ///
172 /// use std::sync::nonpoison::Mutex;
173 ///
174 /// let mutex = Mutex::new(0);
175 /// ```
176 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
177 #[inline]
178 pub const fn new(t: T) -> Mutex<T> {
179 Mutex { inner: sys::Mutex::new(), data: UnsafeCell::new(t) }
180 }
181
182 /// Returns the contained value by cloning it.
183 ///
184 /// # Examples
185 ///
186 /// ```
187 /// #![feature(nonpoison_mutex)]
188 /// #![feature(lock_value_accessors)]
189 ///
190 /// use std::sync::nonpoison::Mutex;
191 ///
192 /// let mut mutex = Mutex::new(7);
193 ///
194 /// assert_eq!(mutex.get_cloned(), 7);
195 /// ```
196 #[unstable(feature = "lock_value_accessors", issue = "133407")]
197 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
198 pub fn get_cloned(&self) -> T
199 where
200 T: Clone,
201 {
202 self.lock().clone()
203 }
204
205 /// Sets the contained value.
206 ///
207 /// # Examples
208 ///
209 /// ```
210 /// #![feature(nonpoison_mutex)]
211 /// #![feature(lock_value_accessors)]
212 ///
213 /// use std::sync::nonpoison::Mutex;
214 ///
215 /// let mut mutex = Mutex::new(7);
216 ///
217 /// assert_eq!(mutex.get_cloned(), 7);
218 /// mutex.set(11);
219 /// assert_eq!(mutex.get_cloned(), 11);
220 /// ```
221 #[unstable(feature = "lock_value_accessors", issue = "133407")]
222 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
223 pub fn set(&self, value: T) {
224 if mem::needs_drop::<T>() {
225 // If the contained value has a non-trivial destructor, we
226 // call that destructor after the lock has been released.
227 drop(self.replace(value))
228 } else {
229 *self.lock() = value;
230 }
231 }
232
233 /// Replaces the contained value with `value`, and returns the old contained value.
234 ///
235 /// # Examples
236 ///
237 /// ```
238 /// #![feature(nonpoison_mutex)]
239 /// #![feature(lock_value_accessors)]
240 ///
241 /// use std::sync::nonpoison::Mutex;
242 ///
243 /// let mut mutex = Mutex::new(7);
244 ///
245 /// assert_eq!(mutex.replace(11), 7);
246 /// assert_eq!(mutex.get_cloned(), 11);
247 /// ```
248 #[unstable(feature = "lock_value_accessors", issue = "133407")]
249 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
250 pub fn replace(&self, value: T) -> T {
251 let mut guard = self.lock();
252 mem::replace(&mut *guard, value)
253 }
254}
255
256impl<T: ?Sized> Mutex<T> {
257 /// Acquires a mutex, blocking the current thread until it is able to do so.
258 ///
259 /// This function will block the local thread until it is available to acquire
260 /// the mutex. Upon returning, the thread is the only thread with the lock
261 /// held. An RAII guard is returned to allow scoped unlock of the lock. When
262 /// the guard goes out of scope, the mutex will be unlocked.
263 ///
264 /// The exact behavior on locking a mutex in the thread which already holds
265 /// the lock is left unspecified. However, this function will not return on
266 /// the second call (it might panic or deadlock, for example).
267 ///
268 /// # Panics
269 ///
270 /// This function might panic when called if the lock is already held by
271 /// the current thread.
272 ///
273 /// # Examples
274 ///
275 /// ```
276 /// #![feature(nonpoison_mutex)]
277 ///
278 /// use std::sync::{Arc, nonpoison::Mutex};
279 /// use std::thread;
280 ///
281 /// let mutex = Arc::new(Mutex::new(0));
282 /// let c_mutex = Arc::clone(&mutex);
283 ///
284 /// thread::spawn(move || {
285 /// *c_mutex.lock() = 10;
286 /// }).join().expect("`thread::spawn` should not fail");
287 /// assert_eq!(*mutex.lock(), 10);
288 /// ```
289 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
290 pub fn lock(&self) -> MutexGuard<'_, T> {
291 unsafe {
292 self.inner.lock();
293 MutexGuard::new(self)
294 }
295 }
296
297 /// Attempts to acquire this lock.
298 ///
299 /// This function does not block. If the lock could not be acquired at this time, then
300 /// [`WouldBlock`] is returned. Otherwise, an RAII guard is returned.
301 ///
302 /// The lock will be unlocked when the guard is dropped.
303 ///
304 /// # Errors
305 ///
306 /// If the mutex could not be acquired because it is already locked, then this call will return
307 /// the [`WouldBlock`] error.
308 ///
309 /// # Examples
310 ///
311 /// ```
312 /// use std::sync::{Arc, Mutex};
313 /// use std::thread;
314 ///
315 /// let mutex = Arc::new(Mutex::new(0));
316 /// let c_mutex = Arc::clone(&mutex);
317 ///
318 /// thread::spawn(move || {
319 /// let mut lock = c_mutex.try_lock();
320 /// if let Ok(ref mut mutex) = lock {
321 /// **mutex = 10;
322 /// } else {
323 /// println!("try_lock failed");
324 /// }
325 /// }).join().expect("`thread::spawn` should not fail");
326 /// assert_eq!(*mutex.lock().unwrap(), 10);
327 /// ```
328 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
329 pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> {
330 unsafe { if self.inner.try_lock() { Ok(MutexGuard::new(self)) } else { Err(WouldBlock) } }
331 }
332
333 /// Consumes this mutex, returning the underlying data.
334 ///
335 /// # Examples
336 ///
337 /// ```
338 /// #![feature(nonpoison_mutex)]
339 ///
340 /// use std::sync::nonpoison::Mutex;
341 ///
342 /// let mutex = Mutex::new(0);
343 /// assert_eq!(mutex.into_inner(), 0);
344 /// ```
345 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
346 pub fn into_inner(self) -> T
347 where
348 T: Sized,
349 {
350 self.data.into_inner()
351 }
352
353 /// Returns a mutable reference to the underlying data.
354 ///
355 /// Since this call borrows the `Mutex` mutably, no actual locking needs to
356 /// take place -- the mutable borrow statically guarantees no locks exist.
357 ///
358 /// # Examples
359 ///
360 /// ```
361 /// #![feature(nonpoison_mutex)]
362 ///
363 /// use std::sync::nonpoison::Mutex;
364 ///
365 /// let mut mutex = Mutex::new(0);
366 /// *mutex.get_mut() = 10;
367 /// assert_eq!(*mutex.lock(), 10);
368 /// ```
369 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
370 pub fn get_mut(&mut self) -> &mut T {
371 self.data.get_mut()
372 }
373
374 /// Returns a raw pointer to the underlying data.
375 ///
376 /// The returned pointer is always non-null and properly aligned, but it is
377 /// the user's responsibility to ensure that any reads and writes through it
378 /// are properly synchronized to avoid data races, and that it is not read
379 /// or written through after the mutex is dropped.
380 #[unstable(feature = "mutex_data_ptr", issue = "140368")]
381 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
382 pub const fn data_ptr(&self) -> *mut T {
383 self.data.get()
384 }
385
386 /// Acquires the mutex and provides mutable access to the underlying data by passing
387 /// a mutable reference to the given closure.
388 ///
389 /// This method acquires the lock, calls the provided closure with a mutable reference
390 /// to the data, and returns the result of the closure. The lock is released after
391 /// the closure completes, even if it panics.
392 ///
393 /// # Examples
394 ///
395 /// ```
396 /// #![feature(lock_value_accessors, nonpoison_mutex)]
397 ///
398 /// use std::sync::nonpoison::Mutex;
399 ///
400 /// let mutex = Mutex::new(2);
401 ///
402 /// let result = mutex.with_mut(|data| {
403 /// *data += 3;
404 ///
405 /// *data + 5
406 /// });
407 ///
408 /// assert_eq!(*mutex.lock(), 5);
409 /// assert_eq!(result, 10);
410 /// ```
411 #[unstable(feature = "lock_value_accessors", issue = "133407")]
412 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
413 pub fn with_mut<F, R>(&self, f: F) -> R
414 where
415 F: FnOnce(&mut T) -> R,
416 {
417 f(&mut self.lock())
418 }
419}
420
421#[unstable(feature = "nonpoison_mutex", issue = "134645")]
422impl<T> From<T> for Mutex<T> {
423 /// Creates a new mutex in an unlocked state ready for use.
424 /// This is equivalent to [`Mutex::new`].
425 fn from(t: T) -> Self {
426 Mutex::new(t)
427 }
428}
429
430#[unstable(feature = "nonpoison_mutex", issue = "134645")]
431impl<T: Default> Default for Mutex<T> {
432 /// Creates a `Mutex<T>`, with the `Default` value for T.
433 fn default() -> Mutex<T> {
434 Mutex::new(Default::default())
435 }
436}
437
438#[unstable(feature = "nonpoison_mutex", issue = "134645")]
439impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441 let mut d = f.debug_struct("Mutex");
442 match self.try_lock() {
443 Ok(guard) => {
444 d.field("data", &&*guard);
445 }
446 Err(WouldBlock) => {
447 d.field("data", &"<locked>");
448 }
449 }
450 d.finish_non_exhaustive()
451 }
452}
453
454impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
455 unsafe fn new(lock: &'mutex Mutex<T>) -> MutexGuard<'mutex, T> {
456 MutexGuard { lock }
457 }
458}
459
460#[unstable(feature = "nonpoison_mutex", issue = "134645")]
461impl<T: ?Sized> Deref for MutexGuard<'_, T> {
462 type Target = T;
463
464 fn deref(&self) -> &T {
465 unsafe { &*self.lock.data.get() }
466 }
467}
468
469#[unstable(feature = "nonpoison_mutex", issue = "134645")]
470impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
471 fn deref_mut(&mut self) -> &mut T {
472 unsafe { &mut *self.lock.data.get() }
473 }
474}
475
476#[unstable(feature = "nonpoison_mutex", issue = "134645")]
477impl<T: ?Sized> Drop for MutexGuard<'_, T> {
478 #[inline]
479 fn drop(&mut self) {
480 unsafe {
481 self.lock.inner.unlock();
482 }
483 }
484}
485
486#[unstable(feature = "nonpoison_mutex", issue = "134645")]
487impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
488 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
489 fmt::Debug::fmt(&**self, f)
490 }
491}
492
493#[unstable(feature = "nonpoison_mutex", issue = "134645")]
494impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
495 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
496 (**self).fmt(f)
497 }
498}
499
500/// For use in [`nonpoison::condvar`](super::condvar).
501pub(super) fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
502 &guard.lock.inner
503}
504
505impl<'a, T: ?Sized> MutexGuard<'a, T> {
506 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g.
507 /// an enum variant.
508 ///
509 /// The `Mutex` is already locked, so this cannot fail.
510 ///
511 /// This is an associated function that needs to be used as
512 /// `MutexGuard::map(...)`. A method would interfere with methods of the
513 /// same name on the contents of the `MutexGuard` used through `Deref`.
514 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
515 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
516 pub fn map<U, F>(orig: Self, f: F) -> MappedMutexGuard<'a, U>
517 where
518 F: FnOnce(&mut T) -> &mut U,
519 U: ?Sized,
520 {
521 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
522 // was created, and have been upheld throughout `map` and/or `filter_map`.
523 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
524 // passed to it. If the closure panics, the guard will be dropped.
525 let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
526 let orig = ManuallyDrop::new(orig);
527 MappedMutexGuard { data, inner: &orig.lock.inner, _variance: PhantomData }
528 }
529
530 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data. The
531 /// original guard is returned as an `Err(...)` if the closure returns
532 /// `None`.
533 ///
534 /// The `Mutex` is already locked, so this cannot fail.
535 ///
536 /// This is an associated function that needs to be used as
537 /// `MutexGuard::filter_map(...)`. A method would interfere with methods of the
538 /// same name on the contents of the `MutexGuard` used through `Deref`.
539 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
540 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
541 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
542 where
543 F: FnOnce(&mut T) -> Option<&mut U>,
544 U: ?Sized,
545 {
546 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
547 // was created, and have been upheld throughout `map` and/or `filter_map`.
548 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
549 // passed to it. If the closure panics, the guard will be dropped.
550 match f(unsafe { &mut *orig.lock.data.get() }) {
551 Some(data) => {
552 let data = NonNull::from(data);
553 let orig = ManuallyDrop::new(orig);
554 Ok(MappedMutexGuard { data, inner: &orig.lock.inner, _variance: PhantomData })
555 }
556 None => Err(orig),
557 }
558 }
559}
560
561#[unstable(feature = "mapped_lock_guards", issue = "117108")]
562impl<T: ?Sized> Deref for MappedMutexGuard<'_, T> {
563 type Target = T;
564
565 fn deref(&self) -> &T {
566 unsafe { self.data.as_ref() }
567 }
568}
569
570#[unstable(feature = "mapped_lock_guards", issue = "117108")]
571impl<T: ?Sized> DerefMut for MappedMutexGuard<'_, T> {
572 fn deref_mut(&mut self) -> &mut T {
573 unsafe { self.data.as_mut() }
574 }
575}
576
577#[unstable(feature = "mapped_lock_guards", issue = "117108")]
578impl<T: ?Sized> Drop for MappedMutexGuard<'_, T> {
579 #[inline]
580 fn drop(&mut self) {
581 unsafe {
582 self.inner.unlock();
583 }
584 }
585}
586
587#[unstable(feature = "mapped_lock_guards", issue = "117108")]
588impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'_, T> {
589 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
590 fmt::Debug::fmt(&**self, f)
591 }
592}
593
594#[unstable(feature = "mapped_lock_guards", issue = "117108")]
595impl<T: ?Sized + fmt::Display> fmt::Display for MappedMutexGuard<'_, T> {
596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
597 (**self).fmt(f)
598 }
599}
600
601impl<'a, T: ?Sized> MappedMutexGuard<'a, T> {
602 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g.
603 /// an enum variant.
604 ///
605 /// The `Mutex` is already locked, so this cannot fail.
606 ///
607 /// This is an associated function that needs to be used as
608 /// `MappedMutexGuard::map(...)`. A method would interfere with methods of the
609 /// same name on the contents of the `MutexGuard` used through `Deref`.
610 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
611 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
612 pub fn map<U, F>(mut orig: Self, f: F) -> MappedMutexGuard<'a, U>
613 where
614 F: FnOnce(&mut T) -> &mut U,
615 U: ?Sized,
616 {
617 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
618 // was created, and have been upheld throughout `map` and/or `filter_map`.
619 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
620 // passed to it. If the closure panics, the guard will be dropped.
621 let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
622 let orig = ManuallyDrop::new(orig);
623 MappedMutexGuard { data, inner: orig.inner, _variance: PhantomData }
624 }
625
626 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data. The
627 /// original guard is returned as an `Err(...)` if the closure returns
628 /// `None`.
629 ///
630 /// The `Mutex` is already locked, so this cannot fail.
631 ///
632 /// This is an associated function that needs to be used as
633 /// `MappedMutexGuard::filter_map(...)`. A method would interfere with methods of the
634 /// same name on the contents of the `MutexGuard` used through `Deref`.
635 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
636 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
637 pub fn filter_map<U, F>(mut orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
638 where
639 F: FnOnce(&mut T) -> Option<&mut U>,
640 U: ?Sized,
641 {
642 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
643 // was created, and have been upheld throughout `map` and/or `filter_map`.
644 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
645 // passed to it. If the closure panics, the guard will be dropped.
646 match f(unsafe { orig.data.as_mut() }) {
647 Some(data) => {
648 let data = NonNull::from(data);
649 let orig = ManuallyDrop::new(orig);
650 Ok(MappedMutexGuard { data, inner: orig.inner, _variance: PhantomData })
651 }
652 None => Err(orig),
653 }
654 }
655}