]> git.lizzy.rs Git - rust.git/blob - src/libstd/sync/mutex.rs
Fix misspelled comments.
[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 prelude::v1::*;
12
13 use cell::UnsafeCell;
14 use kinds::marker;
15 use ops::{Deref, DerefMut};
16 use sync::poison::{self, TryLockError, TryLockResult, LockResult};
17 use sys_common::mutex as sys;
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 /// lock. Once a mutex is poisoned, all other tasks 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_guard` 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 /// # Examples
47 ///
48 /// ```rust
49 /// use std::sync::{Arc, Mutex};
50 /// use std::thread::Thread;
51 /// use std::sync::mpsc::channel;
52 ///
53 /// const N: uint = 10;
54 ///
55 /// // Spawn a few threads to increment a shared variable (non-atomically), and
56 /// // let the main thread know once all increments are done.
57 /// //
58 /// // Here we're using an Arc to share memory among tasks, and the data inside
59 /// // the Arc is protected with a mutex.
60 /// let data = Arc::new(Mutex::new(0));
61 ///
62 /// let (tx, rx) = channel();
63 /// for _ in range(0u, 10) {
64 ///     let (data, tx) = (data.clone(), tx.clone());
65 ///     Thread::spawn(move || {
66 ///         // The shared static can only be accessed once the lock is held.
67 ///         // Our non-atomic increment is safe because we're the only thread
68 ///         // which can access the shared state when the lock is held.
69 ///         //
70 ///         // We unwrap() the return value to assert that we are not expecting
71 ///         // tasks to ever fail while holding the lock.
72 ///         let mut data = data.lock().unwrap();
73 ///         *data += 1;
74 ///         if *data == N {
75 ///             tx.send(()).unwrap();
76 ///         }
77 ///         // the lock is unlocked here when `data` goes out of scope.
78 ///     }).detach();
79 /// }
80 ///
81 /// rx.recv().unwrap();
82 /// ```
83 ///
84 /// To recover from a poisoned mutex:
85 ///
86 /// ```rust
87 /// use std::sync::{Arc, Mutex};
88 /// use std::thread::Thread;
89 ///
90 /// let lock = Arc::new(Mutex::new(0u));
91 /// let lock2 = lock.clone();
92 ///
93 /// let _ = Thread::spawn(move || -> () {
94 ///     // This thread will acquire the mutex first, unwrapping the result of
95 ///     // `lock` because the lock has not been poisoned.
96 ///     let _lock = lock2.lock().unwrap();
97 ///
98 ///     // This panic while holding the lock (`_guard` is in scope) will poison
99 ///     // the mutex.
100 ///     panic!();
101 /// }).join();
102 ///
103 /// // The lock is poisoned by this point, but the returned result can be
104 /// // pattern matched on to return the underlying guard on both branches.
105 /// let mut guard = match lock.lock() {
106 ///     Ok(guard) => guard,
107 ///     Err(poisoned) => poisoned.into_guard(),
108 /// };
109 ///
110 /// *guard += 1;
111 /// ```
112 #[stable]
113 pub struct Mutex<T> {
114     // Note that this static mutex is in a *box*, not inlined into the struct
115     // itself. Once a native mutex has been used once, its address can never
116     // change (it can't be moved). This mutex type can be safely moved at any
117     // time, so to ensure that the native mutex is used correctly we box the
118     // inner lock to give it a constant address.
119     inner: Box<StaticMutex>,
120     data: UnsafeCell<T>,
121 }
122
123 unsafe impl<T:Send> Send for Mutex<T> { }
124
125 unsafe impl<T:Send> Sync for Mutex<T> { }
126
127 /// The static mutex type is provided to allow for static allocation of mutexes.
128 ///
129 /// Note that this is a separate type because using a Mutex correctly means that
130 /// it needs to have a destructor run. In Rust, statics are not allowed to have
131 /// destructors. As a result, a `StaticMutex` has one extra method when compared
132 /// to a `Mutex`, a `destroy` method. This method is unsafe to call, and
133 /// documentation can be found directly on the method.
134 ///
135 /// # Example
136 ///
137 /// ```rust
138 /// use std::sync::{StaticMutex, MUTEX_INIT};
139 ///
140 /// static LOCK: StaticMutex = MUTEX_INIT;
141 ///
142 /// {
143 ///     let _g = LOCK.lock().unwrap();
144 ///     // do some productive work
145 /// }
146 /// // lock is unlocked here.
147 /// ```
148 #[unstable = "may be merged with Mutex in the future"]
149 pub struct StaticMutex {
150     lock: sys::Mutex,
151     poison: poison::Flag,
152 }
153
154 unsafe impl Sync for StaticMutex {}
155
156 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
157 /// dropped (falls out of scope), the lock will be unlocked.
158 ///
159 /// The data protected by the mutex can be access through this guard via its
160 /// Deref and DerefMut implementations
161 #[must_use]
162 #[stable]
163 pub struct MutexGuard<'a, T: 'a> {
164     // funny underscores due to how Deref/DerefMut currently work (they
165     // disregard field privacy).
166     __lock: &'a StaticMutex,
167     __data: &'a UnsafeCell<T>,
168     __poison: poison::Guard,
169     __marker: marker::NoSend,
170 }
171
172 /// Static initialization of a mutex. This constant can be used to initialize
173 /// other mutex constants.
174 #[unstable = "may be merged with Mutex in the future"]
175 pub const MUTEX_INIT: StaticMutex = StaticMutex {
176     lock: sys::MUTEX_INIT,
177     poison: poison::FLAG_INIT,
178 };
179
180 impl<T: Send> Mutex<T> {
181     /// Creates a new mutex in an unlocked state ready for use.
182     #[stable]
183     pub fn new(t: T) -> Mutex<T> {
184         Mutex {
185             inner: box MUTEX_INIT,
186             data: UnsafeCell::new(t),
187         }
188     }
189
190     /// Acquires a mutex, blocking the current task until it is able to do so.
191     ///
192     /// This function will block the local task until it is available to acquire
193     /// the mutex. Upon returning, the task is the only task with the mutex
194     /// held. An RAII guard is returned to allow scoped unlock of the lock. When
195     /// the guard goes out of scope, the mutex will be unlocked.
196     ///
197     /// # Failure
198     ///
199     /// If another user of this mutex panicked while holding the mutex, then
200     /// this call will return an error once the mutex is acquired.
201     #[stable]
202     pub fn lock(&self) -> LockResult<MutexGuard<T>> {
203         unsafe { self.inner.lock.lock() }
204         MutexGuard::new(&*self.inner, &self.data)
205     }
206
207     /// Attempts to acquire this lock.
208     ///
209     /// If the lock could not be acquired at this time, then `None` is returned.
210     /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
211     /// guard is dropped.
212     ///
213     /// This function does not block.
214     ///
215     /// # Failure
216     ///
217     /// If another user of this mutex panicked while holding the mutex, then
218     /// this call will return failure if the mutex would otherwise be
219     /// acquired.
220     #[stable]
221     pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> {
222         if unsafe { self.inner.lock.try_lock() } {
223             Ok(try!(MutexGuard::new(&*self.inner, &self.data)))
224         } else {
225             Err(TryLockError::WouldBlock)
226         }
227     }
228 }
229
230 #[unsafe_destructor]
231 #[stable]
232 impl<T: Send> Drop for Mutex<T> {
233     fn drop(&mut self) {
234         // This is actually safe b/c we know that there is no further usage of
235         // this mutex (it's up to the user to arrange for a mutex to get
236         // dropped, that's not our job)
237         unsafe { self.inner.lock.destroy() }
238     }
239 }
240
241 struct Dummy(UnsafeCell<()>);
242 unsafe impl Sync for Dummy {}
243 static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
244
245 impl StaticMutex {
246     /// Acquires this lock, see `Mutex::lock`
247     #[inline]
248     #[unstable = "may be merged with Mutex in the future"]
249     pub fn lock(&'static self) -> LockResult<MutexGuard<()>> {
250         unsafe { self.lock.lock() }
251         MutexGuard::new(self, &DUMMY.0)
252     }
253
254     /// Attempts to grab this lock, see `Mutex::try_lock`
255     #[inline]
256     #[unstable = "may be merged with Mutex in the future"]
257     pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> {
258         if unsafe { self.lock.try_lock() } {
259             Ok(try!(MutexGuard::new(self, &DUMMY.0)))
260         } else {
261             Err(TryLockError::WouldBlock)
262         }
263     }
264
265     /// Deallocates resources associated with this static mutex.
266     ///
267     /// This method is unsafe because it provides no guarantees that there are
268     /// no active users of this mutex, and safety is not guaranteed if there are
269     /// active users of this mutex.
270     ///
271     /// This method is required to ensure that there are no memory leaks on
272     /// *all* platforms. It may be the case that some platforms do not leak
273     /// memory if this method is not called, but this is not guaranteed to be
274     /// true on all platforms.
275     #[unstable = "may be merged with Mutex in the future"]
276     pub unsafe fn destroy(&'static self) {
277         self.lock.destroy()
278     }
279 }
280
281 impl<'mutex, T> MutexGuard<'mutex, T> {
282     fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
283            -> LockResult<MutexGuard<'mutex, T>> {
284         poison::map_result(lock.poison.borrow(), |guard| {
285             MutexGuard {
286                 __lock: lock,
287                 __data: data,
288                 __poison: guard,
289                 __marker: marker::NoSend,
290             }
291         })
292     }
293 }
294
295 #[stable]
296 impl<'mutex, T> Deref for MutexGuard<'mutex, T> {
297     type Target = T;
298
299     fn deref<'a>(&'a self) -> &'a T {
300         unsafe { &*self.__data.get() }
301     }
302 }
303 #[stable]
304 impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> {
305     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
306         unsafe { &mut *self.__data.get() }
307     }
308 }
309
310 #[unsafe_destructor]
311 #[stable]
312 impl<'a, T> Drop for MutexGuard<'a, T> {
313     #[inline]
314     fn drop(&mut self) {
315         unsafe {
316             self.__lock.poison.done(&self.__poison);
317             self.__lock.lock.unlock();
318         }
319     }
320 }
321
322 pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
323     &guard.__lock.lock
324 }
325
326 pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
327     &guard.__lock.poison
328 }
329
330 #[cfg(test)]
331 mod test {
332     use prelude::v1::*;
333
334     use sync::mpsc::channel;
335     use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
336     use thread::Thread;
337
338     struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
339
340     unsafe impl<T:'static+Send> Send for Packet<T> {}
341     unsafe impl<T> Sync for Packet<T> {}
342
343     #[test]
344     fn smoke() {
345         let m = Mutex::new(());
346         drop(m.lock().unwrap());
347         drop(m.lock().unwrap());
348     }
349
350     #[test]
351     fn smoke_static() {
352         static M: StaticMutex = MUTEX_INIT;
353         unsafe {
354             drop(M.lock().unwrap());
355             drop(M.lock().unwrap());
356             M.destroy();
357         }
358     }
359
360     #[test]
361     fn lots_and_lots() {
362         static M: StaticMutex = MUTEX_INIT;
363         static mut CNT: uint = 0;
364         static J: uint = 1000;
365         static K: uint = 3;
366
367         fn inc() {
368             for _ in range(0, J) {
369                 unsafe {
370                     let _g = M.lock().unwrap();
371                     CNT += 1;
372                 }
373             }
374         }
375
376         let (tx, rx) = channel();
377         for _ in range(0, K) {
378             let tx2 = tx.clone();
379             Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach();
380             let tx2 = tx.clone();
381             Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach();
382         }
383
384         drop(tx);
385         for _ in range(0, 2 * K) {
386             rx.recv().unwrap();
387         }
388         assert_eq!(unsafe {CNT}, J * K * 2);
389         unsafe {
390             M.destroy();
391         }
392     }
393
394     #[test]
395     fn try_lock() {
396         let m = Mutex::new(());
397         *m.try_lock().unwrap() = ();
398     }
399
400     #[test]
401     fn test_mutex_arc_condvar() {
402         let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
403         let packet2 = Packet(packet.0.clone());
404         let (tx, rx) = channel();
405         let _t = Thread::spawn(move|| {
406             // wait until parent gets in
407             rx.recv().unwrap();
408             let &(ref lock, ref cvar) = &*packet2.0;
409             let mut lock = lock.lock().unwrap();
410             *lock = true;
411             cvar.notify_one();
412         });
413
414         let &(ref lock, ref cvar) = &*packet.0;
415         let mut lock = lock.lock().unwrap();
416         tx.send(()).unwrap();
417         assert!(!*lock);
418         while !*lock {
419             lock = cvar.wait(lock).unwrap();
420         }
421     }
422
423     #[test]
424     fn test_arc_condvar_poison() {
425         let packet = Packet(Arc::new((Mutex::new(1i), Condvar::new())));
426         let packet2 = Packet(packet.0.clone());
427         let (tx, rx) = channel();
428
429         let _t = Thread::spawn(move || -> () {
430             rx.recv().unwrap();
431             let &(ref lock, ref cvar) = &*packet2.0;
432             let _g = lock.lock().unwrap();
433             cvar.notify_one();
434             // Parent should fail when it wakes up.
435             panic!();
436         });
437
438         let &(ref lock, ref cvar) = &*packet.0;
439         let mut lock = lock.lock().unwrap();
440         tx.send(()).unwrap();
441         while *lock == 1 {
442             match cvar.wait(lock) {
443                 Ok(l) => {
444                     lock = l;
445                     assert_eq!(*lock, 1);
446                 }
447                 Err(..) => break,
448             }
449         }
450     }
451
452     #[test]
453     fn test_mutex_arc_poison() {
454         let arc = Arc::new(Mutex::new(1i));
455         let arc2 = arc.clone();
456         let _ = Thread::spawn(move|| {
457             let lock = arc2.lock().unwrap();
458             assert_eq!(*lock, 2);
459         }).join();
460         assert!(arc.lock().is_err());
461     }
462
463     #[test]
464     fn test_mutex_arc_nested() {
465         // Tests nested mutexes and access
466         // to underlying data.
467         let arc = Arc::new(Mutex::new(1i));
468         let arc2 = Arc::new(Mutex::new(arc));
469         let (tx, rx) = channel();
470         let _t = Thread::spawn(move|| {
471             let lock = arc2.lock().unwrap();
472             let lock2 = lock.lock().unwrap();
473             assert_eq!(*lock2, 1);
474             tx.send(()).unwrap();
475         });
476         rx.recv().unwrap();
477     }
478
479     #[test]
480     fn test_mutex_arc_access_in_unwind() {
481         let arc = Arc::new(Mutex::new(1i));
482         let arc2 = arc.clone();
483         let _ = Thread::spawn(move|| -> () {
484             struct Unwinder {
485                 i: Arc<Mutex<int>>,
486             }
487             impl Drop for Unwinder {
488                 fn drop(&mut self) {
489                     *self.i.lock().unwrap() += 1;
490                 }
491             }
492             let _u = Unwinder { i: arc2 };
493             panic!();
494         }).join();
495         let lock = arc.lock().unwrap();
496         assert_eq!(*lock, 2);
497     }
498 }