]> git.lizzy.rs Git - rust.git/blob - src/libstd/sync/condvar.rs
Rollup merge of #48507 - GuillaumeGomez:cstr-note, r=steveklabnik
[rust.git] / src / libstd / sync / condvar.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 fmt;
12 use sync::atomic::{AtomicUsize, Ordering};
13 use sync::{mutex, MutexGuard, PoisonError};
14 use sys_common::condvar as sys;
15 use sys_common::mutex as sys_mutex;
16 use sys_common::poison::{self, LockResult};
17 use time::{Duration, Instant};
18
19 /// A type indicating whether a timed wait on a condition variable returned
20 /// due to a time out or not.
21 ///
22 /// It is returned by the [`wait_timeout`] method.
23 ///
24 /// [`wait_timeout`]: struct.Condvar.html#method.wait_timeout
25 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
26 #[stable(feature = "wait_timeout", since = "1.5.0")]
27 pub struct WaitTimeoutResult(bool);
28
29 impl WaitTimeoutResult {
30     /// Returns whether the wait was known to have timed out.
31     ///
32     /// # Examples
33     ///
34     /// This example spawns a thread which will update the boolean value and
35     /// then wait 100 milliseconds before notifying the condvar.
36     ///
37     /// The main thread will wait with a timeout on the condvar and then leave
38     /// once the boolean has been updated and notified.
39     ///
40     /// ```
41     /// use std::sync::{Arc, Mutex, Condvar};
42     /// use std::thread;
43     /// use std::time::Duration;
44     ///
45     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
46     /// let pair2 = pair.clone();
47     ///
48     /// thread::spawn(move|| {
49     ///     let &(ref lock, ref cvar) = &*pair2;
50     ///
51     ///     // Let's wait 20 milliseconds before notifying the condvar.
52     ///     thread::sleep(Duration::from_millis(20));
53     ///
54     ///     let mut started = lock.lock().unwrap();
55     ///     // We update the boolean value.
56     ///     *started = true;
57     ///     cvar.notify_one();
58     /// });
59     ///
60     /// // Wait for the thread to start up.
61     /// let &(ref lock, ref cvar) = &*pair;
62     /// let mut started = lock.lock().unwrap();
63     /// loop {
64     ///     // Let's put a timeout on the condvar's wait.
65     ///     let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
66     ///     // 10 milliseconds have passed, or maybe the value changed!
67     ///     started = result.0;
68     ///     if *started == true {
69     ///         // We received the notification and the value has been updated, we can leave.
70     ///         break
71     ///     }
72     /// }
73     /// ```
74     #[stable(feature = "wait_timeout", since = "1.5.0")]
75     pub fn timed_out(&self) -> bool {
76         self.0
77     }
78 }
79
80 /// A Condition Variable
81 ///
82 /// Condition variables represent the ability to block a thread such that it
83 /// consumes no CPU time while waiting for an event to occur. Condition
84 /// variables are typically associated with a boolean predicate (a condition)
85 /// and a mutex. The predicate is always verified inside of the mutex before
86 /// determining that a thread must block.
87 ///
88 /// Functions in this module will block the current **thread** of execution and
89 /// are bindings to system-provided condition variables where possible. Note
90 /// that this module places one additional restriction over the system condition
91 /// variables: each condvar can be used with precisely one mutex at runtime. Any
92 /// attempt to use multiple mutexes on the same condition variable will result
93 /// in a runtime panic. If this is not desired, then the unsafe primitives in
94 /// `sys` do not have this restriction but may result in undefined behavior.
95 ///
96 /// # Examples
97 ///
98 /// ```
99 /// use std::sync::{Arc, Mutex, Condvar};
100 /// use std::thread;
101 ///
102 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
103 /// let pair2 = pair.clone();
104 ///
105 /// // Inside of our lock, spawn a new thread, and then wait for it to start.
106 /// thread::spawn(move|| {
107 ///     let &(ref lock, ref cvar) = &*pair2;
108 ///     let mut started = lock.lock().unwrap();
109 ///     *started = true;
110 ///     // We notify the condvar that the value has changed.
111 ///     cvar.notify_one();
112 /// });
113 ///
114 /// // Wait for the thread to start up.
115 /// let &(ref lock, ref cvar) = &*pair;
116 /// let mut started = lock.lock().unwrap();
117 /// while !*started {
118 ///     started = cvar.wait(started).unwrap();
119 /// }
120 /// ```
121 #[stable(feature = "rust1", since = "1.0.0")]
122 pub struct Condvar {
123     inner: Box<sys::Condvar>,
124     mutex: AtomicUsize,
125 }
126
127 impl Condvar {
128     /// Creates a new condition variable which is ready to be waited on and
129     /// notified.
130     ///
131     /// # Examples
132     ///
133     /// ```
134     /// use std::sync::Condvar;
135     ///
136     /// let condvar = Condvar::new();
137     /// ```
138     #[stable(feature = "rust1", since = "1.0.0")]
139     pub fn new() -> Condvar {
140         let mut c = Condvar {
141             inner: box sys::Condvar::new(),
142             mutex: AtomicUsize::new(0),
143         };
144         unsafe {
145             c.inner.init();
146         }
147         c
148     }
149
150     /// Blocks the current thread until this condition variable receives a
151     /// notification.
152     ///
153     /// This function will atomically unlock the mutex specified (represented by
154     /// `guard`) and block the current thread. This means that any calls
155     /// to [`notify_one`] or [`notify_all`] which happen logically after the
156     /// mutex is unlocked are candidates to wake this thread up. When this
157     /// function call returns, the lock specified will have been re-acquired.
158     ///
159     /// Note that this function is susceptible to spurious wakeups. Condition
160     /// variables normally have a boolean predicate associated with them, and
161     /// the predicate must always be checked each time this function returns to
162     /// protect against spurious wakeups.
163     ///
164     /// # Errors
165     ///
166     /// This function will return an error if the mutex being waited on is
167     /// poisoned when this thread re-acquires the lock. For more information,
168     /// see information about [poisoning] on the [`Mutex`] type.
169     ///
170     /// # Panics
171     ///
172     /// This function will [`panic!`] if it is used with more than one mutex
173     /// over time. Each condition variable is dynamically bound to exactly one
174     /// mutex to ensure defined behavior across platforms. If this functionality
175     /// is not desired, then unsafe primitives in `sys` are provided.
176     ///
177     /// [`notify_one`]: #method.notify_one
178     /// [`notify_all`]: #method.notify_all
179     /// [poisoning]: ../sync/struct.Mutex.html#poisoning
180     /// [`Mutex`]: ../sync/struct.Mutex.html
181     /// [`panic!`]: ../../std/macro.panic.html
182     ///
183     /// # Examples
184     ///
185     /// ```
186     /// use std::sync::{Arc, Mutex, Condvar};
187     /// use std::thread;
188     ///
189     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
190     /// let pair2 = pair.clone();
191     ///
192     /// thread::spawn(move|| {
193     ///     let &(ref lock, ref cvar) = &*pair2;
194     ///     let mut started = lock.lock().unwrap();
195     ///     *started = true;
196     ///     // We notify the condvar that the value has changed.
197     ///     cvar.notify_one();
198     /// });
199     ///
200     /// // Wait for the thread to start up.
201     /// let &(ref lock, ref cvar) = &*pair;
202     /// let mut started = lock.lock().unwrap();
203     /// // As long as the value inside the `Mutex` is false, we wait.
204     /// while !*started {
205     ///     started = cvar.wait(started).unwrap();
206     /// }
207     /// ```
208     #[stable(feature = "rust1", since = "1.0.0")]
209     pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
210                        -> LockResult<MutexGuard<'a, T>> {
211         let poisoned = unsafe {
212             let lock = mutex::guard_lock(&guard);
213             self.verify(lock);
214             self.inner.wait(lock);
215             mutex::guard_poison(&guard).get()
216         };
217         if poisoned {
218             Err(PoisonError::new(guard))
219         } else {
220             Ok(guard)
221         }
222     }
223
224     /// Blocks the current thread until this condition variable receives a
225     /// notification and the required condition is met. Spurious wakeups are
226     /// ignored and this function will only return once the condition has been
227     /// met.
228     ///
229     /// This function will atomically unlock the mutex specified (represented by
230     /// `guard`) and block the current thread. This means that any calls
231     /// to [`notify_one`] or [`notify_all`] which happen logically after the
232     /// mutex is unlocked are candidates to wake this thread up. When this
233     /// function call returns, the lock specified will have been re-acquired.
234     ///
235     /// # Errors
236     ///
237     /// This function will return an error if the mutex being waited on is
238     /// poisoned when this thread re-acquires the lock. For more information,
239     /// see information about [poisoning] on the [`Mutex`] type.
240     ///
241     /// [`notify_one`]: #method.notify_one
242     /// [`notify_all`]: #method.notify_all
243     /// [poisoning]: ../sync/struct.Mutex.html#poisoning
244     /// [`Mutex`]: ../sync/struct.Mutex.html
245     ///
246     /// # Examples
247     ///
248     /// ```
249     /// #![feature(wait_until)]
250     ///
251     /// use std::sync::{Arc, Mutex, Condvar};
252     /// use std::thread;
253     ///
254     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
255     /// let pair2 = pair.clone();
256     ///
257     /// thread::spawn(move|| {
258     ///     let &(ref lock, ref cvar) = &*pair2;
259     ///     let mut started = lock.lock().unwrap();
260     ///     *started = true;
261     ///     // We notify the condvar that the value has changed.
262     ///     cvar.notify_one();
263     /// });
264     ///
265     /// // Wait for the thread to start up.
266     /// let &(ref lock, ref cvar) = &*pair;
267     /// // As long as the value inside the `Mutex` is false, we wait.
268     /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
269     /// ```
270     #[unstable(feature = "wait_until", issue = "47960")]
271     pub fn wait_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
272                                 mut condition: F)
273                                 -> LockResult<MutexGuard<'a, T>>
274                                 where F: FnMut(&mut T) -> bool {
275         while !condition(&mut *guard) {
276             guard = self.wait(guard)?;
277         }
278         Ok(guard)
279     }
280
281
282     /// Waits on this condition variable for a notification, timing out after a
283     /// specified duration.
284     ///
285     /// The semantics of this function are equivalent to [`wait`]
286     /// except that the thread will be blocked for roughly no longer
287     /// than `ms` milliseconds. This method should not be used for
288     /// precise timing due to anomalies such as preemption or platform
289     /// differences that may not cause the maximum amount of time
290     /// waited to be precisely `ms`.
291     ///
292     /// Note that the best effort is made to ensure that the time waited is
293     /// measured with a monotonic clock, and not affected by the changes made to
294     /// the system time.
295     ///
296     /// The returned boolean is `false` only if the timeout is known
297     /// to have elapsed.
298     ///
299     /// Like [`wait`], the lock specified will be re-acquired when this function
300     /// returns, regardless of whether the timeout elapsed or not.
301     ///
302     /// [`wait`]: #method.wait
303     ///
304     /// # Examples
305     ///
306     /// ```
307     /// use std::sync::{Arc, Mutex, Condvar};
308     /// use std::thread;
309     ///
310     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
311     /// let pair2 = pair.clone();
312     ///
313     /// thread::spawn(move|| {
314     ///     let &(ref lock, ref cvar) = &*pair2;
315     ///     let mut started = lock.lock().unwrap();
316     ///     *started = true;
317     ///     // We notify the condvar that the value has changed.
318     ///     cvar.notify_one();
319     /// });
320     ///
321     /// // Wait for the thread to start up.
322     /// let &(ref lock, ref cvar) = &*pair;
323     /// let mut started = lock.lock().unwrap();
324     /// // As long as the value inside the `Mutex` is false, we wait.
325     /// loop {
326     ///     let result = cvar.wait_timeout_ms(started, 10).unwrap();
327     ///     // 10 milliseconds have passed, or maybe the value changed!
328     ///     started = result.0;
329     ///     if *started == true {
330     ///         // We received the notification and the value has been updated, we can leave.
331     ///         break
332     ///     }
333     /// }
334     /// ```
335     #[stable(feature = "rust1", since = "1.0.0")]
336     #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::sync::Condvar::wait_timeout`")]
337     pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
338                                   -> LockResult<(MutexGuard<'a, T>, bool)> {
339         let res = self.wait_timeout(guard, Duration::from_millis(ms as u64));
340         poison::map_result(res, |(a, b)| {
341             (a, !b.timed_out())
342         })
343     }
344
345     /// Waits on this condition variable for a notification, timing out after a
346     /// specified duration.
347     ///
348     /// The semantics of this function are equivalent to [`wait`] except that
349     /// the thread will be blocked for roughly no longer than `dur`. This
350     /// method should not be used for precise timing due to anomalies such as
351     /// preemption or platform differences that may not cause the maximum
352     /// amount of time waited to be precisely `dur`.
353     ///
354     /// Note that the best effort is made to ensure that the time waited is
355     /// measured with a monotonic clock, and not affected by the changes made to
356     /// the system time.  This function is susceptible to spurious wakeups.
357     /// Condition variables normally have a boolean predicate associated with
358     /// them, and the predicate must always be checked each time this function
359     /// returns to protect against spurious wakeups.  Additionally, it is
360     /// typically desirable for the time-out to not exceed some duration in
361     /// spite of spurious wakes, thus the sleep-duration is decremented by the
362     /// amount slept.  Alternatively, use the `wait_timeout_until` method
363     /// to wait until a condition is met with a total time-out regardless
364     /// of spurious wakes.
365     ///
366     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
367     /// known to have elapsed.
368     ///
369     /// Like [`wait`], the lock specified will be re-acquired when this function
370     /// returns, regardless of whether the timeout elapsed or not.
371     ///
372     /// [`wait`]: #method.wait
373     /// [`wait_timeout_until`]: #method.wait_timeout_until
374     /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
375     ///
376     /// # Examples
377     ///
378     /// ```
379     /// use std::sync::{Arc, Mutex, Condvar};
380     /// use std::thread;
381     /// use std::time::Duration;
382     ///
383     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
384     /// let pair2 = pair.clone();
385     ///
386     /// thread::spawn(move|| {
387     ///     let &(ref lock, ref cvar) = &*pair2;
388     ///     let mut started = lock.lock().unwrap();
389     ///     *started = true;
390     ///     // We notify the condvar that the value has changed.
391     ///     cvar.notify_one();
392     /// });
393     ///
394     /// // wait for the thread to start up
395     /// let &(ref lock, ref cvar) = &*pair;
396     /// let mut started = lock.lock().unwrap();
397     /// // as long as the value inside the `Mutex` is false, we wait
398     /// loop {
399     ///     let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
400     ///     // 10 milliseconds have passed, or maybe the value changed!
401     ///     started = result.0;
402     ///     if *started == true {
403     ///         // We received the notification and the value has been updated, we can leave.
404     ///         break
405     ///     }
406     /// }
407     /// ```
408     #[stable(feature = "wait_timeout", since = "1.5.0")]
409     pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
410                                dur: Duration)
411                                -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
412         let (poisoned, result) = unsafe {
413             let lock = mutex::guard_lock(&guard);
414             self.verify(lock);
415             let success = self.inner.wait_timeout(lock, dur);
416             (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
417         };
418         if poisoned {
419             Err(PoisonError::new((guard, result)))
420         } else {
421             Ok((guard, result))
422         }
423     }
424
425     /// Waits on this condition variable for a notification, timing out after a
426     /// specified duration.  Spurious wakes will not cause this function to
427     /// return.
428     ///
429     /// The semantics of this function are equivalent to [`wait_until`] except
430     /// that the thread will be blocked for roughly no longer than `dur`. This
431     /// method should not be used for precise timing due to anomalies such as
432     /// preemption or platform differences that may not cause the maximum
433     /// amount of time waited to be precisely `dur`.
434     ///
435     /// Note that the best effort is made to ensure that the time waited is
436     /// measured with a monotonic clock, and not affected by the changes made to
437     /// the system time.
438     ///
439     /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
440     /// known to have elapsed without the condition being met.
441     ///
442     /// Like [`wait_until`], the lock specified will be re-acquired when this
443     /// function returns, regardless of whether the timeout elapsed or not.
444     ///
445     /// [`wait_until`]: #method.wait_until
446     /// [`wait_timeout`]: #method.wait_timeout
447     /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
448     ///
449     /// # Examples
450     ///
451     /// ```
452     /// #![feature(wait_timeout_until)]
453     ///
454     /// use std::sync::{Arc, Mutex, Condvar};
455     /// use std::thread;
456     /// use std::time::Duration;
457     ///
458     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
459     /// let pair2 = pair.clone();
460     ///
461     /// thread::spawn(move|| {
462     ///     let &(ref lock, ref cvar) = &*pair2;
463     ///     let mut started = lock.lock().unwrap();
464     ///     *started = true;
465     ///     // We notify the condvar that the value has changed.
466     ///     cvar.notify_one();
467     /// });
468     ///
469     /// // wait for the thread to start up
470     /// let &(ref lock, ref cvar) = &*pair;
471     /// let result = cvar.wait_timeout_until(
472     ///     lock.lock().unwrap(),
473     ///     Duration::from_millis(100),
474     ///     |&mut started| started,
475     /// ).unwrap();
476     /// if result.1.timed_out() {
477     ///     // timed-out without the condition ever evaluating to true.
478     /// }
479     /// // access the locked mutex via result.0
480     /// ```
481     #[unstable(feature = "wait_timeout_until", issue = "47960")]
482     pub fn wait_timeout_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
483                                         dur: Duration, mut condition: F)
484                                         -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
485                                         where F: FnMut(&mut T) -> bool {
486         let start = Instant::now();
487         loop {
488             if condition(&mut *guard) {
489                 return Ok((guard, WaitTimeoutResult(false)));
490             }
491             let timeout = match dur.checked_sub(start.elapsed()) {
492                 Some(timeout) => timeout,
493                 None => return Ok((guard, WaitTimeoutResult(true))),
494             };
495             guard = self.wait_timeout(guard, timeout)?.0;
496         }
497     }
498
499     /// Wakes up one blocked thread on this condvar.
500     ///
501     /// If there is a blocked thread on this condition variable, then it will
502     /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to
503     /// `notify_one` are not buffered in any way.
504     ///
505     /// To wake up all threads, see [`notify_all`].
506     ///
507     /// [`wait`]: #method.wait
508     /// [`wait_timeout`]: #method.wait_timeout
509     /// [`notify_all`]: #method.notify_all
510     ///
511     /// # Examples
512     ///
513     /// ```
514     /// use std::sync::{Arc, Mutex, Condvar};
515     /// use std::thread;
516     ///
517     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
518     /// let pair2 = pair.clone();
519     ///
520     /// thread::spawn(move|| {
521     ///     let &(ref lock, ref cvar) = &*pair2;
522     ///     let mut started = lock.lock().unwrap();
523     ///     *started = true;
524     ///     // We notify the condvar that the value has changed.
525     ///     cvar.notify_one();
526     /// });
527     ///
528     /// // Wait for the thread to start up.
529     /// let &(ref lock, ref cvar) = &*pair;
530     /// let mut started = lock.lock().unwrap();
531     /// // As long as the value inside the `Mutex` is false, we wait.
532     /// while !*started {
533     ///     started = cvar.wait(started).unwrap();
534     /// }
535     /// ```
536     #[stable(feature = "rust1", since = "1.0.0")]
537     pub fn notify_one(&self) {
538         unsafe { self.inner.notify_one() }
539     }
540
541     /// Wakes up all blocked threads on this condvar.
542     ///
543     /// This method will ensure that any current waiters on the condition
544     /// variable are awoken. Calls to `notify_all()` are not buffered in any
545     /// way.
546     ///
547     /// To wake up only one thread, see [`notify_one`].
548     ///
549     /// [`notify_one`]: #method.notify_one
550     ///
551     /// # Examples
552     ///
553     /// ```
554     /// use std::sync::{Arc, Mutex, Condvar};
555     /// use std::thread;
556     ///
557     /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
558     /// let pair2 = pair.clone();
559     ///
560     /// thread::spawn(move|| {
561     ///     let &(ref lock, ref cvar) = &*pair2;
562     ///     let mut started = lock.lock().unwrap();
563     ///     *started = true;
564     ///     // We notify the condvar that the value has changed.
565     ///     cvar.notify_all();
566     /// });
567     ///
568     /// // Wait for the thread to start up.
569     /// let &(ref lock, ref cvar) = &*pair;
570     /// let mut started = lock.lock().unwrap();
571     /// // As long as the value inside the `Mutex` is false, we wait.
572     /// while !*started {
573     ///     started = cvar.wait(started).unwrap();
574     /// }
575     /// ```
576     #[stable(feature = "rust1", since = "1.0.0")]
577     pub fn notify_all(&self) {
578         unsafe { self.inner.notify_all() }
579     }
580
581     fn verify(&self, mutex: &sys_mutex::Mutex) {
582         let addr = mutex as *const _ as usize;
583         match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
584             // If we got out 0, then we have successfully bound the mutex to
585             // this cvar.
586             0 => {}
587
588             // If we get out a value that's the same as `addr`, then someone
589             // already beat us to the punch.
590             n if n == addr => {}
591
592             // Anything else and we're using more than one mutex on this cvar,
593             // which is currently disallowed.
594             _ => panic!("attempted to use a condition variable with two \
595                          mutexes"),
596         }
597     }
598 }
599
600 #[stable(feature = "std_debug", since = "1.16.0")]
601 impl fmt::Debug for Condvar {
602     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
603         f.pad("Condvar { .. }")
604     }
605 }
606
607 #[stable(feature = "condvar_default", since = "1.10.0")]
608 impl Default for Condvar {
609     /// Creates a `Condvar` which is ready to be waited on and notified.
610     fn default() -> Condvar {
611         Condvar::new()
612     }
613 }
614
615 #[stable(feature = "rust1", since = "1.0.0")]
616 impl Drop for Condvar {
617     fn drop(&mut self) {
618         unsafe { self.inner.destroy() }
619     }
620 }
621
622 #[cfg(test)]
623 mod tests {
624     /// #![feature(wait_until)]
625     use sync::mpsc::channel;
626     use sync::{Condvar, Mutex, Arc};
627     use sync::atomic::{AtomicBool, Ordering};
628     use thread;
629     use time::Duration;
630     use u64;
631
632     #[test]
633     fn smoke() {
634         let c = Condvar::new();
635         c.notify_one();
636         c.notify_all();
637     }
638
639     #[test]
640     #[cfg_attr(target_os = "emscripten", ignore)]
641     fn notify_one() {
642         let m = Arc::new(Mutex::new(()));
643         let m2 = m.clone();
644         let c = Arc::new(Condvar::new());
645         let c2 = c.clone();
646
647         let g = m.lock().unwrap();
648         let _t = thread::spawn(move|| {
649             let _g = m2.lock().unwrap();
650             c2.notify_one();
651         });
652         let g = c.wait(g).unwrap();
653         drop(g);
654     }
655
656     #[test]
657     #[cfg_attr(target_os = "emscripten", ignore)]
658     fn notify_all() {
659         const N: usize = 10;
660
661         let data = Arc::new((Mutex::new(0), Condvar::new()));
662         let (tx, rx) = channel();
663         for _ in 0..N {
664             let data = data.clone();
665             let tx = tx.clone();
666             thread::spawn(move|| {
667                 let &(ref lock, ref cond) = &*data;
668                 let mut cnt = lock.lock().unwrap();
669                 *cnt += 1;
670                 if *cnt == N {
671                     tx.send(()).unwrap();
672                 }
673                 while *cnt != 0 {
674                     cnt = cond.wait(cnt).unwrap();
675                 }
676                 tx.send(()).unwrap();
677             });
678         }
679         drop(tx);
680
681         let &(ref lock, ref cond) = &*data;
682         rx.recv().unwrap();
683         let mut cnt = lock.lock().unwrap();
684         *cnt = 0;
685         cond.notify_all();
686         drop(cnt);
687
688         for _ in 0..N {
689             rx.recv().unwrap();
690         }
691     }
692
693     #[test]
694     #[cfg_attr(target_os = "emscripten", ignore)]
695     fn wait_until() {
696         let pair = Arc::new((Mutex::new(false), Condvar::new()));
697         let pair2 = pair.clone();
698
699         // Inside of our lock, spawn a new thread, and then wait for it to start.
700         thread::spawn(move|| {
701             let &(ref lock, ref cvar) = &*pair2;
702             let mut started = lock.lock().unwrap();
703             *started = true;
704             // We notify the condvar that the value has changed.
705             cvar.notify_one();
706         });
707
708         // Wait for the thread to start up.
709         let &(ref lock, ref cvar) = &*pair;
710         let guard = cvar.wait_until(lock.lock().unwrap(), |started| {
711             *started
712         });
713         assert!(*guard.unwrap());
714     }
715
716     #[test]
717     #[cfg_attr(target_os = "emscripten", ignore)]
718     fn wait_timeout_wait() {
719         let m = Arc::new(Mutex::new(()));
720         let c = Arc::new(Condvar::new());
721
722         loop {
723             let g = m.lock().unwrap();
724             let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap();
725             // spurious wakeups mean this isn't necessarily true
726             // so execute test again, if not timeout
727             if !no_timeout.timed_out() {
728                 continue;
729             }
730
731             break;
732         }
733     }
734
735     #[test]
736     #[cfg_attr(target_os = "emscripten", ignore)]
737     fn wait_timeout_until_wait() {
738         let m = Arc::new(Mutex::new(()));
739         let c = Arc::new(Condvar::new());
740
741         let g = m.lock().unwrap();
742         let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| { false }).unwrap();
743         // no spurious wakeups. ensure it timed-out
744         assert!(wait.timed_out());
745     }
746
747     #[test]
748     #[cfg_attr(target_os = "emscripten", ignore)]
749     fn wait_timeout_until_instant_satisfy() {
750         let m = Arc::new(Mutex::new(()));
751         let c = Arc::new(Condvar::new());
752
753         let g = m.lock().unwrap();
754         let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| { true }).unwrap();
755         // ensure it didn't time-out even if we were not given any time.
756         assert!(!wait.timed_out());
757     }
758
759     #[test]
760     #[cfg_attr(target_os = "emscripten", ignore)]
761     fn wait_timeout_until_wake() {
762         let pair = Arc::new((Mutex::new(false), Condvar::new()));
763         let pair_copy = pair.clone();
764
765         let &(ref m, ref c) = &*pair;
766         let g = m.lock().unwrap();
767         let _t = thread::spawn(move || {
768             let &(ref lock, ref cvar) = &*pair_copy;
769             let mut started = lock.lock().unwrap();
770             thread::sleep(Duration::from_millis(1));
771             *started = true;
772             cvar.notify_one();
773         });
774         let (g2, wait) = c.wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| {
775             notified
776         }).unwrap();
777         // ensure it didn't time-out even if we were not given any time.
778         assert!(!wait.timed_out());
779         assert!(*g2);
780     }
781
782     #[test]
783     #[cfg_attr(target_os = "emscripten", ignore)]
784     fn wait_timeout_wake() {
785         let m = Arc::new(Mutex::new(()));
786         let c = Arc::new(Condvar::new());
787
788         loop {
789             let g = m.lock().unwrap();
790
791             let c2 = c.clone();
792             let m2 = m.clone();
793
794             let notified = Arc::new(AtomicBool::new(false));
795             let notified_copy = notified.clone();
796
797             let t = thread::spawn(move || {
798                 let _g = m2.lock().unwrap();
799                 thread::sleep(Duration::from_millis(1));
800                 notified_copy.store(true, Ordering::SeqCst);
801                 c2.notify_one();
802             });
803             let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap();
804             assert!(!timeout_res.timed_out());
805             // spurious wakeups mean this isn't necessarily true
806             // so execute test again, if not notified
807             if !notified.load(Ordering::SeqCst) {
808                 t.join().unwrap();
809                 continue;
810             }
811             drop(g);
812
813             t.join().unwrap();
814
815             break;
816         }
817     }
818
819     #[test]
820     #[should_panic]
821     #[cfg_attr(target_os = "emscripten", ignore)]
822     fn two_mutexes() {
823         let m = Arc::new(Mutex::new(()));
824         let m2 = m.clone();
825         let c = Arc::new(Condvar::new());
826         let c2 = c.clone();
827
828         let mut g = m.lock().unwrap();
829         let _t = thread::spawn(move|| {
830             let _g = m2.lock().unwrap();
831             c2.notify_one();
832         });
833         g = c.wait(g).unwrap();
834         drop(g);
835
836         let m = Mutex::new(());
837         let _ = c.wait(m.lock().unwrap()).unwrap();
838     }
839 }