mutex.rs 23.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use prelude::v1::*;
12

F
Flavio Percoco 已提交
13
use cell::UnsafeCell;
14
use fmt;
N
Nick Cameron 已提交
15
use marker;
16
use mem;
17
use ops::{Deref, DerefMut};
18
use ptr;
A
Alex Crichton 已提交
19
use sys_common::mutex as sys;
20
use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
21 22 23

/// A mutual exclusion primitive useful for protecting shared data
///
A
Alex Crichton 已提交
24 25 26 27 28 29 30 31 32
/// This mutex will block threads waiting for the lock to become available. The
/// mutex can also be statically initialized or created via a `new`
/// constructor. Each mutex has a type parameter which represents the data that
/// it is protecting. The data can only be accessed through the RAII guards
/// returned from `lock` and `try_lock`, which guarantees that the data is only
/// ever accessed when the mutex is locked.
///
/// # Poisoning
///
33 34
/// The mutexes in this module implement a strategy called "poisoning" where a
/// 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 37
/// data by default as it is likely tainted (some invariant is not being
/// upheld).
38
///
39 40 41 42 43 44
/// For a mutex, this means that the `lock` and `try_lock` methods return a
/// `Result` which indicates whether a mutex has been poisoned or not. Most
/// usage of a mutex will simply `unwrap()` these results, propagating panics
/// among threads to ensure that a possibly invalid invariant is not witnessed.
///
/// 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 47 48 49
/// the guard that would have otherwise been returned on a successful lock. This
/// allows access to the data, despite the lock being poisoned.
///
/// # Examples
50
///
51
/// ```
A
Alex Crichton 已提交
52
/// use std::sync::{Arc, Mutex};
A
Aaron Turon 已提交
53
/// use std::thread;
54
/// use std::sync::mpsc::channel;
55
///
N
Nick Cameron 已提交
56
/// const N: usize = 10;
57
///
A
Alex Crichton 已提交
58 59 60
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
/// //
61
/// // Here we're using an Arc to share memory among threads, and the data inside
A
Alex Crichton 已提交
62 63 64 65
/// // the Arc is protected with a mutex.
/// let data = Arc::new(Mutex::new(0));
///
/// let (tx, rx) = channel();
66
/// for _ in 0..10 {
A
Alex Crichton 已提交
67
///     let (data, tx) = (data.clone(), tx.clone());
A
Aaron Turon 已提交
68
///     thread::spawn(move || {
69
///         // The shared state can only be accessed once the lock is held.
A
Alex Crichton 已提交
70 71
///         // Our non-atomic increment is safe because we're the only thread
///         // 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();
A
Alex Crichton 已提交
76 77
///         *data += 1;
///         if *data == N {
78
///             tx.send(()).unwrap();
A
Alex Crichton 已提交
79 80
///         }
///         // the lock is unlocked here when `data` goes out of scope.
A
Aaron Turon 已提交
81
///     });
A
Alex Crichton 已提交
82 83
/// }
///
84
/// rx.recv().unwrap();
85
/// ```
86 87 88
///
/// To recover from a poisoned mutex:
///
89
/// ```
90
/// use std::sync::{Arc, Mutex};
A
Aaron Turon 已提交
91
/// use std::thread;
92
///
93
/// let lock = Arc::new(Mutex::new(0_u32));
94 95
/// let lock2 = lock.clone();
///
A
Aaron Turon 已提交
96
/// let _ = thread::spawn(move || -> () {
97 98
///     // This thread will acquire the mutex first, unwrapping the result of
///     // `lock` because the lock has not been poisoned.
99
///     let _guard = lock2.lock().unwrap();
100 101 102 103 104 105 106 107 108 109
///
///     // This panic while holding the lock (`_guard` is in scope) will poison
///     // the mutex.
///     panic!();
/// }).join();
///
/// // The lock is poisoned by this point, but the returned result can be
/// // pattern matched on to return the underlying guard on both branches.
/// let mut guard = match lock.lock() {
///     Ok(guard) => guard,
110
///     Err(poisoned) => poisoned.into_inner(),
111 112 113 114
/// };
///
/// *guard += 1;
/// ```
B
Brian Anderson 已提交
115
#[stable(feature = "rust1", since = "1.0.0")]
116
#[allow(deprecated)]
117
pub struct Mutex<T: ?Sized> {
A
Alex Crichton 已提交
118
    // Note that this static mutex is in a *box*, not inlined into the struct
A
Alex Crichton 已提交
119 120 121 122 123
    // itself. Once a native mutex has been used once, its address can never
    // change (it can't be moved). This mutex type can be safely moved at any
    // time, so to ensure that the native mutex is used correctly we box the
    // inner lock to give it a constant address.
    inner: Box<StaticMutex>,
124
    data: UnsafeCell<T>,
125 126
}

