mutex.rs 21.5 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.

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

/// A mutual exclusion primitive useful for protecting shared data
///
A
Alex Crichton 已提交
22 23 24 25 26 27 28 29 30
/// 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
///
31 32
/// The mutexes in this module implement a strategy called "poisoning" where a
/// mutex is considered poisoned whenever a thread panics while holding the
33
/// lock. Once a mutex is poisoned, all other threads are unable to access the
34 35
/// data by default as it is likely tainted (some invariant is not being
/// upheld).
36
///
37 38 39 40 41 42
/// 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
43
/// data. The `PoisonError` type has an `into_inner` method which will return
44 45 46 47
/// the guard that would have otherwise been returned on a successful lock. This
/// allows access to the data, despite the lock being poisoned.
///
/// # Examples
48
///
49
/// ```
A
Alex Crichton 已提交
50
/// use std::sync::{Arc, Mutex};
A
Aaron Turon 已提交
51
/// use std::thread;
52
/// use std::sync::mpsc::channel;
53
///
N
Nick Cameron 已提交
54
/// const N: usize = 10;
55
///
A
Alex Crichton 已提交
56 57 58
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
/// //
59
/// // Here we're using an Arc to share memory among threads, and the data inside
A
Alex Crichton 已提交
60 61 62 63
/// // the Arc is protected with a mutex.
/// let data = Arc::new(Mutex::new(0));
///
/// let (tx, rx) = channel();
64
/// for _ in 0..10 {
A
Alex Crichton 已提交
65
///     let (data, tx) = (data.clone(), tx.clone());
A
Aaron Turon 已提交
66
///     thread::spawn(move || {
67
///         // The shared state can only be accessed once the lock is held.
A
Alex Crichton 已提交
68 69
///         // Our non-atomic increment is safe because we're the only thread
///         // which can access the shared state when the lock is held.
70 71
///         //
///         // We unwrap() the return value to assert that we are not expecting
72
///         // threads to ever fail while holding the lock.
73
///         let mut data = data.lock().unwrap();
A
Alex Crichton 已提交
74 75
///         *data += 1;
///         if *data == N {
76
///             tx.send(()).unwrap();
A
Alex Crichton 已提交
77 78
///         }
///         // the lock is unlocked here when `data` goes out of scope.
A
Aaron Turon 已提交
79
///     });
A
Alex Crichton 已提交
80 81
/// }
///
82
/// rx.recv().unwrap();
83
/// ```
84 85 86
///
/// To recover from a poisoned mutex:
///
87
/// ```
88
/// use std::sync::{Arc, Mutex};
A
Aaron Turon 已提交
89
/// use std::thread;
90
///
91
/// let lock = Arc::new(Mutex::new(0_u32));
92 93
/// let lock2 = lock.clone();
///
A
Aaron Turon 已提交
94
/// let _ = thread::spawn(move || -> () {
95 96
///     // This thread will acquire the mutex first, unwrapping the result of
///     // `lock` because the lock has not been poisoned.
97
///     let _guard = lock2.lock().unwrap();
98 99 100 101 102 103 104 105 106 107
///
///     // 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,
108
///     Err(poisoned) => poisoned.into_inner(),
109 110 111 112
/// };
///
/// *guard += 1;
/// ```
B
Brian Anderson 已提交
113
#[stable(feature = "rust1", since = "1.0.0")]
114
pub struct Mutex<T: ?Sized> {
A
Alex Crichton 已提交
115 116 117 118 119 120 121
    // Note that this mutex is in a *box*, not inlined into the struct 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<sys::Mutex>,
    poison: poison::Flag,
122
    data: UnsafeCell<T>,
123 124
}

125 126
// these are the only places where `T: Send` matters; all other
// functionality works fine on a single thread.
127
#[stable(feature = "rust1", since = "1.0.0")]
128
unsafe impl<T: ?Sized + Send> Send for Mutex<T> { }
129
#[stable(feature = "rust1", since = "1.0.0")]
130
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
F
Flavio Percoco 已提交
131

