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<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<'a, T: ?Sized + 'a> {
100 lock: &'a Mutex<T>,
101}
102
103/// A [`MutexGuard`] is not `Send` to maximize platform portability.
104///
105/// On platforms that use POSIX threads (commonly referred to as pthreads) there is a requirement to
106/// release mutex locks on the same thread they were acquired.
107/// For this reason, [`MutexGuard`] must not implement `Send` to prevent it being dropped from
108/// another thread.
109#[unstable(feature = "nonpoison_mutex", issue = "134645")]
110impl<T: ?Sized> !Send for MutexGuard<'_, T> {}
111
112/// `T` must be `Sync` for a [`MutexGuard<T>`] to be `Sync`
113/// because it is possible to get a `&T` from `&MutexGuard` (via `Deref`).
114#[unstable(feature = "nonpoison_mutex", issue = "134645")]
115unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {}
116
117/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
118/// subfield of the protected data. When this structure is dropped (falls out
119/// of scope), the lock will be unlocked.
120///
121/// The main difference between `MappedMutexGuard` and [`MutexGuard`] is that the
122/// former cannot be used with [`Condvar`], since that could introduce soundness issues if the
123/// locked object is modified by another thread while the `Mutex` is unlocked.
124///
125/// The data protected by the mutex can be accessed through this guard via its
126/// [`Deref`] and [`DerefMut`] implementations.
127///
128/// This structure is created by the [`map`] and [`filter_map`] methods on
129/// [`MutexGuard`].
130///
131/// [`map`]: MutexGuard::map
132/// [`filter_map`]: MutexGuard::filter_map
133/// [`Condvar`]: crate::sync::nonpoison::Condvar
134#[must_use = "if unused the Mutex will immediately unlock"]
135#[must_not_suspend = "holding a MappedMutexGuard across suspend \
136 points can cause deadlocks, delays, \
137 and cause Futures to not implement `Send`"]
138#[unstable(feature = "mapped_lock_guards", issue = "117108")]
139// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
140#[clippy::has_significant_drop]
141pub struct MappedMutexGuard<'a, T: ?Sized + 'a> {
142 // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a
143 // `MappedMutexGuard` argument doesn't hold uniqueness for its whole scope, only until it drops.
144 // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field
145 // below for the correct variance over `T` (invariance).
146 data: NonNull<T>,
147 inner: &'a sys::Mutex,
148 _variance: PhantomData<&'a mut T>,
149}
150
151#[unstable(feature = "mapped_lock_guards", issue = "117108")]
152// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
153impl<T: ?Sized> !Send for MappedMutexGuard<'_, T> {}
154#[unstable(feature = "mapped_lock_guards", issue = "117108")]
155// #[unstable(feature = "nonpoison_mutex", issue = "134645")]
156unsafe impl<T: ?Sized + Sync> Sync for MappedMutexGuard<'_, T> {}
157
158impl<T> Mutex<T> {
159 /// Creates a new mutex in an unlocked state ready for use.
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// #![feature(nonpoison_mutex)]
165 ///
166 /// use std::sync::nonpoison::Mutex;
167 ///
168 /// let mutex = Mutex::new(0);
169 /// ```
170 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
171 #[inline]
172 pub const fn new(t: T) -> Mutex<T> {
173 Mutex { inner: sys::Mutex::new(), data: UnsafeCell::new(t) }
174 }
175
176 /// Returns the contained value by cloning it.
177 ///
178 /// # Examples
179 ///
180 /// ```
181 /// #![feature(nonpoison_mutex)]
182 /// #![feature(lock_value_accessors)]
183 ///
184 /// use std::sync::nonpoison::Mutex;
185 ///
186 /// let mut mutex = Mutex::new(7);
187 ///
188 /// assert_eq!(mutex.get_cloned(), 7);
189 /// ```
190 #[unstable(feature = "lock_value_accessors", issue = "133407")]
191 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
192 pub fn get_cloned(&self) -> T
193 where
194 T: Clone,
195 {
196 self.lock().clone()
197 }
198
199 /// Sets the contained value.
200 ///
201 /// # Examples
202 ///
203 /// ```
204 /// #![feature(nonpoison_mutex)]
205 /// #![feature(lock_value_accessors)]
206 ///
207 /// use std::sync::nonpoison::Mutex;
208 ///
209 /// let mut mutex = Mutex::new(7);
210 ///
211 /// assert_eq!(mutex.get_cloned(), 7);
212 /// mutex.set(11);
213 /// assert_eq!(mutex.get_cloned(), 11);
214 /// ```
215 #[unstable(feature = "lock_value_accessors", issue = "133407")]
216 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
217 pub fn set(&self, value: T) {
218 if mem::needs_drop::<T>() {
219 // If the contained value has a non-trivial destructor, we
220 // call that destructor after the lock has been released.
221 drop(self.replace(value))
222 } else {
223 *self.lock() = value;
224 }
225 }
226
227 /// Replaces the contained value with `value`, and returns the old contained value.
228 ///
229 /// # Examples
230 ///
231 /// ```
232 /// #![feature(nonpoison_mutex)]
233 /// #![feature(lock_value_accessors)]
234 ///
235 /// use std::sync::nonpoison::Mutex;
236 ///
237 /// let mut mutex = Mutex::new(7);
238 ///
239 /// assert_eq!(mutex.replace(11), 7);
240 /// assert_eq!(mutex.get_cloned(), 11);
241 /// ```
242 #[unstable(feature = "lock_value_accessors", issue = "133407")]
243 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
244 pub fn replace(&self, value: T) -> T {
245 let mut guard = self.lock();
246 mem::replace(&mut *guard, value)
247 }
248}
249
250impl<T: ?Sized> Mutex<T> {
251 /// Acquires a mutex, blocking the current thread until it is able to do so.
252 ///
253 /// This function will block the local thread until it is available to acquire
254 /// the mutex. Upon returning, the thread is the only thread with the lock
255 /// held. An RAII guard is returned to allow scoped unlock of the lock. When
256 /// the guard goes out of scope, the mutex will be unlocked.
257 ///
258 /// The exact behavior on locking a mutex in the thread which already holds
259 /// the lock is left unspecified. However, this function will not return on
260 /// the second call (it might panic or deadlock, for example).
261 ///
262 /// # Panics
263 ///
264 /// This function might panic when called if the lock is already held by
265 /// the current thread.
266 ///
267 /// # Examples
268 ///
269 /// ```
270 /// #![feature(nonpoison_mutex)]
271 ///
272 /// use std::sync::{Arc, nonpoison::Mutex};
273 /// use std::thread;
274 ///
275 /// let mutex = Arc::new(Mutex::new(0));
276 /// let c_mutex = Arc::clone(&mutex);
277 ///
278 /// thread::spawn(move || {
279 /// *c_mutex.lock() = 10;
280 /// }).join().expect("thread::spawn failed");
281 /// assert_eq!(*mutex.lock(), 10);
282 /// ```
283 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
284 pub fn lock(&self) -> MutexGuard<'_, T> {
285 unsafe {
286 self.inner.lock();
287 MutexGuard::new(self)
288 }
289 }
290
291 /// Attempts to acquire this lock.
292 ///
293 /// This function does not block. If the lock could not be acquired at this time, then
294 /// [`WouldBlock`] is returned. Otherwise, an RAII guard is returned.
295 ///
296 /// The lock will be unlocked when the guard is dropped.
297 ///
298 /// # Errors
299 ///
300 /// If the mutex could not be acquired because it is already locked, then this call will return
301 /// the [`WouldBlock`] error.
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// use std::sync::{Arc, Mutex};
307 /// use std::thread;
308 ///
309 /// let mutex = Arc::new(Mutex::new(0));
310 /// let c_mutex = Arc::clone(&mutex);
311 ///
312 /// thread::spawn(move || {
313 /// let mut lock = c_mutex.try_lock();
314 /// if let Ok(ref mut mutex) = lock {
315 /// **mutex = 10;
316 /// } else {
317 /// println!("try_lock failed");
318 /// }
319 /// }).join().expect("thread::spawn failed");
320 /// assert_eq!(*mutex.lock().unwrap(), 10);
321 /// ```
322 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
323 pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> {
324 unsafe { if self.inner.try_lock() { Ok(MutexGuard::new(self)) } else { Err(WouldBlock) } }
325 }
326
327 /// Consumes this mutex, returning the underlying data.
328 ///
329 /// # Examples
330 ///
331 /// ```
332 /// #![feature(nonpoison_mutex)]
333 ///
334 /// use std::sync::nonpoison::Mutex;
335 ///
336 /// let mutex = Mutex::new(0);
337 /// assert_eq!(mutex.into_inner(), 0);
338 /// ```
339 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
340 pub fn into_inner(self) -> T
341 where
342 T: Sized,
343 {
344 self.data.into_inner()
345 }
346
347 /// Returns a mutable reference to the underlying data.
348 ///
349 /// Since this call borrows the `Mutex` mutably, no actual locking needs to
350 /// take place -- the mutable borrow statically guarantees no locks exist.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// #![feature(nonpoison_mutex)]
356 ///
357 /// use std::sync::nonpoison::Mutex;
358 ///
359 /// let mut mutex = Mutex::new(0);
360 /// *mutex.get_mut() = 10;
361 /// assert_eq!(*mutex.lock(), 10);
362 /// ```
363 #[unstable(feature = "nonpoison_mutex", issue = "134645")]
364 pub fn get_mut(&mut self) -> &mut T {
365 self.data.get_mut()
366 }
367
368 /// Returns a raw pointer to the underlying data.
369 ///
370 /// The returned pointer is always non-null and properly aligned, but it is
371 /// the user's responsibility to ensure that any reads and writes through it
372 /// are properly synchronized to avoid data races, and that it is not read
373 /// or written through after the mutex is dropped.
374 #[unstable(feature = "mutex_data_ptr", issue = "140368")]
375 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
376 pub fn data_ptr(&self) -> *mut T {
377 self.data.get()
378 }
379}
380
381#[unstable(feature = "nonpoison_mutex", issue = "134645")]
382impl<T> From<T> for Mutex<T> {
383 /// Creates a new mutex in an unlocked state ready for use.
384 /// This is equivalent to [`Mutex::new`].
385 fn from(t: T) -> Self {
386 Mutex::new(t)
387 }
388}
389
390#[unstable(feature = "nonpoison_mutex", issue = "134645")]
391impl<T: ?Sized + Default> Default for Mutex<T> {
392 /// Creates a `Mutex<T>`, with the `Default` value for T.
393 fn default() -> Mutex<T> {
394 Mutex::new(Default::default())
395 }
396}
397
398#[unstable(feature = "nonpoison_mutex", issue = "134645")]
399impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
400 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401 let mut d = f.debug_struct("Mutex");
402 match self.try_lock() {
403 Ok(guard) => {
404 d.field("data", &&*guard);
405 }
406 Err(WouldBlock) => {
407 d.field("data", &"<locked>");
408 }
409 }
410 d.finish_non_exhaustive()
411 }
412}
413
414impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
415 unsafe fn new(lock: &'mutex Mutex<T>) -> MutexGuard<'mutex, T> {
416 return MutexGuard { lock };
417 }
418}
419
420#[unstable(feature = "nonpoison_mutex", issue = "134645")]
421impl<T: ?Sized> Deref for MutexGuard<'_, T> {
422 type Target = T;
423
424 fn deref(&self) -> &T {
425 unsafe { &*self.lock.data.get() }
426 }
427}
428
429#[unstable(feature = "nonpoison_mutex", issue = "134645")]
430impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
431 fn deref_mut(&mut self) -> &mut T {
432 unsafe { &mut *self.lock.data.get() }
433 }
434}
435
436#[unstable(feature = "nonpoison_mutex", issue = "134645")]
437impl<T: ?Sized> Drop for MutexGuard<'_, T> {
438 #[inline]
439 fn drop(&mut self) {
440 unsafe {
441 self.lock.inner.unlock();
442 }
443 }
444}
445
446#[unstable(feature = "nonpoison_mutex", issue = "134645")]
447impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> {
448 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449 fmt::Debug::fmt(&**self, f)
450 }
451}
452
453#[unstable(feature = "nonpoison_mutex", issue = "134645")]
454impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> {
455 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456 (**self).fmt(f)
457 }
458}
459
460/// For use in [`nonpoison::condvar`](super::condvar).
461pub(super) fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
462 &guard.lock.inner
463}
464
465impl<'a, T: ?Sized> MutexGuard<'a, T> {
466 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g.
467 /// an enum variant.
468 ///
469 /// The `Mutex` is already locked, so this cannot fail.
470 ///
471 /// This is an associated function that needs to be used as
472 /// `MutexGuard::map(...)`. A method would interfere with methods of the
473 /// same name on the contents of the `MutexGuard` used through `Deref`.
474 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
475 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
476 pub fn map<U, F>(orig: Self, f: F) -> MappedMutexGuard<'a, U>
477 where
478 F: FnOnce(&mut T) -> &mut U,
479 U: ?Sized,
480 {
481 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
482 // was created, and have been upheld throughout `map` and/or `filter_map`.
483 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
484 // passed to it. If the closure panics, the guard will be dropped.
485 let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() }));
486 let orig = ManuallyDrop::new(orig);
487 MappedMutexGuard { data, inner: &orig.lock.inner, _variance: PhantomData }
488 }
489
490 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data. The
491 /// original guard is returned as an `Err(...)` if the closure returns
492 /// `None`.
493 ///
494 /// The `Mutex` is already locked, so this cannot fail.
495 ///
496 /// This is an associated function that needs to be used as
497 /// `MutexGuard::filter_map(...)`. A method would interfere with methods of the
498 /// same name on the contents of the `MutexGuard` used through `Deref`.
499 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
500 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
501 pub fn filter_map<U, F>(orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
502 where
503 F: FnOnce(&mut T) -> Option<&mut U>,
504 U: ?Sized,
505 {
506 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
507 // was created, and have been upheld throughout `map` and/or `filter_map`.
508 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
509 // passed to it. If the closure panics, the guard will be dropped.
510 match f(unsafe { &mut *orig.lock.data.get() }) {
511 Some(data) => {
512 let data = NonNull::from(data);
513 let orig = ManuallyDrop::new(orig);
514 Ok(MappedMutexGuard { data, inner: &orig.lock.inner, _variance: PhantomData })
515 }
516 None => Err(orig),
517 }
518 }
519}
520
521#[unstable(feature = "mapped_lock_guards", issue = "117108")]
522impl<T: ?Sized> Deref for MappedMutexGuard<'_, T> {
523 type Target = T;
524
525 fn deref(&self) -> &T {
526 unsafe { self.data.as_ref() }
527 }
528}
529
530#[unstable(feature = "mapped_lock_guards", issue = "117108")]
531impl<T: ?Sized> DerefMut for MappedMutexGuard<'_, T> {
532 fn deref_mut(&mut self) -> &mut T {
533 unsafe { self.data.as_mut() }
534 }
535}
536
537#[unstable(feature = "mapped_lock_guards", issue = "117108")]
538impl<T: ?Sized> Drop for MappedMutexGuard<'_, T> {
539 #[inline]
540 fn drop(&mut self) {
541 unsafe {
542 self.inner.unlock();
543 }
544 }
545}
546
547#[unstable(feature = "mapped_lock_guards", issue = "117108")]
548impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'_, T> {
549 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
550 fmt::Debug::fmt(&**self, f)
551 }
552}
553
554#[unstable(feature = "mapped_lock_guards", issue = "117108")]
555impl<T: ?Sized + fmt::Display> fmt::Display for MappedMutexGuard<'_, T> {
556 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
557 (**self).fmt(f)
558 }
559}
560
561impl<'a, T: ?Sized> MappedMutexGuard<'a, T> {
562 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g.
563 /// an enum variant.
564 ///
565 /// The `Mutex` is already locked, so this cannot fail.
566 ///
567 /// This is an associated function that needs to be used as
568 /// `MappedMutexGuard::map(...)`. A method would interfere with methods of the
569 /// same name on the contents of the `MutexGuard` used through `Deref`.
570 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
571 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
572 pub fn map<U, F>(mut orig: Self, f: F) -> MappedMutexGuard<'a, U>
573 where
574 F: FnOnce(&mut T) -> &mut U,
575 U: ?Sized,
576 {
577 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
578 // was created, and have been upheld throughout `map` and/or `filter_map`.
579 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
580 // passed to it. If the closure panics, the guard will be dropped.
581 let data = NonNull::from(f(unsafe { orig.data.as_mut() }));
582 let orig = ManuallyDrop::new(orig);
583 MappedMutexGuard { data, inner: orig.inner, _variance: PhantomData }
584 }
585
586 /// Makes a [`MappedMutexGuard`] for a component of the borrowed data. The
587 /// original guard is returned as an `Err(...)` if the closure returns
588 /// `None`.
589 ///
590 /// The `Mutex` is already locked, so this cannot fail.
591 ///
592 /// This is an associated function that needs to be used as
593 /// `MappedMutexGuard::filter_map(...)`. A method would interfere with methods of the
594 /// same name on the contents of the `MutexGuard` used through `Deref`.
595 #[unstable(feature = "mapped_lock_guards", issue = "117108")]
596 // #[unstable(feature = "nonpoison_mutex", issue = "134645")]
597 pub fn filter_map<U, F>(mut orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self>
598 where
599 F: FnOnce(&mut T) -> Option<&mut U>,
600 U: ?Sized,
601 {
602 // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard
603 // was created, and have been upheld throughout `map` and/or `filter_map`.
604 // The signature of the closure guarantees that it will not "leak" the lifetime of the reference
605 // passed to it. If the closure panics, the guard will be dropped.
606 match f(unsafe { orig.data.as_mut() }) {
607 Some(data) => {
608 let data = NonNull::from(data);
609 let orig = ManuallyDrop::new(orig);
610 Ok(MappedMutexGuard { data, inner: orig.inner, _variance: PhantomData })
611 }
612 None => Err(orig),
613 }
614 }
615}