]> git.proxmox.com Git - rustc.git/blob - src/libstd/sync/mutex.rs
New upstream version 1.12.0+dfsg1
[rustc.git] / src / libstd / sync / mutex.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use prelude::v1::*;
12
13 use cell::UnsafeCell;
14 use fmt;
15 use marker;
16 use mem;
17 use ops::{Deref, DerefMut};
18 use ptr;
19 use sys_common::mutex as sys;
20 use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
21
22 /// A mutual exclusion primitive useful for protecting shared data
23 ///
24 /// This mutex will block threads waiting for the lock to become available. The
25 /// mutex can also be statically initialized or created via a `new`
26 /// constructor. Each mutex has a type parameter which represents the data that
27 /// it is protecting. The data can only be accessed through the RAII guards
28 /// returned from `lock` and `try_lock`, which guarantees that the data is only
29 /// ever accessed when the mutex is locked.
30 ///
31 /// # Poisoning
32 ///
33 /// The mutexes in this module implement a strategy called "poisoning" where a
34 /// mutex is considered poisoned whenever a thread panics while holding the
35 /// lock. Once a mutex is poisoned, all other threads are unable to access the
36 /// data by default as it is likely tainted (some invariant is not being
37 /// upheld).
38 ///
39 /// For a mutex, this means that the `lock` and `try_lock` methods return a
40 /// `Result` which indicates whether a mutex has been poisoned or not. Most
41 /// usage of a mutex will simply `unwrap()` these results, propagating panics
42 /// among threads to ensure that a possibly invalid invariant is not witnessed.
43 ///
44 /// A poisoned mutex, however, does not prevent all access to the underlying
45 /// data. The `PoisonError` type has an `into_inner` method which will return
46 /// the guard that would have otherwise been returned on a successful lock. This
47 /// allows access to the data, despite the lock being poisoned.
48 ///
49 /// # Examples
50 ///
51 /// ```
52 /// use std::sync::{Arc, Mutex};
53 /// use std::thread;
54 /// use std::sync::mpsc::channel;
55 ///
56 /// const N: usize = 10;
57 ///
58 /// // Spawn a few threads to increment a shared variable (non-atomically), and
59 /// // let the main thread know once all increments are done.
60 /// //
61 /// // Here we're using an Arc to share memory among threads, and the data inside
62 /// // the Arc is protected with a mutex.
63 /// let data = Arc::new(Mutex::new(0));
64 ///
65 /// let (tx, rx) = channel();
66 /// for _ in 0..10 {
67 /// let (data, tx) = (data.clone(), tx.clone());
68 /// thread::spawn(move || {
69 /// // The shared state can only be accessed once the lock is held.
70 /// // Our non-atomic increment is safe because we're the only thread
71 /// // which can access the shared state when the lock is held.
72 /// //
73 /// // We unwrap() the return value to assert that we are not expecting
74 /// // threads to ever fail while holding the lock.
75 /// let mut data = data.lock().unwrap();
76 /// *data += 1;
77 /// if *data == N {
78 /// tx.send(()).unwrap();
79 /// }
80 /// // the lock is unlocked here when `data` goes out of scope.
81 /// });
82 /// }
83 ///
84 /// rx.recv().unwrap();
85 /// ```
86 ///
87 /// To recover from a poisoned mutex:
88 ///
89 /// ```
90 /// use std::sync::{Arc, Mutex};
91 /// use std::thread;
92 ///
93 /// let lock = Arc::new(Mutex::new(0_u32));
94 /// let lock2 = lock.clone();
95 ///
96 /// let _ = thread::spawn(move || -> () {
97 /// // This thread will acquire the mutex first, unwrapping the result of
98 /// // `lock` because the lock has not been poisoned.
99 /// let _guard = lock2.lock().unwrap();
100 ///
101 /// // This panic while holding the lock (`_guard` is in scope) will poison
102 /// // the mutex.
103 /// panic!();
104 /// }).join();
105 ///
106 /// // The lock is poisoned by this point, but the returned result can be
107 /// // pattern matched on to return the underlying guard on both branches.
108 /// let mut guard = match lock.lock() {
109 /// Ok(guard) => guard,
110 /// Err(poisoned) => poisoned.into_inner(),
111 /// };
112 ///
113 /// *guard += 1;
114 /// ```
115 #[stable(feature = "rust1", since = "1.0.0")]
116 pub struct Mutex<T: ?Sized> {
117 // Note that this mutex is in a *box*, not inlined into the struct itself.
118 // Once a native mutex has been used once, its address can never change (it
119 // can't be moved). This mutex type can be safely moved at any time, so to
120 // ensure that the native mutex is used correctly we box the inner lock to
121 // give it a constant address.
122 inner: Box<sys::Mutex>,
123 poison: poison::Flag,
124 data: UnsafeCell<T>,
125 }
126
127 // these are the only places where `T: Send` matters; all other
128 // functionality works fine on a single thread.
129 #[stable(feature = "rust1", since = "1.0.0")]
130 unsafe impl<T: ?Sized + Send> Send for Mutex<T> { }
131 #[stable(feature = "rust1", since = "1.0.0")]
132 unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
133
134 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
135 /// dropped (falls out of scope), the lock will be unlocked.
136 ///
137 /// The data protected by the mutex can be access through this guard via its
138 /// `Deref` and `DerefMut` implementations
139 #[must_use]
140 #[stable(feature = "rust1", since = "1.0.0")]
141 pub struct MutexGuard<'a, T: ?Sized + 'a> {
142 // funny underscores due to how Deref/DerefMut currently work (they
143 // disregard field privacy).
144 __lock: &'a Mutex<T>,
145 __poison: poison::Guard,
146 }
147
148 #[stable(feature = "rust1", since = "1.0.0")]
149 impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}
150
151 impl<T> Mutex<T> {
152 /// Creates a new mutex in an unlocked state ready for use.
153 #[stable(feature = "rust1", since = "1.0.0")]
154 pub fn new(t: T) -> Mutex<T> {
155 let mut m = Mutex {
156 inner: box sys::Mutex::new(),
157 poison: poison::Flag::new(),
158 data: UnsafeCell::new(t),
159 };
160 unsafe {
161 m.inner.init();
162 }
163 m
164 }
165 }
166
167 impl<T: ?Sized> Mutex<T> {
168 /// Acquires a mutex, blocking the current thread until it is able to do so.
169 ///
170 /// This function will block the local thread until it is available to acquire
171 /// the mutex. Upon returning, the thread is the only thread with the mutex
172 /// held. An RAII guard is returned to allow scoped unlock of the lock. When
173 /// the guard goes out of scope, the mutex will be unlocked.
174 ///
175 /// The exact behavior on locking a mutex in the thread which already holds
176 /// the lock is left unspecified. However, this function will not return on
177 /// the second call (it might panic or deadlock, for example).
178 ///
179 /// # Errors
180 ///
181 /// If another user of this mutex panicked while holding the mutex, then
182 /// this call will return an error once the mutex is acquired.
183 ///
184 /// # Panics
185 ///
186 /// This function might panic when called if the lock is already held by
187 /// the current thread.
188 #[stable(feature = "rust1", since = "1.0.0")]
189 pub fn lock(&self) -> LockResult<MutexGuard<T>> {
190 unsafe {
191 self.inner.lock();
192 MutexGuard::new(self)
193 }
194 }
195
196 /// Attempts to acquire this lock.
197 ///
198 /// If the lock could not be acquired at this time, then `Err` is returned.
199 /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
200 /// guard is dropped.
201 ///
202 /// This function does not block.
203 ///
204 /// # Errors
205 ///
206 /// If another user of this mutex panicked while holding the mutex, then
207 /// this call will return failure if the mutex would otherwise be
208 /// acquired.
209 #[stable(feature = "rust1", since = "1.0.0")]
210 pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
211 unsafe {
212 if self.inner.try_lock() {
213 Ok(MutexGuard::new(self)?)
214 } else {
215 Err(TryLockError::WouldBlock)
216 }
217 }
218 }
219
220 /// Determines whether the lock is poisoned.
221 ///
222 /// If another thread is active, the lock can still become poisoned at any
223 /// time. You should not trust a `false` value for program correctness
224 /// without additional synchronization.
225 #[inline]
226 #[stable(feature = "sync_poison", since = "1.2.0")]
227 pub fn is_poisoned(&self) -> bool {
228 self.poison.get()
229 }
230
231 /// Consumes this mutex, returning the underlying data.
232 ///
233 /// # Errors
234 ///
235 /// If another user of this mutex panicked while holding the mutex, then
236 /// this call will return an error instead.
237 #[stable(feature = "mutex_into_inner", since = "1.6.0")]
238 pub fn into_inner(self) -> LockResult<T> where T: Sized {
239 // We know statically that there are no outstanding references to
240 // `self` so there's no need to lock the inner lock.
241 //
242 // To get the inner value, we'd like to call `data.into_inner()`,
243 // but because `Mutex` impl-s `Drop`, we can't move out of it, so
244 // we'll have to destructure it manually instead.
245 unsafe {
246 // Like `let Mutex { inner, poison, data } = self`.
247 let (inner, poison, data) = {
248 let Mutex { ref inner, ref poison, ref data } = self;
249 (ptr::read(inner), ptr::read(poison), ptr::read(data))
250 };
251 mem::forget(self);
252 inner.destroy(); // Keep in sync with the `Drop` impl.
253 drop(inner);
254
255 poison::map_result(poison.borrow(), |_| data.into_inner())
256 }
257 }
258
259 /// Returns a mutable reference to the underlying data.
260 ///
261 /// Since this call borrows the `Mutex` mutably, no actual locking needs to
262 /// take place---the mutable borrow statically guarantees no locks exist.
263 ///
264 /// # Errors
265 ///
266 /// If another user of this mutex panicked while holding the mutex, then
267 /// this call will return an error instead.
268 #[stable(feature = "mutex_get_mut", since = "1.6.0")]
269 pub fn get_mut(&mut self) -> LockResult<&mut T> {
270 // We know statically that there are no other references to `self`, so
271 // there's no need to lock the inner lock.
272 let data = unsafe { &mut *self.data.get() };
273 poison::map_result(self.poison.borrow(), |_| data )
274 }
275 }
276
277 #[stable(feature = "rust1", since = "1.0.0")]
278 impl<T: ?Sized> Drop for Mutex<T> {
279 #[unsafe_destructor_blind_to_params]
280 fn drop(&mut self) {
281 // This is actually safe b/c we know that there is no further usage of
282 // this mutex (it's up to the user to arrange for a mutex to get
283 // dropped, that's not our job)
284 //
285 // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
286 unsafe { self.inner.destroy() }
287 }
288 }
289
290 #[stable(feature = "mutex_default", since = "1.9.0")]
291 impl<T: ?Sized + Default> Default for Mutex<T> {
292 fn default() -> Mutex<T> {
293 Mutex::new(Default::default())
294 }
295 }
296
297 #[stable(feature = "rust1", since = "1.0.0")]
298 impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
299 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
300 match self.try_lock() {
301 Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
302 Err(TryLockError::Poisoned(err)) => {
303 write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
304 },
305 Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
306 }
307 }
308 }
309
310 impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
311 unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
312 poison::map_result(lock.poison.borrow(), |guard| {
313 MutexGuard {
314 __lock: lock,
315 __poison: guard,
316 }
317 })
318 }
319 }
320
321 #[stable(feature = "rust1", since = "1.0.0")]
322 impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
323 type Target = T;
324
325 fn deref(&self) -> &T {
326 unsafe { &*self.__lock.data.get() }
327 }
328 }
329
330 #[stable(feature = "rust1", since = "1.0.0")]
331 impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
332 fn deref_mut(&mut self) -> &mut T {
333 unsafe { &mut *self.__lock.data.get() }
334 }
335 }
336
337 #[stable(feature = "rust1", since = "1.0.0")]
338 impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
339 #[inline]
340 fn drop(&mut self) {
341 unsafe {
342 self.__lock.poison.done(&self.__poison);
343 self.__lock.inner.unlock();
344 }
345 }
346 }
347
348 pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
349 &guard.__lock.inner
350 }
351
352 pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
353 &guard.__lock.poison
354 }
355
356 #[cfg(test)]
357 mod tests {
358 use prelude::v1::*;
359
360 use sync::mpsc::channel;
361 use sync::{Arc, Mutex, Condvar};
362 use sync::atomic::{AtomicUsize, Ordering};
363 use thread;
364
365 struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
366
367 #[derive(Eq, PartialEq, Debug)]
368 struct NonCopy(i32);
369
370 unsafe impl<T: Send> Send for Packet<T> {}
371 unsafe impl<T> Sync for Packet<T> {}
372
373 #[test]
374 fn smoke() {
375 let m = Mutex::new(());
376 drop(m.lock().unwrap());
377 drop(m.lock().unwrap());
378 }
379
380 #[test]
381 fn lots_and_lots() {
382 const J: u32 = 1000;
383 const K: u32 = 3;
384
385 let m = Arc::new(Mutex::new(0));
386
387 fn inc(m: &Mutex<u32>) {
388 for _ in 0..J {
389 *m.lock().unwrap() += 1;
390 }
391 }
392
393 let (tx, rx) = channel();
394 for _ in 0..K {
395 let tx2 = tx.clone();
396 let m2 = m.clone();
397 thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); });
398 let tx2 = tx.clone();
399 let m2 = m.clone();
400 thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); });
401 }
402
403 drop(tx);
404 for _ in 0..2 * K {
405 rx.recv().unwrap();
406 }
407 assert_eq!(*m.lock().unwrap(), J * K * 2);
408 }
409
410 #[test]
411 fn try_lock() {
412 let m = Mutex::new(());
413 *m.try_lock().unwrap() = ();
414 }
415
416 #[test]
417 fn test_into_inner() {
418 let m = Mutex::new(NonCopy(10));
419 assert_eq!(m.into_inner().unwrap(), NonCopy(10));
420 }
421
422 #[test]
423 fn test_into_inner_drop() {
424 struct Foo(Arc<AtomicUsize>);
425 impl Drop for Foo {
426 fn drop(&mut self) {
427 self.0.fetch_add(1, Ordering::SeqCst);
428 }
429 }
430 let num_drops = Arc::new(AtomicUsize::new(0));
431 let m = Mutex::new(Foo(num_drops.clone()));
432 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
433 {
434 let _inner = m.into_inner().unwrap();
435 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
436 }
437 assert_eq!(num_drops.load(Ordering::SeqCst), 1);
438 }
439
440 #[test]
441 fn test_into_inner_poison() {
442 let m = Arc::new(Mutex::new(NonCopy(10)));
443 let m2 = m.clone();
444 let _ = thread::spawn(move || {
445 let _lock = m2.lock().unwrap();
446 panic!("test panic in inner thread to poison mutex");
447 }).join();
448
449 assert!(m.is_poisoned());
450 match Arc::try_unwrap(m).unwrap().into_inner() {
451 Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
452 Ok(x) => panic!("into_inner of poisoned Mutex is Ok: {:?}", x),
453 }
454 }
455
456 #[test]
457 fn test_get_mut() {
458 let mut m = Mutex::new(NonCopy(10));
459 *m.get_mut().unwrap() = NonCopy(20);
460 assert_eq!(m.into_inner().unwrap(), NonCopy(20));
461 }
462
463 #[test]
464 fn test_get_mut_poison() {
465 let m = Arc::new(Mutex::new(NonCopy(10)));
466 let m2 = m.clone();
467 let _ = thread::spawn(move || {
468 let _lock = m2.lock().unwrap();
469 panic!("test panic in inner thread to poison mutex");
470 }).join();
471
472 assert!(m.is_poisoned());
473 match Arc::try_unwrap(m).unwrap().get_mut() {
474 Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
475 Ok(x) => panic!("get_mut of poisoned Mutex is Ok: {:?}", x),
476 }
477 }
478
479 #[test]
480 fn test_mutex_arc_condvar() {
481 let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
482 let packet2 = Packet(packet.0.clone());
483 let (tx, rx) = channel();
484 let _t = thread::spawn(move|| {
485 // wait until parent gets in
486 rx.recv().unwrap();
487 let &(ref lock, ref cvar) = &*packet2.0;
488 let mut lock = lock.lock().unwrap();
489 *lock = true;
490 cvar.notify_one();
491 });
492
493 let &(ref lock, ref cvar) = &*packet.0;
494 let mut lock = lock.lock().unwrap();
495 tx.send(()).unwrap();
496 assert!(!*lock);
497 while !*lock {
498 lock = cvar.wait(lock).unwrap();
499 }
500 }
501
502 #[test]
503 fn test_arc_condvar_poison() {
504 let packet = Packet(Arc::new((Mutex::new(1), Condvar::new())));
505 let packet2 = Packet(packet.0.clone());
506 let (tx, rx) = channel();
507
508 let _t = thread::spawn(move || -> () {
509 rx.recv().unwrap();
510 let &(ref lock, ref cvar) = &*packet2.0;
511 let _g = lock.lock().unwrap();
512 cvar.notify_one();
513 // Parent should fail when it wakes up.
514 panic!();
515 });
516
517 let &(ref lock, ref cvar) = &*packet.0;
518 let mut lock = lock.lock().unwrap();
519 tx.send(()).unwrap();
520 while *lock == 1 {
521 match cvar.wait(lock) {
522 Ok(l) => {
523 lock = l;
524 assert_eq!(*lock, 1);
525 }
526 Err(..) => break,
527 }
528 }
529 }
530
531 #[test]
532 fn test_mutex_arc_poison() {
533 let arc = Arc::new(Mutex::new(1));
534 assert!(!arc.is_poisoned());
535 let arc2 = arc.clone();
536 let _ = thread::spawn(move|| {
537 let lock = arc2.lock().unwrap();
538 assert_eq!(*lock, 2);
539 }).join();
540 assert!(arc.lock().is_err());
541 assert!(arc.is_poisoned());
542 }
543
544 #[test]
545 fn test_mutex_arc_nested() {
546 // Tests nested mutexes and access
547 // to underlying data.
548 let arc = Arc::new(Mutex::new(1));
549 let arc2 = Arc::new(Mutex::new(arc));
550 let (tx, rx) = channel();
551 let _t = thread::spawn(move|| {
552 let lock = arc2.lock().unwrap();
553 let lock2 = lock.lock().unwrap();
554 assert_eq!(*lock2, 1);
555 tx.send(()).unwrap();
556 });
557 rx.recv().unwrap();
558 }
559
560 #[test]
561 fn test_mutex_arc_access_in_unwind() {
562 let arc = Arc::new(Mutex::new(1));
563 let arc2 = arc.clone();
564 let _ = thread::spawn(move|| -> () {
565 struct Unwinder {
566 i: Arc<Mutex<i32>>,
567 }
568 impl Drop for Unwinder {
569 fn drop(&mut self) {
570 *self.i.lock().unwrap() += 1;
571 }
572 }
573 let _u = Unwinder { i: arc2 };
574 panic!();
575 }).join();
576 let lock = arc.lock().unwrap();
577 assert_eq!(*lock, 2);
578 }
579
580 #[test]
581 fn test_mutex_unsized() {
582 let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
583 {
584 let b = &mut *mutex.lock().unwrap();
585 b[0] = 4;
586 b[2] = 5;
587 }
588 let comp: &[i32] = &[4, 2, 5];
589 assert_eq!(&*mutex.lock().unwrap(), comp);
590 }
591 }