127 128
// these are the only places where `T: Send` matters; all other
// 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> { }
F
Flavio Percoco 已提交
133

134 135 136 137 138 139 140 141
/// The static mutex type is provided to allow for static allocation of mutexes.
///
/// Note that this is a separate type because using a Mutex correctly means that
/// it needs to have a destructor run. In Rust, statics are not allowed to have
/// destructors. As a result, a `StaticMutex` has one extra method when compared
/// to a `Mutex`, a `destroy` method. This method is unsafe to call, and
/// documentation can be found directly on the method.
///
S
Steve Klabnik 已提交
142
/// # Examples
143
///
144
/// ```
145 146
/// #![feature(static_mutex)]
///
A
Alex Crichton 已提交
147
/// use std::sync::{StaticMutex, MUTEX_INIT};
148
///
A
Alex Crichton 已提交
149
/// static LOCK: StaticMutex = MUTEX_INIT;
150
///
A
Alex Crichton 已提交
151
/// {
152
///     let _g = LOCK.lock().unwrap();
153 154 155 156
///     // do some productive work
/// }
/// // lock is unlocked here.
/// ```
157
#[unstable(feature = "static_mutex",
158 159
           reason = "may be merged with Mutex in the future",
           issue = "27717")]
160 161 162 163 164
#[rustc_deprecated(since = "1.10.0",
                   reason = "the lazy-static crate suffices for static sync \
                             primitives and eventually this type shouldn't \
                             be necessary as `Mutex::new` in a static should \
                             suffice")]
165
pub struct StaticMutex {
A
Alex Crichton 已提交
166
    lock: sys::Mutex,
167
    poison: poison::Flag,
168 169 170 171
}

/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked.
A
Alex Crichton 已提交
172 173
///
/// The data protected by the mutex can be access through this guard via its
174
/// `Deref` and `DerefMut` implementations
175
#[must_use]
B
Brian Anderson 已提交
176
#[stable(feature = "rust1", since = "1.0.0")]
177
#[allow(deprecated)]
178
pub struct MutexGuard<'a, T: ?Sized + 'a> {
A
Alex Crichton 已提交
179 180
    // funny underscores due to how Deref/DerefMut currently work (they
    // disregard field privacy).
181
    __lock: &'a StaticMutex,
182
    __data: &'a mut T,
183
    __poison: poison::Guard,
184 185
}

186
#[stable(feature = "rust1", since = "1.0.0")]
187
impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}
188

189 190
/// Static initialization of a mutex. This constant can be used to initialize
/// other mutex constants.
191
#[unstable(feature = "static_mutex",
192 193
           reason = "may be merged with Mutex in the future",
           issue = "27717")]
194 195 196 197 198 199
#[rustc_deprecated(since = "1.10.0",
                   reason = "the lazy-static crate suffices for static sync \
                             primitives and eventually this type shouldn't \
                             be necessary as `Mutex::new` in a static should \
                             suffice")]