132 133
/// 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 已提交
134
///
S
ScottAbbey 已提交
135
/// The data protected by the mutex can be accessed through this guard via its
136
/// [`Deref`] and [`DerefMut`] implementations.
137
///
138
/// This structure is created by the [`lock`] and [`try_lock`] methods on
139 140
/// [`Mutex`].
///
141 142
/// [`Deref`]: ../../std/ops/trait.Deref.html
/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
143 144
/// [`lock`]: struct.Mutex.html#method.lock
/// [`try_lock`]: struct.Mutex.html#method.try_lock
145
/// [`Mutex`]: struct.Mutex.html
146
#[must_use]
B
Brian Anderson 已提交
147
#[stable(feature = "rust1", since = "1.0.0")]
148
pub struct MutexGuard<'a, T: ?Sized + 'a> {
A
Alex Crichton 已提交
149 150
    // funny underscores due to how Deref/DerefMut currently work (they
    // disregard field privacy).
A
Alex Crichton 已提交
151
    __lock: &'a Mutex<T>,
152
    __poison: poison::Guard,
153 154
}

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

158
impl<T> Mutex<T> {
A
Alex Crichton 已提交
159
    /// Creates a new mutex in an unlocked state ready for use.
160 161 162 163 164 165 166 167
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Mutex;
    ///
    /// let mutex = Mutex::new(0);
    /// ```
B
Brian Anderson 已提交
168
    #[stable(feature = "rust1", since = "1.0.0")]
A
Alex Crichton 已提交
169
    pub fn new(t: T) -> Mutex<T> {
170
        let mut m = Mutex {
A
Alex Crichton 已提交
171 172
            inner: box sys::Mutex::new(),
            poison: poison::Flag::new(),
173
            data: UnsafeCell::new(t),
174 175
        };
        unsafe {
A
Alex Crichton 已提交
176
            m.inner.init();
A
Alex Crichton 已提交
177
        }
178
        m
A
Alex Crichton 已提交
179
    }
180
}
A
Alex Crichton 已提交
181

182
impl<T: ?Sized> Mutex<T> {
183
    /// Acquires a mutex, blocking the current thread until it is able to do so.
A
Alex Crichton 已提交
184
    ///
185 186
    /// 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 已提交
187 188 189
    /// 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.
    ///
190
    /// The exact behavior on locking a mutex in the thread which already holds
191 192
    /// the lock is left unspecified. However, this function will not return on
    /// the second call (it might panic or deadlock, for example).
193
    ///
194
    /// # Errors
A
Alex Crichton 已提交
195 196
    ///
    /// If another user of this mutex panicked while holding the mutex, then
197
    /// this call will return an error once the mutex is acquired.
198 199 200 201 202
    ///
    /// # Panics
    ///
    /// This function might panic when called if the lock is already held by
    /// the current thread.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::{Arc, Mutex};
    /// use std::thread;
    ///
    /// let mutex = Arc::new(Mutex::new(0));
    /// let c_mutex = mutex.clone();
    ///
    /// thread::spawn(move || {
    ///     *c_mutex.lock().unwrap() = 10;
    /// }).join().expect("thread::spawn failed");
    /// assert_eq!(*mutex.lock().unwrap(), 10);
    /// ```
B
Brian Anderson 已提交
218
    #[stable(feature = "rust1", since = "1.0.0")]
219
    pub fn lock(&self) -> LockResult<MutexGuard<T>> {
220
        unsafe {
A
Alex Crichton 已提交
221 222
            self.inner.lock();
            MutexGuard::new(self)
223
        }
A
Alex Crichton 已提交
224 225 226 227
    }

    /// Attempts to acquire this lock.
    ///
228
    /// If the lock could not be acquired at this time, then `Err` is returned.
A
Alex Crichton 已提交
229 230 231 232 233
    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
    /// guard is dropped.
    ///
    /// This function does not block.
    ///
234
    /// # Errors
A
Alex Crichton 已提交
235 236
    ///
    /// If another user of this mutex panicked while holding the mutex, then
237
    /// this call will return failure if the mutex would otherwise be
A
Alex Crichton 已提交
238
    /// acquired.
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::{Arc, Mutex};
    /// use std::thread;
    ///
    /// let mutex = Arc::new(Mutex::new(0));
    /// let c_mutex = mutex.clone();
    ///
    /// thread::spawn(move || {
    ///     let mut lock = c_mutex.try_lock();
    ///     if let Ok(ref mut mutex) = lock {
    ///         **mutex = 10;
    ///     } else {
    ///         println!("try_lock failed");
    ///     }
    /// }).join().expect("thread::spawn failed");
    /// assert_eq!(*mutex.lock().unwrap(), 10);
    /// ```
B
Brian Anderson 已提交
259
    #[stable(feature = "rust1", since = "1.0.0")]
260
    pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
261
        unsafe {
A
Alex Crichton 已提交
262 263
            if self.inner.try_lock() {
                Ok(MutexGuard::new(self)?)
264 265 266
            } else {
                Err(TryLockError::WouldBlock)
            }
A
Alex Crichton 已提交
267
        }
268
    }
