1 | #[cfg (all(test, not(target_os = "emscripten" )))] |
2 | mod tests; |
3 | |
4 | use crate::cell::UnsafeCell; |
5 | use crate::fmt; |
6 | use crate::marker::PhantomData; |
7 | use crate::mem::ManuallyDrop; |
8 | use crate::ops::{Deref, DerefMut}; |
9 | use crate::ptr::NonNull; |
10 | use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; |
11 | use crate::sys::sync as sys; |
12 | |
13 | /// A mutual exclusion primitive useful for protecting shared data |
14 | /// |
15 | /// This mutex will block threads waiting for the lock to become available. The |
16 | /// mutex can be created via a [`new`] constructor. Each mutex has a type parameter |
17 | /// which represents the data that it is protecting. The data can only be accessed |
18 | /// through the RAII guards returned from [`lock`] and [`try_lock`], which |
19 | /// guarantees that the data is only ever accessed when the mutex is locked. |
20 | /// |
21 | /// # Poisoning |
22 | /// |
23 | /// The mutexes in this module implement a strategy called "poisoning" where a |
24 | /// mutex is considered poisoned whenever a thread panics while holding the |
25 | /// mutex. Once a mutex is poisoned, all other threads are unable to access the |
26 | /// data by default as it is likely tainted (some invariant is not being |
27 | /// upheld). |
28 | /// |
29 | /// For a mutex, this means that the [`lock`] and [`try_lock`] methods return a |
30 | /// [`Result`] which indicates whether a mutex has been poisoned or not. Most |
31 | /// usage of a mutex will simply [`unwrap()`] these results, propagating panics |
32 | /// among threads to ensure that a possibly invalid invariant is not witnessed. |
33 | /// |
34 | /// A poisoned mutex, however, does not prevent all access to the underlying |
35 | /// data. The [`PoisonError`] type has an [`into_inner`] method which will return |
36 | /// the guard that would have otherwise been returned on a successful lock. This |
37 | /// allows access to the data, despite the lock being poisoned. |
38 | /// |
39 | /// [`new`]: Self::new |
40 | /// [`lock`]: Self::lock |
41 | /// [`try_lock`]: Self::try_lock |
42 | /// [`unwrap()`]: Result::unwrap |
43 | /// [`PoisonError`]: super::PoisonError |
44 | /// [`into_inner`]: super::PoisonError::into_inner |
45 | /// |
46 | /// # Examples |
47 | /// |
48 | /// ``` |
49 | /// use std::sync::{Arc, Mutex}; |
50 | /// use std::thread; |
51 | /// use std::sync::mpsc::channel; |
52 | /// |
53 | /// const N: usize = 10; |
54 | /// |
55 | /// // Spawn a few threads to increment a shared variable (non-atomically), and |
56 | /// // let the main thread know once all increments are done. |
57 | /// // |
58 | /// // Here we're using an Arc to share memory among threads, and the data inside |
59 | /// // the Arc is protected with a mutex. |
60 | /// let data = Arc::new(Mutex::new(0)); |
61 | /// |
62 | /// let (tx, rx) = channel(); |
63 | /// for _ in 0..N { |
64 | /// let (data, tx) = (Arc::clone(&data), tx.clone()); |
65 | /// thread::spawn(move || { |
66 | /// // The shared state can only be accessed once the lock is held. |
67 | /// // Our non-atomic increment is safe because we're the only thread |
68 | /// // which can access the shared state when the lock is held. |
69 | /// // |
70 | /// // We unwrap() the return value to assert that we are not expecting |
71 | /// // threads to ever fail while holding the lock. |
72 | /// let mut data = data.lock().unwrap(); |
73 | /// *data += 1; |
74 | /// if *data == N { |
75 | /// tx.send(()).unwrap(); |
76 | /// } |
77 | /// // the lock is unlocked here when `data` goes out of scope. |
78 | /// }); |
79 | /// } |
80 | /// |
81 | /// rx.recv().unwrap(); |
82 | /// ``` |
83 | /// |
84 | /// To recover from a poisoned mutex: |
85 | /// |
86 | /// ``` |
87 | /// use std::sync::{Arc, Mutex}; |
88 | /// use std::thread; |
89 | /// |
90 | /// let lock = Arc::new(Mutex::new(0_u32)); |
91 | /// let lock2 = Arc::clone(&lock); |
92 | /// |
93 | /// let _ = thread::spawn(move || -> () { |
94 | /// // This thread will acquire the mutex first, unwrapping the result of |
95 | /// // `lock` because the lock has not been poisoned. |
96 | /// let _guard = lock2.lock().unwrap(); |
97 | /// |
98 | /// // This panic while holding the lock (`_guard` is in scope) will poison |
99 | /// // the mutex. |
100 | /// panic!(); |
101 | /// }).join(); |
102 | /// |
103 | /// // The lock is poisoned by this point, but the returned result can be |
104 | /// // pattern matched on to return the underlying guard on both branches. |
105 | /// let mut guard = match lock.lock() { |
106 | /// Ok(guard) => guard, |
107 | /// Err(poisoned) => poisoned.into_inner(), |
108 | /// }; |
109 | /// |
110 | /// *guard += 1; |
111 | /// ``` |
112 | /// |
113 | /// To unlock a mutex guard sooner than the end of the enclosing scope, |
114 | /// either create an inner scope or drop the guard manually. |
115 | /// |
116 | /// ``` |
117 | /// use std::sync::{Arc, Mutex}; |
118 | /// use std::thread; |
119 | /// |
120 | /// const N: usize = 3; |
121 | /// |
122 | /// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); |
123 | /// let res_mutex = Arc::new(Mutex::new(0)); |
124 | /// |
125 | /// let mut threads = Vec::with_capacity(N); |
126 | /// (0..N).for_each(|_| { |
127 | /// let data_mutex_clone = Arc::clone(&data_mutex); |
128 | /// let res_mutex_clone = Arc::clone(&res_mutex); |
129 | /// |
130 | /// threads.push(thread::spawn(move || { |
131 | /// // Here we use a block to limit the lifetime of the lock guard. |
132 | /// let result = { |
133 | /// let mut data = data_mutex_clone.lock().unwrap(); |
134 | /// // This is the result of some important and long-ish work. |
135 | /// let result = data.iter().fold(0, |acc, x| acc + x * 2); |
136 | /// data.push(result); |
137 | /// result |
138 | /// // The mutex guard gets dropped here, together with any other values |
139 | /// // created in the critical section. |
140 | /// }; |
141 | /// // The guard created here is a temporary dropped at the end of the statement, i.e. |
142 | /// // the lock would not remain being held even if the thread did some additional work. |
143 | /// *res_mutex_clone.lock().unwrap() += result; |
144 | /// })); |
145 | /// }); |
146 | /// |
147 | /// let mut data = data_mutex.lock().unwrap(); |
148 | /// // This is the result of some important and long-ish work. |
149 | /// let result = data.iter().fold(0, |acc, x| acc + x * 2); |
150 | /// data.push(result); |
151 | /// // We drop the `data` explicitly because it's not necessary anymore and the |
152 | /// // thread still has work to do. This allows other threads to start working on |
153 | /// // the data immediately, without waiting for the rest of the unrelated work |
154 | /// // to be done here. |
155 | /// // |
156 | /// // It's even more important here than in the threads because we `.join` the |
157 | /// // threads after that. If we had not dropped the mutex guard, a thread could |
158 | /// // be waiting forever for it, causing a deadlock. |
159 | /// // As in the threads, a block could have been used instead of calling the |
160 | /// // `drop` function. |
161 | /// drop(data); |
162 | /// // Here the mutex guard is not assigned to a variable and so, even if the |
163 | /// // scope does not end after this line, the mutex is still released: there is |
164 | /// // no deadlock. |
165 | /// *res_mutex.lock().unwrap() += result; |
166 | /// |
167 | /// threads.into_iter().for_each(|thread| { |
168 | /// thread |
169 | /// .join() |
170 | /// .expect("The thread creating or execution failed !" ) |
171 | /// }); |
172 | /// |
173 | /// assert_eq!(*res_mutex.lock().unwrap(), 800); |
174 | /// ``` |
175 | /// |
176 | #[stable (feature = "rust1" , since = "1.0.0" )] |
177 | #[cfg_attr (not(test), rustc_diagnostic_item = "Mutex" )] |
178 | pub struct Mutex<T: ?Sized> { |
179 | inner: sys::Mutex, |
180 | poison: poison::Flag, |
181 | data: UnsafeCell<T>, |
182 | } |
183 | |
184 | // these are the only places where `T: Send` matters; all other |
185 | // functionality works fine on a single thread. |
186 | #[stable (feature = "rust1" , since = "1.0.0" )] |
187 | unsafe impl<T: ?Sized + Send> Send for Mutex<T> {} |
188 | #[stable (feature = "rust1" , since = "1.0.0" )] |
189 | unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {} |
190 | |
191 | /// An RAII implementation of a "scoped lock" of a mutex. When this structure is |
192 | /// dropped (falls out of scope), the lock will be unlocked. |
193 | /// |
194 | /// The data protected by the mutex can be accessed through this guard via its |
195 | /// [`Deref`] and [`DerefMut`] implementations. |
196 | /// |
197 | /// This structure is created by the [`lock`] and [`try_lock`] methods on |
198 | /// [`Mutex`]. |
199 | /// |
200 | /// [`lock`]: Mutex::lock |
201 | /// [`try_lock`]: Mutex::try_lock |
202 | #[must_use = "if unused the Mutex will immediately unlock" ] |
203 | #[must_not_suspend = "holding a MutexGuard across suspend \ |
204 | points can cause deadlocks, delays, \ |
205 | and cause Futures to not implement `Send`" ] |
206 | #[stable (feature = "rust1" , since = "1.0.0" )] |
207 | #[clippy::has_significant_drop] |
208 | #[cfg_attr (not(test), rustc_diagnostic_item = "MutexGuard" )] |
209 | pub struct MutexGuard<'a, T: ?Sized + 'a> { |
210 | lock: &'a Mutex<T>, |
211 | poison: poison::Guard, |
212 | } |
213 | |
214 | #[stable (feature = "rust1" , since = "1.0.0" )] |
215 | impl<T: ?Sized> !Send for MutexGuard<'_, T> {} |
216 | #[stable (feature = "mutexguard" , since = "1.19.0" )] |
217 | unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {} |
218 | |
219 | /// An RAII mutex guard returned by `MutexGuard::map`, which can point to a |
220 | /// subfield of the protected data. When this structure is dropped (falls out |
221 | /// of scope), the lock will be unlocked. |
222 | /// |
223 | /// The main difference between `MappedMutexGuard` and [`MutexGuard`] is that the |
224 | /// former cannot be used with [`Condvar`], since that |
225 | /// could introduce soundness issues if the locked object is modified by another |
226 | /// thread while the `Mutex` is unlocked. |
227 | /// |
228 | /// The data protected by the mutex can be accessed through this guard via its |
229 | /// [`Deref`] and [`DerefMut`] implementations. |
230 | /// |
231 | /// This structure is created by the [`map`] and [`try_map`] methods on |
232 | /// [`MutexGuard`]. |
233 | /// |
234 | /// [`map`]: MutexGuard::map |
235 | /// [`try_map`]: MutexGuard::try_map |
236 | /// [`Condvar`]: crate::sync::Condvar |
237 | #[must_use = "if unused the Mutex will immediately unlock" ] |
238 | #[must_not_suspend = "holding a MappedMutexGuard across suspend \ |
239 | points can cause deadlocks, delays, \ |
240 | and cause Futures to not implement `Send`" ] |
241 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
242 | #[clippy::has_significant_drop] |
243 | pub struct MappedMutexGuard<'a, T: ?Sized + 'a> { |
244 | // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a |
245 | // `MappedMutexGuard` argument doesn't hold uniqueness for its whole scope, only until it drops. |
246 | // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field |
247 | // below for the correct variance over `T` (invariance). |
248 | data: NonNull<T>, |
249 | inner: &'a sys::Mutex, |
250 | poison_flag: &'a poison::Flag, |
251 | poison: poison::Guard, |
252 | _variance: PhantomData<&'a mut T>, |
253 | } |
254 | |
255 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
256 | impl<T: ?Sized> !Send for MappedMutexGuard<'_, T> {} |
257 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
258 | unsafe impl<T: ?Sized + Sync> Sync for MappedMutexGuard<'_, T> {} |
259 | |
260 | impl<T> Mutex<T> { |
261 | /// Creates a new mutex in an unlocked state ready for use. |
262 | /// |
263 | /// # Examples |
264 | /// |
265 | /// ``` |
266 | /// use std::sync::Mutex; |
267 | /// |
268 | /// let mutex = Mutex::new(0); |
269 | /// ``` |
270 | #[stable (feature = "rust1" , since = "1.0.0" )] |
271 | #[rustc_const_stable (feature = "const_locks" , since = "1.63.0" )] |
272 | #[inline ] |
273 | pub const fn new(t: T) -> Mutex<T> { |
274 | Mutex { inner: sys::Mutex::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t) } |
275 | } |
276 | } |
277 | |
278 | impl<T: ?Sized> Mutex<T> { |
279 | /// Acquires a mutex, blocking the current thread until it is able to do so. |
280 | /// |
281 | /// This function will block the local thread until it is available to acquire |
282 | /// the mutex. Upon returning, the thread is the only thread with the lock |
283 | /// held. An RAII guard is returned to allow scoped unlock of the lock. When |
284 | /// the guard goes out of scope, the mutex will be unlocked. |
285 | /// |
286 | /// The exact behavior on locking a mutex in the thread which already holds |
287 | /// the lock is left unspecified. However, this function will not return on |
288 | /// the second call (it might panic or deadlock, for example). |
289 | /// |
290 | /// # Errors |
291 | /// |
292 | /// If another user of this mutex panicked while holding the mutex, then |
293 | /// this call will return an error once the mutex is acquired. |
294 | /// |
295 | /// # Panics |
296 | /// |
297 | /// This function might panic when called if the lock is already held by |
298 | /// the current thread. |
299 | /// |
300 | /// # Examples |
301 | /// |
302 | /// ``` |
303 | /// use std::sync::{Arc, Mutex}; |
304 | /// use std::thread; |
305 | /// |
306 | /// let mutex = Arc::new(Mutex::new(0)); |
307 | /// let c_mutex = Arc::clone(&mutex); |
308 | /// |
309 | /// thread::spawn(move || { |
310 | /// *c_mutex.lock().unwrap() = 10; |
311 | /// }).join().expect("thread::spawn failed" ); |
312 | /// assert_eq!(*mutex.lock().unwrap(), 10); |
313 | /// ``` |
314 | #[stable (feature = "rust1" , since = "1.0.0" )] |
315 | pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> { |
316 | unsafe { |
317 | self.inner.lock(); |
318 | MutexGuard::new(self) |
319 | } |
320 | } |
321 | |
322 | /// Attempts to acquire this lock. |
323 | /// |
324 | /// If the lock could not be acquired at this time, then [`Err`] is returned. |
325 | /// Otherwise, an RAII guard is returned. The lock will be unlocked when the |
326 | /// guard is dropped. |
327 | /// |
328 | /// This function does not block. |
329 | /// |
330 | /// # Errors |
331 | /// |
332 | /// If another user of this mutex panicked while holding the mutex, then |
333 | /// this call will return the [`Poisoned`] error if the mutex would |
334 | /// otherwise be acquired. |
335 | /// |
336 | /// If the mutex could not be acquired because it is already locked, then |
337 | /// this call will return the [`WouldBlock`] error. |
338 | /// |
339 | /// [`Poisoned`]: TryLockError::Poisoned |
340 | /// [`WouldBlock`]: TryLockError::WouldBlock |
341 | /// |
342 | /// # Examples |
343 | /// |
344 | /// ``` |
345 | /// use std::sync::{Arc, Mutex}; |
346 | /// use std::thread; |
347 | /// |
348 | /// let mutex = Arc::new(Mutex::new(0)); |
349 | /// let c_mutex = Arc::clone(&mutex); |
350 | /// |
351 | /// thread::spawn(move || { |
352 | /// let mut lock = c_mutex.try_lock(); |
353 | /// if let Ok(ref mut mutex) = lock { |
354 | /// **mutex = 10; |
355 | /// } else { |
356 | /// println!("try_lock failed" ); |
357 | /// } |
358 | /// }).join().expect("thread::spawn failed" ); |
359 | /// assert_eq!(*mutex.lock().unwrap(), 10); |
360 | /// ``` |
361 | #[stable (feature = "rust1" , since = "1.0.0" )] |
362 | pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> { |
363 | unsafe { |
364 | if self.inner.try_lock() { |
365 | Ok(MutexGuard::new(self)?) |
366 | } else { |
367 | Err(TryLockError::WouldBlock) |
368 | } |
369 | } |
370 | } |
371 | |
372 | /// Determines whether the mutex is poisoned. |
373 | /// |
374 | /// If another thread is active, the mutex can still become poisoned at any |
375 | /// time. You should not trust a `false` value for program correctness |
376 | /// without additional synchronization. |
377 | /// |
378 | /// # Examples |
379 | /// |
380 | /// ``` |
381 | /// use std::sync::{Arc, Mutex}; |
382 | /// use std::thread; |
383 | /// |
384 | /// let mutex = Arc::new(Mutex::new(0)); |
385 | /// let c_mutex = Arc::clone(&mutex); |
386 | /// |
387 | /// let _ = thread::spawn(move || { |
388 | /// let _lock = c_mutex.lock().unwrap(); |
389 | /// panic!(); // the mutex gets poisoned |
390 | /// }).join(); |
391 | /// assert_eq!(mutex.is_poisoned(), true); |
392 | /// ``` |
393 | #[inline ] |
394 | #[stable (feature = "sync_poison" , since = "1.2.0" )] |
395 | pub fn is_poisoned(&self) -> bool { |
396 | self.poison.get() |
397 | } |
398 | |
399 | /// Clear the poisoned state from a mutex. |
400 | /// |
401 | /// If the mutex is poisoned, it will remain poisoned until this function is called. This |
402 | /// allows recovering from a poisoned state and marking that it has recovered. For example, if |
403 | /// the value is overwritten by a known-good value, then the mutex can be marked as |
404 | /// un-poisoned. Or possibly, the value could be inspected to determine if it is in a |
405 | /// consistent state, and if so the poison is removed. |
406 | /// |
407 | /// # Examples |
408 | /// |
409 | /// ``` |
410 | /// use std::sync::{Arc, Mutex}; |
411 | /// use std::thread; |
412 | /// |
413 | /// let mutex = Arc::new(Mutex::new(0)); |
414 | /// let c_mutex = Arc::clone(&mutex); |
415 | /// |
416 | /// let _ = thread::spawn(move || { |
417 | /// let _lock = c_mutex.lock().unwrap(); |
418 | /// panic!(); // the mutex gets poisoned |
419 | /// }).join(); |
420 | /// |
421 | /// assert_eq!(mutex.is_poisoned(), true); |
422 | /// let x = mutex.lock().unwrap_or_else(|mut e| { |
423 | /// **e.get_mut() = 1; |
424 | /// mutex.clear_poison(); |
425 | /// e.into_inner() |
426 | /// }); |
427 | /// assert_eq!(mutex.is_poisoned(), false); |
428 | /// assert_eq!(*x, 1); |
429 | /// ``` |
430 | #[inline ] |
431 | #[stable (feature = "mutex_unpoison" , since = "1.77.0" )] |
432 | pub fn clear_poison(&self) { |
433 | self.poison.clear(); |
434 | } |
435 | |
436 | /// Consumes this mutex, returning the underlying data. |
437 | /// |
438 | /// # Errors |
439 | /// |
440 | /// If another user of this mutex panicked while holding the mutex, then |
441 | /// this call will return an error instead. |
442 | /// |
443 | /// # Examples |
444 | /// |
445 | /// ``` |
446 | /// use std::sync::Mutex; |
447 | /// |
448 | /// let mutex = Mutex::new(0); |
449 | /// assert_eq!(mutex.into_inner().unwrap(), 0); |
450 | /// ``` |
451 | #[stable (feature = "mutex_into_inner" , since = "1.6.0" )] |
452 | pub fn into_inner(self) -> LockResult<T> |
453 | where |
454 | T: Sized, |
455 | { |
456 | let data = self.data.into_inner(); |
457 | poison::map_result(self.poison.borrow(), |()| data) |
458 | } |
459 | |
460 | /// Returns a mutable reference to the underlying data. |
461 | /// |
462 | /// Since this call borrows the `Mutex` mutably, no actual locking needs to |
463 | /// take place -- the mutable borrow statically guarantees no locks exist. |
464 | /// |
465 | /// # Errors |
466 | /// |
467 | /// If another user of this mutex panicked while holding the mutex, then |
468 | /// this call will return an error instead. |
469 | /// |
470 | /// # Examples |
471 | /// |
472 | /// ``` |
473 | /// use std::sync::Mutex; |
474 | /// |
475 | /// let mut mutex = Mutex::new(0); |
476 | /// *mutex.get_mut().unwrap() = 10; |
477 | /// assert_eq!(*mutex.lock().unwrap(), 10); |
478 | /// ``` |
479 | #[stable (feature = "mutex_get_mut" , since = "1.6.0" )] |
480 | pub fn get_mut(&mut self) -> LockResult<&mut T> { |
481 | let data = self.data.get_mut(); |
482 | poison::map_result(self.poison.borrow(), |()| data) |
483 | } |
484 | } |
485 | |
486 | #[stable (feature = "mutex_from" , since = "1.24.0" )] |
487 | impl<T> From<T> for Mutex<T> { |
488 | /// Creates a new mutex in an unlocked state ready for use. |
489 | /// This is equivalent to [`Mutex::new`]. |
490 | fn from(t: T) -> Self { |
491 | Mutex::new(t) |
492 | } |
493 | } |
494 | |
495 | #[stable (feature = "mutex_default" , since = "1.10.0" )] |
496 | impl<T: ?Sized + Default> Default for Mutex<T> { |
497 | /// Creates a `Mutex<T>`, with the `Default` value for T. |
498 | fn default() -> Mutex<T> { |
499 | Mutex::new(Default::default()) |
500 | } |
501 | } |
502 | |
503 | #[stable (feature = "rust1" , since = "1.0.0" )] |
504 | impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> { |
505 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
506 | let mut d: DebugStruct<'_, '_> = f.debug_struct(name:"Mutex" ); |
507 | match self.try_lock() { |
508 | Ok(guard: MutexGuard<'_, T>) => { |
509 | d.field(name:"data" , &&*guard); |
510 | } |
511 | Err(TryLockError::Poisoned(err: PoisonError>)) => { |
512 | d.field(name:"data" , &&**err.get_ref()); |
513 | } |
514 | Err(TryLockError::WouldBlock) => { |
515 | d.field(name:"data" , &format_args!("<locked>" )); |
516 | } |
517 | } |
518 | d.field(name:"poisoned" , &self.poison.get()); |
519 | d.finish_non_exhaustive() |
520 | } |
521 | } |
522 | |
523 | impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { |
524 | unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> { |
525 | poison::map_result(result:lock.poison.guard(), |guard: Guard| MutexGuard { lock, poison: guard }) |
526 | } |
527 | } |
528 | |
529 | #[stable (feature = "rust1" , since = "1.0.0" )] |
530 | impl<T: ?Sized> Deref for MutexGuard<'_, T> { |
531 | type Target = T; |
532 | |
533 | fn deref(&self) -> &T { |
534 | unsafe { &*self.lock.data.get() } |
535 | } |
536 | } |
537 | |
538 | #[stable (feature = "rust1" , since = "1.0.0" )] |
539 | impl<T: ?Sized> DerefMut for MutexGuard<'_, T> { |
540 | fn deref_mut(&mut self) -> &mut T { |
541 | unsafe { &mut *self.lock.data.get() } |
542 | } |
543 | } |
544 | |
545 | #[stable (feature = "rust1" , since = "1.0.0" )] |
546 | impl<T: ?Sized> Drop for MutexGuard<'_, T> { |
547 | #[inline ] |
548 | fn drop(&mut self) { |
549 | unsafe { |
550 | self.lock.poison.done(&self.poison); |
551 | self.lock.inner.unlock(); |
552 | } |
553 | } |
554 | } |
555 | |
556 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
557 | impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> { |
558 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
559 | fmt::Debug::fmt(&**self, f) |
560 | } |
561 | } |
562 | |
563 | #[stable (feature = "std_guard_impls" , since = "1.20.0" )] |
564 | impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { |
565 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
566 | (**self).fmt(f) |
567 | } |
568 | } |
569 | |
570 | pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { |
571 | &guard.lock.inner |
572 | } |
573 | |
574 | pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { |
575 | &guard.lock.poison |
576 | } |
577 | |
578 | impl<'a, T: ?Sized> MutexGuard<'a, T> { |
579 | /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g. |
580 | /// an enum variant. |
581 | /// |
582 | /// The `Mutex` is already locked, so this cannot fail. |
583 | /// |
584 | /// This is an associated function that needs to be used as |
585 | /// `MutexGuard::map(...)`. A method would interfere with methods of the |
586 | /// same name on the contents of the `MutexGuard` used through `Deref`. |
587 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
588 | pub fn map<U, F>(orig: Self, f: F) -> MappedMutexGuard<'a, U> |
589 | where |
590 | F: FnOnce(&mut T) -> &mut U, |
591 | U: ?Sized, |
592 | { |
593 | // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard |
594 | // was created, and have been upheld throughout `map` and/or `try_map`. |
595 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
596 | // passed to it. If the closure panics, the guard will be dropped. |
597 | let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() })); |
598 | let orig = ManuallyDrop::new(orig); |
599 | MappedMutexGuard { |
600 | data, |
601 | inner: &orig.lock.inner, |
602 | poison_flag: &orig.lock.poison, |
603 | poison: orig.poison.clone(), |
604 | _variance: PhantomData, |
605 | } |
606 | } |
607 | |
608 | /// Makes a [`MappedMutexGuard`] for a component of the borrowed data. The |
609 | /// original guard is returned as an `Err(...)` if the closure returns |
610 | /// `None`. |
611 | /// |
612 | /// The `Mutex` is already locked, so this cannot fail. |
613 | /// |
614 | /// This is an associated function that needs to be used as |
615 | /// `MutexGuard::try_map(...)`. A method would interfere with methods of the |
616 | /// same name on the contents of the `MutexGuard` used through `Deref`. |
617 | #[doc (alias = "filter_map" )] |
618 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
619 | pub fn try_map<U, F>(orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self> |
620 | where |
621 | F: FnOnce(&mut T) -> Option<&mut U>, |
622 | U: ?Sized, |
623 | { |
624 | // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard |
625 | // was created, and have been upheld throughout `map` and/or `try_map`. |
626 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
627 | // passed to it. If the closure panics, the guard will be dropped. |
628 | match f(unsafe { &mut *orig.lock.data.get() }) { |
629 | Some(data) => { |
630 | let data = NonNull::from(data); |
631 | let orig = ManuallyDrop::new(orig); |
632 | Ok(MappedMutexGuard { |
633 | data, |
634 | inner: &orig.lock.inner, |
635 | poison_flag: &orig.lock.poison, |
636 | poison: orig.poison.clone(), |
637 | _variance: PhantomData, |
638 | }) |
639 | } |
640 | None => Err(orig), |
641 | } |
642 | } |
643 | } |
644 | |
645 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
646 | impl<T: ?Sized> Deref for MappedMutexGuard<'_, T> { |
647 | type Target = T; |
648 | |
649 | fn deref(&self) -> &T { |
650 | unsafe { self.data.as_ref() } |
651 | } |
652 | } |
653 | |
654 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
655 | impl<T: ?Sized> DerefMut for MappedMutexGuard<'_, T> { |
656 | fn deref_mut(&mut self) -> &mut T { |
657 | unsafe { self.data.as_mut() } |
658 | } |
659 | } |
660 | |
661 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
662 | impl<T: ?Sized> Drop for MappedMutexGuard<'_, T> { |
663 | #[inline ] |
664 | fn drop(&mut self) { |
665 | unsafe { |
666 | self.poison_flag.done(&self.poison); |
667 | self.inner.unlock(); |
668 | } |
669 | } |
670 | } |
671 | |
672 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
673 | impl<T: ?Sized + fmt::Debug> fmt::Debug for MappedMutexGuard<'_, T> { |
674 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
675 | fmt::Debug::fmt(&**self, f) |
676 | } |
677 | } |
678 | |
679 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
680 | impl<T: ?Sized + fmt::Display> fmt::Display for MappedMutexGuard<'_, T> { |
681 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
682 | (**self).fmt(f) |
683 | } |
684 | } |
685 | |
686 | impl<'a, T: ?Sized> MappedMutexGuard<'a, T> { |
687 | /// Makes a [`MappedMutexGuard`] for a component of the borrowed data, e.g. |
688 | /// an enum variant. |
689 | /// |
690 | /// The `Mutex` is already locked, so this cannot fail. |
691 | /// |
692 | /// This is an associated function that needs to be used as |
693 | /// `MappedMutexGuard::map(...)`. A method would interfere with methods of the |
694 | /// same name on the contents of the `MutexGuard` used through `Deref`. |
695 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
696 | pub fn map<U, F>(mut orig: Self, f: F) -> MappedMutexGuard<'a, U> |
697 | where |
698 | F: FnOnce(&mut T) -> &mut U, |
699 | U: ?Sized, |
700 | { |
701 | // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard |
702 | // was created, and have been upheld throughout `map` and/or `try_map`. |
703 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
704 | // passed to it. If the closure panics, the guard will be dropped. |
705 | let data = NonNull::from(f(unsafe { orig.data.as_mut() })); |
706 | let orig = ManuallyDrop::new(orig); |
707 | MappedMutexGuard { |
708 | data, |
709 | inner: orig.inner, |
710 | poison_flag: orig.poison_flag, |
711 | poison: orig.poison.clone(), |
712 | _variance: PhantomData, |
713 | } |
714 | } |
715 | |
716 | /// Makes a [`MappedMutexGuard`] for a component of the borrowed data. The |
717 | /// original guard is returned as an `Err(...)` if the closure returns |
718 | /// `None`. |
719 | /// |
720 | /// The `Mutex` is already locked, so this cannot fail. |
721 | /// |
722 | /// This is an associated function that needs to be used as |
723 | /// `MappedMutexGuard::try_map(...)`. A method would interfere with methods of the |
724 | /// same name on the contents of the `MutexGuard` used through `Deref`. |
725 | #[doc (alias = "filter_map" )] |
726 | #[unstable (feature = "mapped_lock_guards" , issue = "117108" )] |
727 | pub fn try_map<U, F>(mut orig: Self, f: F) -> Result<MappedMutexGuard<'a, U>, Self> |
728 | where |
729 | F: FnOnce(&mut T) -> Option<&mut U>, |
730 | U: ?Sized, |
731 | { |
732 | // SAFETY: the conditions of `MutexGuard::new` were satisfied when the original guard |
733 | // was created, and have been upheld throughout `map` and/or `try_map`. |
734 | // The signature of the closure guarantees that it will not "leak" the lifetime of the reference |
735 | // passed to it. If the closure panics, the guard will be dropped. |
736 | match f(unsafe { orig.data.as_mut() }) { |
737 | Some(data) => { |
738 | let data = NonNull::from(data); |
739 | let orig = ManuallyDrop::new(orig); |
740 | Ok(MappedMutexGuard { |
741 | data, |
742 | inner: orig.inner, |
743 | poison_flag: orig.poison_flag, |
744 | poison: orig.poison.clone(), |
745 | _variance: PhantomData, |
746 | }) |
747 | } |
748 | None => Err(orig), |
749 | } |
750 | } |
751 | } |
752 | |