#[allow(deprecated)]
200
pub const MUTEX_INIT: StaticMutex = StaticMutex::new();
201

202
#[allow(deprecated)]
203
impl<T> Mutex<T> {
A
Alex Crichton 已提交
204
    /// Creates a new mutex in an unlocked state ready for use.
B
Brian Anderson 已提交
205
    #[stable(feature = "rust1", since = "1.0.0")]
A
Alex Crichton 已提交
206
    pub fn new(t: T) -> Mutex<T> {
207
        let mut m = Mutex {
208
            inner: box StaticMutex::new(),
209
            data: UnsafeCell::new(t),
210 211 212
        };
        unsafe {
            m.inner.lock.init();
A
Alex Crichton 已提交
213
        }
214
        m
A
Alex Crichton 已提交
215
    }
216
}
A
Alex Crichton 已提交
217

218
#[allow(deprecated)]
219
impl<T: ?Sized> Mutex<T> {
220
    /// Acquires a mutex, blocking the current thread until it is able to do so.
A
Alex Crichton 已提交
221
    ///
222 223
    /// This function will block the local thread until it is available to acquire
    /// the mutex. Upon returning, the thread is the only thread with the mutex
A
Alex Crichton 已提交
224 225 226
    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
    /// the guard goes out of scope, the mutex will be unlocked.
    ///
227
    /// The exact behavior on locking a mutex in the thread which already holds
228 229
    /// the lock is left unspecified. However, this function will not return on
    /// the second call (it might panic or deadlock, for example).
230
    ///
231
    /// # Errors
A
Alex Crichton 已提交
232 233
    ///
    /// If another user of this mutex panicked while holding the mutex, then
234
    /// this call will return an error once the mutex is acquired.
235 236 237 238 239
    ///
    /// # Panics
    ///
    /// This function might panic when called if the lock is already held by
    /// the current thread.
B
Brian Anderson 已提交
240
    #[stable(feature = "rust1", since = "1.0.0")]
241
    pub fn lock(&self) -> LockResult<MutexGuard<T>> {
242 243 244 245
        unsafe {
            self.inner.lock.lock();
            MutexGuard::new(&*self.inner, &self.data)
        }
A
Alex Crichton 已提交
246 247 248 249
    }

    /// Attempts to acquire this lock.
    ///
250
    /// If the lock could not be acquired at this time, then `Err` is returned.
A
Alex Crichton 已提交
251 252 253 254 255
    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
    /// guard is dropped.
    ///
    /// This function does not block.
    ///
256
    /// # Errors
A
Alex Crichton 已提交
257 258
    ///
    /// If another user of this mutex panicked while holding the mutex, then
259
    /// this call will return failure if the mutex would otherwise be
A
Alex Crichton 已提交
260
    /// acquired.
B
Brian Anderson 已提交
261
    #[stable(feature = "rust1", since = "1.0.0")]
262
    pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
263 264
        unsafe {
            if self.inner.lock.try_lock() {
J
Jorge Aparicio 已提交
265
                Ok(MutexGuard::new(&*self.inner, &self.data)?)
266 267 268
            } else {
                Err(TryLockError::WouldBlock)
            }
A
Alex Crichton 已提交
269
        }
270
    }
271

272
    /// Determines whether the lock is poisoned.
273 274 275 276 277
    ///
    /// If another thread is active, the lock can still become poisoned at any
    /// time.  You should not trust a `false` value for program correctness
    /// without additional synchronization.
    #[inline]
278
    #[stable(feature = "sync_poison", since = "1.2.0")]
279 280 281
    pub fn is_poisoned(&self) -> bool {
        self.inner.poison.get()
    }
282 283 284

    /// Consumes this mutex, returning the underlying data.
    ///
285
    /// # Errors