269

270
    /// Determines whether the lock is poisoned.
271 272
    ///
    /// If another thread is active, the lock can still become poisoned at any
273
    /// time. You should not trust a `false` value for program correctness
274
    /// without additional synchronization.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::{Arc, Mutex};
    /// use std::thread;
    ///
    /// let mutex = Arc::new(Mutex::new(0));
    /// let c_mutex = mutex.clone();
    ///
    /// let _ = thread::spawn(move || {
    ///     let _lock = c_mutex.lock().unwrap();
    ///     panic!(); // the mutex gets poisoned
    /// }).join();
    /// assert_eq!(mutex.is_poisoned(), true);
    /// ```
291
    #[inline]
292
    #[stable(feature = "sync_poison", since = "1.2.0")]
293
    pub fn is_poisoned(&self) -> bool {
A
Alex Crichton 已提交
294
        self.poison.get()
295
    }
296 297 298

    /// Consumes this mutex, returning the underlying data.
    ///
299
    /// # Errors
300 301 302
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return an error instead.
303 304 305 306 307 308 309 310 311
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Mutex;
    ///
    /// let mutex = Mutex::new(0);
    /// assert_eq!(mutex.into_inner().unwrap(), 0);
    /// ```
312
    #[stable(feature = "mutex_into_inner", since = "1.6.0")]
313 314
    pub fn into_inner(self) -> LockResult<T> where T: Sized {
        // We know statically that there are no outstanding references to
A
Alex Crichton 已提交
315
        // `self` so there's no need to lock the inner lock.
316 317 318 319 320
        //
        // 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 {
A
Alex Crichton 已提交
321 322 323 324
            // Like `let Mutex { inner, poison, data } = self`.
            let (inner, poison, data) = {
                let Mutex { ref inner, ref poison, ref data } = self;
                (ptr::read(inner), ptr::read(poison), ptr::read(data))
325 326
            };
            mem::forget(self);
A
Alex Crichton 已提交
327 328
            inner.destroy();  // Keep in sync with the `Drop` impl.
            drop(inner);
329

A
Alex Crichton 已提交
330
            poison::map_result(poison.borrow(), |_| data.into_inner())
331 332 333 334 335 336 337 338
        }
    }

    /// 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.
    ///
339
    /// # Errors
340 341 342
    ///
    /// If another user of this mutex panicked while holding the mutex, then
    /// this call will return an error instead.
343 344 345 346 347 348 349 350 351 352
    ///
    /// # Examples
    ///
    /// ```
    /// use std::sync::Mutex;
    ///
    /// let mut mutex = Mutex::new(0);
    /// *mutex.get_mut().unwrap() = 10;
    /// assert_eq!(*mutex.lock().unwrap(), 10);
    /// ```
353
    #[stable(feature = "mutex_get_mut", since = "1.6.0")]
354 355
    pub fn get_mut(&mut self) -> LockResult<&mut T> {
        // We know statically that there are no other references to `self`, so
A
Alex Crichton 已提交
356
        // there's no need to lock the inner lock.
357
        let data = unsafe { &mut *self.data.get() };
A
Alex Crichton 已提交
358
        poison::map_result(self.poison.borrow(), |_| data )
359
    }
A
Alex Crichton 已提交
360
}
361

B
Brian Anderson 已提交
362
#[stable(feature = "rust1", since = "1.0.0")]
363
unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex<T> {
A
Alex Crichton 已提交
364 365 366 367
    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)
368 369
        //
        // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
A
Alex Crichton 已提交
370
        unsafe { self.inner.destroy() }
A
Alex Crichton 已提交
371 372 373
    }
}

374 375
#[stable(feature = "mutex_default", since = "1.9.0")]
impl<T: ?Sized + Default> Default for Mutex<T> {
376
    /// Creates a `Mutex<T>`, with the `Default` value for T.
377 378 379 380 381
    fn default() -> Mutex<T> {
        Mutex::new(Default::default())
    }
}

