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