286 287 288
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return an error instead.
289
    #[stable(feature = "mutex_into_inner", since = "1.6.0")]
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
    pub fn into_inner(self) -> LockResult<T> where T: Sized {
        // We know statically that there are no outstanding references to
        // `self` so there's no need to lock the inner StaticMutex.
        //
        // To get the inner value, we'd like to call `data.into_inner()`,
        // but because `Mutex` impl-s `Drop`, we can't move out of it, so
        // we'll have to destructure it manually instead.
        unsafe {
            // Like `let Mutex { inner, data } = self`.
            let (inner, data) = {
                let Mutex { ref inner, ref data } = self;
                (ptr::read(inner), ptr::read(data))
            };
            mem::forget(self);
            inner.lock.destroy();  // Keep in sync with the `Drop` impl.

            poison::map_result(inner.poison.borrow(), |_| data.into_inner())
        }
    }

    /// Returns a mutable reference to the underlying data.
    ///
    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
    /// take place---the mutable borrow statically guarantees no locks exist.
    ///
315
    /// # Errors
316 317 318
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return an error instead.
319
    #[stable(feature = "mutex_get_mut", since = "1.6.0")]
320 321 322 323 324 325
    pub fn get_mut(&mut self) -> LockResult<&mut T> {
        // We know statically that there are no other references to `self`, so
        // there's no need to lock the inner StaticMutex.
        let data = unsafe { &mut *self.data.get() };
        poison::map_result(self.inner.poison.borrow(), |_| data )
    }
A
Alex Crichton 已提交
326
}
327

B
Brian Anderson 已提交
328
#[stable(feature = "rust1", since = "1.0.0")]
329
#[allow(deprecated)]
330
impl<T: ?Sized> Drop for Mutex<T> {
331
    #[unsafe_destructor_blind_to_params]
A
Alex Crichton 已提交
332 333 334 335
    fn drop(&mut self) {
        // This is actually safe b/c we know that there is no further usage of
        // this mutex (it's up to the user to arrange for a mutex to get
        // dropped, that's not our job)
336 337
        //
        // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
A
Alex Crichton 已提交
338 339 340 341
        unsafe { self.inner.lock.destroy() }
    }
}

342 343 344 345 346 347 348
#[stable(feature = "mutex_default", since = "1.9.0")]
impl<T: ?Sized + Default> Default for Mutex<T> {
    fn default() -> Mutex<T> {
        Mutex::new(Default::default())
    }
}

349
#[stable(feature = "rust1", since = "1.0.0")]
350
impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
351 352
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.try_lock() {
353
            Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
354
            Err(TryLockError::Poisoned(err)) => {
355
                write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
356 357 358 359 360 361
            },
            Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
        }
    }
}

A
Alex Crichton 已提交
362 363
struct Dummy(UnsafeCell<()>);
unsafe impl Sync for Dummy {}
364
static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
365

366
#[unstable(feature = "static_mutex",
367 368
           reason = "may be merged with Mutex in the future",
           issue = "27717")]
369 370 371 372 373 374
#[rustc_deprecated(since = "1.10.0",
                   reason = "the lazy-static crate suffices for static sync \
                             primitives and eventually this type shouldn't \
                             be necessary as `Mutex::new` in a static should \
                             suffice")]
#[allow(deprecated)]
A
Alex Crichton 已提交
375
impl StaticMutex {
376 377 378 379 380 381 382 383
    /// Creates a new mutex in an unlocked state ready for use.
    pub const fn new() -> StaticMutex {
        StaticMutex {
            lock: sys::Mutex::new(),
            poison: poison::Flag::new(),
        }
    }

384
    /// Acquires this lock, see `Mutex::lock`
385
    #[inline]
386
    pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
387 388 389 390
        unsafe {
            self.lock.lock();
            MutexGuard::new(self, &DUMMY.0)
        }
A
Alex Crichton 已提交
391 392 393
    }

    /// Attempts to grab this lock, see `Mutex::try_lock`
394
    #[inline]