382
#[stable(feature = "rust1", since = "1.0.0")]
383
impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
384 385
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.try_lock() {
386
            Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard),
387
            Err(TryLockError::Poisoned(err)) => {
388
                write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref())
389 390 391 392 393 394
            },
            Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
        }
    }
}

395
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
A
Alex Crichton 已提交
396
    unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
397 398 399 400 401 402 403
        poison::map_result(lock.poison.borrow(), |guard| {
            MutexGuard {
                __lock: lock,
                __poison: guard,
            }
        })
    }
A
Alex Crichton 已提交
404
}
405

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

A
Alex Crichton 已提交
410 411 412
    fn deref(&self) -> &T {
        unsafe { &*self.__lock.data.get() }
    }
A
Alex Crichton 已提交
413
}
414

B
Brian Anderson 已提交
415
#[stable(feature = "rust1", since = "1.0.0")]
416
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
A
Alex Crichton 已提交
417 418 419
    fn deref_mut(&mut self) -> &mut T {
        unsafe { &mut *self.__lock.data.get() }
    }
A
Alex Crichton 已提交
420 421
}

B
Brian Anderson 已提交
422
#[stable(feature = "rust1", since = "1.0.0")]
423
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
424
    #[inline]
425 426 427
    fn drop(&mut self) {
        unsafe {
            self.__lock.poison.done(&self.__poison);
A
Alex Crichton 已提交
428
            self.__lock.inner.unlock();
429 430 431 432
        }
    }
}

433
#[stable(feature = "std_debug", since = "1.16.0")]
434 435 436 437 438 439 440 441
impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("MutexGuard")
            .field("lock", &self.__lock)
            .finish()
    }
}

442
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
A
Alex Crichton 已提交
443
    &guard.__lock.inner
444 445
}

446
pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
447
    &guard.__lock.poison
448 449
}

450
#[cfg(all(test, not(target_os = "emscripten")))]
451
mod tests {
452
    use sync::mpsc::channel;
A
Alex Crichton 已提交
453
    use sync::{Arc, Mutex, Condvar};
454
    use sync::atomic::{AtomicUsize, Ordering};
A
Aaron Turon 已提交
455
    use thread;
456

457
    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
458

459 460 461
    #[derive(Eq, PartialEq, Debug)]
    struct NonCopy(i32);

462
    unsafe impl<T: Send> Send for Packet<T> {}
463 464
    unsafe impl<T> Sync for Packet<T> {}

465 466
    #[test]
    fn smoke() {
A
Alex Crichton 已提交
467
        let m = Mutex::new(());
468 469
        drop(m.lock().unwrap());
        drop(m.lock().unwrap());
470 471 472 473
    }

    #[test]
    fn lots_and_lots() {
474 475
        const J: u32 = 1000;
        const K: u32 = 3;
476

A
Alex Crichton 已提交
477 478 479
        let m = Arc::new(Mutex::new(0));

        fn inc(m: &Mutex<u32>) {
480
            for _ in 0..J {
A
Alex Crichton 已提交
481
                *m.lock().unwrap() += 1;
482 483 484
            }
        }

485
        let (tx, rx) = channel();
486
        for _ in 0..K {
487
            let tx2 = tx.clone();
A
Alex Crichton 已提交
488 489
            let m2 = m.clone();
            thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); });
490
            let tx2 = tx.clone();
A
Alex Crichton 已提交
491 492
            let m2 = m.clone();
            thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); });
493 494
        }

495
        drop(tx);
496
        for _ in 0..2 * K {
497
            rx.recv().unwrap();
498
        }
A
Alex Crichton 已提交
499
        assert_eq!(*m.lock().unwrap(), J * K * 2);
500 501 502
    }

    #[test]
A
Alex Crichton 已提交
503 504
    fn try_lock() {
        let m = Mutex::new(());
505
        *m.try_lock().unwrap() = ();
506
    }
A
Alex Crichton 已提交
507

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 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
    #[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 已提交
571 572
    #[test]
    fn test_mutex_arc_condvar() {
573 574
        let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
        let packet2 = Packet(packet.0.clone());
A
Alex Crichton 已提交
575
        let (tx, rx) = channel();
A
Aaron Turon 已提交
576
        let _t = thread::spawn(move|| {
A
Alex Crichton 已提交
577
            // wait until parent gets in
578
            rx.recv().unwrap();
579
            let &(ref lock, ref cvar) = &*packet2.0;
580
            let mut lock = lock.lock().unwrap();
A
Alex Crichton 已提交
581 582 583 584
            *lock = true;
            cvar.notify_one();
        });

585
        let &(ref lock, ref cvar) = &*packet.0;
586
        let mut lock = lock.lock().unwrap();
587
        tx.send(()).unwrap();
A
Alex Crichton 已提交
588 589
        assert!(!*lock);
        while !*lock {
590
            lock = cvar.wait(lock).unwrap();
A
Alex Crichton 已提交
591 592 593 594 595
        }
    }

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

A
Aaron Turon 已提交
600
        let _t = thread::spawn(move || -> () {
601
            rx.recv().unwrap();
602
            let &(ref lock, ref cvar) = &*packet2.0;
603
            let _g = lock.lock().unwrap();
A
Alex Crichton 已提交
604 605 606 607 608
            cvar.notify_one();
            // Parent should fail when it wakes up.
            panic!();
        });

609
        let &(ref lock, ref cvar) = &*packet.0;
610
        let mut lock = lock.lock().unwrap();
611
        tx.send(()).unwrap();
A
Alex Crichton 已提交
612
        while *lock == 1 {
613 614 615 616 617 618 619
            match cvar.wait(lock) {
                Ok(l) => {
                    lock = l;
                    assert_eq!(*lock, 1);
                }
                Err(..) => break,
            }
A
Alex Crichton 已提交
620 621 622 623 624
        }
    }

    #[test]
    fn test_mutex_arc_poison() {
T
Tobias Bucher 已提交
625
        let arc = Arc::new(Mutex::new(1));
626
        assert!(!arc.is_poisoned());
A
Alex Crichton 已提交
627
        let arc2 = arc.clone();
A
Aaron Turon 已提交
628
        let _ = thread::spawn(move|| {
629
            let lock = arc2.lock().unwrap();
A
Alex Crichton 已提交
630
            assert_eq!(*lock, 2);
A
Aaron Turon 已提交
631
        }).join();
632
        assert!(arc.lock().is_err());
633
        assert!(arc.is_poisoned());
A
Alex Crichton 已提交
634 635 636 637 638 639
    }

    #[test]
    fn test_mutex_arc_nested() {
        // Tests nested mutexes and access
        // to underlying data.
T
Tobias Bucher 已提交
640
        let arc = Arc::new(Mutex::new(1));
A
Alex Crichton 已提交
641 642
        let arc2 = Arc::new(Mutex::new(arc));
        let (tx, rx) = channel();
A
Aaron Turon 已提交
643
        let _t = thread::spawn(move|| {
644
            let lock = arc2.lock().unwrap();
645
            let lock2 = lock.lock().unwrap();
A
Alex Crichton 已提交
646
            assert_eq!(*lock2, 1);
647
            tx.send(()).unwrap();
A
Alex Crichton 已提交
648
        });
649
        rx.recv().unwrap();
A
Alex Crichton 已提交
650 651 652 653
    }

    #[test]
    fn test_mutex_arc_access_in_unwind() {
T
Tobias Bucher 已提交
654
        let arc = Arc::new(Mutex::new(1));
A
Alex Crichton 已提交
655
        let arc2 = arc.clone();
A
Aaron Turon 已提交
656
        let _ = thread::spawn(move|| -> () {
A
Alex Crichton 已提交
657
            struct Unwinder {
N
Nick Cameron 已提交
658
                i: Arc<Mutex<i32>>,
A
Alex Crichton 已提交
659 660 661
            }
            impl Drop for Unwinder {
                fn drop(&mut self) {
662
                    *self.i.lock().unwrap() += 1;
A
Alex Crichton 已提交
663 664 665 666
                }
            }
            let _u = Unwinder { i: arc2 };
            panic!();
A
Aaron Turon 已提交
667
        }).join();
668
        let lock = arc.lock().unwrap();
A
Alex Crichton 已提交
669 670
        assert_eq!(*lock, 2);
    }
671

672 673 674 675 676 677 678 679 680 681 682
    #[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);
    }
683
}