395
    pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
396 397
        unsafe {
            if self.lock.try_lock() {
J
Jorge Aparicio 已提交
398
                Ok(MutexGuard::new(self, &DUMMY.0)?)
399 400 401
            } else {
                Err(TryLockError::WouldBlock)
            }
A
Alex Crichton 已提交
402
        }
403 404 405 406 407 408 409 410 411 412 413 414
    }

    /// Deallocates resources associated with this static mutex.
    ///
    /// This method is unsafe because it provides no guarantees that there are
    /// no active users of this mutex, and safety is not guaranteed if there are
    /// active users of this mutex.
    ///
    /// This method is required to ensure that there are no memory leaks on
    /// *all* platforms. It may be the case that some platforms do not leak
    /// memory if this method is not called, but this is not guaranteed to be
    /// true on all platforms.
A
Alex Crichton 已提交
415
    pub unsafe fn destroy(&'static self) {
416 417 418 419
        self.lock.destroy()
    }
}

420
#[allow(deprecated)]
421
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
422
    unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
423 424 425 426
           -> LockResult<MutexGuard<'mutex, T>> {
        poison::map_result(lock.poison.borrow(), |guard| {
            MutexGuard {
                __lock: lock,
427
                __data: &mut *data.get(),
428 429 430 431
                __poison: guard,
            }
        })
    }
A
Alex Crichton 已提交
432
}
433

B
Brian Anderson 已提交
434
#[stable(feature = "rust1", since = "1.0.0")]
435
impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> {
436 437
    type Target = T;

438
    fn deref(&self) -> &T {self.__data }
A
Alex Crichton 已提交
439
}
440

B
Brian Anderson 已提交
441
#[stable(feature = "rust1", since = "1.0.0")]
442
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
443
    fn deref_mut(&mut self) -> &mut T { self.__data }
A
Alex Crichton 已提交
444 445
}

B
Brian Anderson 已提交
446
#[stable(feature = "rust1", since = "1.0.0")]
447
#[allow(deprecated)]
448
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
449
    #[inline]
450 451 452 453
    fn drop(&mut self) {
        unsafe {
            self.__lock.poison.done(&self.__poison);
            self.__lock.lock.unlock();
454 455 456 457
        }
    }
}

458
#[allow(deprecated)]
459
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
460
    &guard.__lock.lock
461 462
}

463
#[allow(deprecated)]
464
pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
465
    &guard.__lock.poison
466 467 468
}

#[cfg(test)]
469
#[allow(deprecated)]
470
mod tests {
471
    use prelude::v1::*;
A
Alex Crichton 已提交
472

473
    use sync::mpsc::channel;
474
    use sync::{Arc, Mutex, StaticMutex, Condvar};
475
    use sync::atomic::{AtomicUsize, Ordering};
A
Aaron Turon 已提交
476
    use thread;
477

478
    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
479

480 481 482
    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

483
    unsafe impl<T: Send> Send for Packet<T> {}
484 485
    unsafe impl<T> Sync for Packet<T> {}

486 487
    #[test]
    fn smoke() {
A
Alex Crichton 已提交
488
        let m = Mutex::new(());
489 490
        drop(m.lock().unwrap());
        drop(m.lock().unwrap());
491 492 493 494
    }

    #[test]
    fn smoke_static() {
495
        static M: StaticMutex = StaticMutex::new();
496
        unsafe {
497 498
            drop(M.lock().unwrap());
            drop(M.lock().unwrap());
N
NODA, Kai 已提交
499
            M.destroy();
500 501 502 503 504
        }
    }

    #[test]
    fn lots_and_lots() {
505
        static M: StaticMutex = StaticMutex::new();
N
Nick Cameron 已提交
506
        static mut CNT: u32 = 0;
507 508
        const J: u32 = 1000;
        const K: u32 = 3;
509 510

        fn inc() {
511
            for _ in 0..J {
512
                unsafe {
513
                    let _g = M.lock().unwrap();
514 515 516 517 518
                    CNT += 1;
                }
            }
        }

519
        let (tx, rx) = channel();
520
        for _ in 0..K {
521
            let tx2 = tx.clone();
A
Aaron Turon 已提交
522
            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
523
            let tx2 = tx.clone();
A
Aaron Turon 已提交
524
            thread::spawn(move|| { inc(); tx2.send(()).unwrap(); });
525 526
        }

527
        drop(tx);
528
        for _ in 0..2 * K {
529
            rx.recv().unwrap();
530
        }
N
NODA, Kai 已提交
531
        assert_eq!(unsafe {CNT}, J * K * 2);
532
        unsafe {
N
NODA, Kai 已提交
533
            M.destroy();
534 535 536 537
        }
    }

    #[test]
A
Alex Crichton 已提交
538 539
    fn try_lock() {
        let m = Mutex::new(());
540
        *m.try_lock().unwrap() = ();
541
    }
A
Alex Crichton 已提交
542

543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
    #[test]
    fn test_into_inner() {
        let m = Mutex::new(NonCopy(10));
        assert_eq!(m.into_inner().unwrap(), NonCopy(10));
    }

    #[test]
    fn test_into_inner_drop() {
        struct Foo(Arc<AtomicUsize>);
        impl Drop for Foo {
            fn drop(&mut self) {
                self.0.fetch_add(1, Ordering::SeqCst);
            }
        }
        let num_drops = Arc::new(AtomicUsize::new(0));
        let m = Mutex::new(Foo(num_drops.clone()));
        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        {
            let _inner = m.into_inner().unwrap();
            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
        }
        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
    }

    #[test]
    fn test_into_inner_poison() {
        let m = Arc::new(Mutex::new(NonCopy(10)));
        let m2 = m.clone();
        let _ = thread::spawn(move || {
            let _lock = m2.lock().unwrap();
            panic!("test panic in inner thread to poison mutex");
        }).join();

        assert!(m.is_poisoned());
        match Arc::try_unwrap(m).unwrap().into_inner() {
            Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
            Ok(x) => panic!("into_inner of poisoned Mutex is Ok: {:?}", x),
        }
    }

    #[test]
    fn test_get_mut() {
        let mut m = Mutex::new(NonCopy(10));
        *m.get_mut().unwrap() = NonCopy(20);
        assert_eq!(m.into_inner().unwrap(), NonCopy(20));
    }

    #[test]
    fn test_get_mut_poison() {
        let m = Arc::new(Mutex::new(NonCopy(10)));
        let m2 = m.clone();
        let _ = thread::spawn(move || {
            let _lock = m2.lock().unwrap();
            panic!("test panic in inner thread to poison mutex");
        }).join();

        assert!(m.is_poisoned());
        match Arc::try_unwrap(m).unwrap().get_mut() {
            Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
            Ok(x) => panic!("get_mut of poisoned Mutex is Ok: {:?}", x),
        }
    }

A
Alex Crichton 已提交
606 607
    #[test]
    fn test_mutex_arc_condvar() {
608 609
        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
        let packet2 = Packet(packet.0.clone());
A
Alex Crichton 已提交
610
        let (tx, rx) = channel();
A
Aaron Turon 已提交
611
        let _t = thread::spawn(move|| {
A
Alex Crichton 已提交
612
            // wait until parent gets in
613
            rx.recv().unwrap();
614
            let &(ref lock, ref cvar) = &*packet2.0;
615
            let mut lock = lock.lock().unwrap();
A
Alex Crichton 已提交
616 617 618 619
            *lock = true;
            cvar.notify_one();
        });

620
        let &(ref lock, ref cvar) = &*packet.0;
621
        let mut lock = lock.lock().unwrap();
622
        tx.send(()).unwrap();
A
Alex Crichton 已提交
623 624
        assert!(!*lock);
        while !*lock {
625
            lock = cvar.wait(lock).unwrap();
A
Alex Crichton 已提交
626 627 628 629 630
        }
    }

    #[test]
    fn test_arc_condvar_poison() {
T
Tobias Bucher 已提交
631
        let packet = Packet(Arc::new((Mutex::new(1), Condvar::new())));
632
        let packet2 = Packet(packet.0.clone());
A
Alex Crichton 已提交
633 634
        let (tx, rx) = channel();

A
Aaron Turon 已提交
635
        let _t = thread::spawn(move || -> () {
636
            rx.recv().unwrap();
637
            let &(ref lock, ref cvar) = &*packet2.0;
638
            let _g = lock.lock().unwrap();
A
Alex Crichton 已提交
639 640 641 642 643
            cvar.notify_one();
            // Parent should fail when it wakes up.
            panic!();
        });

644
        let &(ref lock, ref cvar) = &*packet.0;
645
        let mut lock = lock.lock().unwrap();
646
        tx.send(()).unwrap();
A
Alex Crichton 已提交
647
        while *lock == 1 {
648 649 650 651 652 653 654
            match cvar.wait(lock) {
                Ok(l) => {
                    lock = l;
                    assert_eq!(*lock, 1);
                }
                Err(..) => break,
            }
A
Alex Crichton 已提交
655 656 657 658 659
        }
    }

    #[test]
    fn test_mutex_arc_poison() {
T
Tobias Bucher 已提交
660
        let arc = Arc::new(Mutex::new(1));
661
        assert!(!arc.is_poisoned());
A
Alex Crichton 已提交
662
        let arc2 = arc.clone();
A
Aaron Turon 已提交
663
        let _ = thread::spawn(move|| {
664
            let lock = arc2.lock().unwrap();
A
Alex Crichton 已提交
665
            assert_eq!(*lock, 2);
A
Aaron Turon 已提交
666
        }).join();
667
        assert!(arc.lock().is_err());
668
        assert!(arc.is_poisoned());
A
Alex Crichton 已提交
669 670 671 672 673 674
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
T
Tobias Bucher 已提交
675
        let arc = Arc::new(Mutex::new(1));
A
Alex Crichton 已提交
676 677
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
A
Aaron Turon 已提交
678
        let _t = thread::spawn(move|| {
679
            let lock = arc2.lock().unwrap();
680
            let lock2 = lock.lock().unwrap();
A
Alex Crichton 已提交
681
            assert_eq!(*lock2, 1);
682
            tx.send(()).unwrap();
A
Alex Crichton 已提交
683
        });
684
        rx.recv().unwrap();
A
Alex Crichton 已提交
685 686 687 688
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
T
Tobias Bucher 已提交
689
        let arc = Arc::new(Mutex::new(1));
A
Alex Crichton 已提交
690
        let arc2 = arc.clone();
A
Aaron Turon 已提交
691
        let _ = thread::spawn(move|| -> () {
A
Alex Crichton 已提交
692
            struct Unwinder {
N
Nick Cameron 已提交
693
                i: Arc<Mutex<i32>>,
A
Alex Crichton 已提交
694 695 696
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
697
                    *self.i.lock().unwrap() += 1;
A
Alex Crichton 已提交
698 699 700 701
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
A
Aaron Turon 已提交
702
        }).join();
703
        let lock = arc.lock().unwrap();
A
Alex Crichton 已提交
704 705
        assert_eq!(*lock, 2);
    }
706

707 708 709 710 711 712 713 714 715 716 717
    #[test]
    fn test_mutex_unsized() {
        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
        {
            let b = &mut *mutex.lock().unwrap();
            b[0] = 4;
            b[2] = 5;
        }
        let comp: &[i32] = &[4, 2, 5];
        assert_eq!(&*mutex.lock().unwrap(), comp);
    }
718
}