2 use crate::sync::atomic::{AtomicUsize, Ordering};
3 use crate::sync::{mutex, MutexGuard, PoisonError};
4 use crate::sys_common::condvar as sys;
5 use crate::sys_common::mutex as sys_mutex;
6 use crate::sys_common::poison::{self, LockResult};
7 use crate::time::{Duration, Instant};
9 /// A type indicating whether a timed wait on a condition variable returned
10 /// due to a time out or not.
12 /// It is returned by the [`wait_timeout`] method.
14 /// [`wait_timeout`]: struct.Condvar.html#method.wait_timeout
15 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
16 #[stable(feature = "wait_timeout", since = "1.5.0")]
17 pub struct WaitTimeoutResult(bool);
19 impl WaitTimeoutResult {
20 /// Returns `true` if the wait was known to have timed out.
24 /// This example spawns a thread which will update the boolean value and
25 /// then wait 100 milliseconds before notifying the condvar.
27 /// The main thread will wait with a timeout on the condvar and then leave
28 /// once the boolean has been updated and notified.
31 /// use std::sync::{Arc, Mutex, Condvar};
33 /// use std::time::Duration;
35 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
36 /// let pair2 = pair.clone();
38 /// thread::spawn(move|| {
39 /// let &(ref lock, ref cvar) = &*pair2;
41 /// // Let's wait 20 milliseconds before notifying the condvar.
42 /// thread::sleep(Duration::from_millis(20));
44 /// let mut started = lock.lock().unwrap();
45 /// // We update the boolean value.
47 /// cvar.notify_one();
50 /// // Wait for the thread to start up.
51 /// let &(ref lock, ref cvar) = &*pair;
52 /// let mut started = lock.lock().unwrap();
54 /// // Let's put a timeout on the condvar's wait.
55 /// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
56 /// // 10 milliseconds have passed, or maybe the value changed!
57 /// started = result.0;
58 /// if *started == true {
59 /// // We received the notification and the value has been updated, we can leave.
64 #[stable(feature = "wait_timeout", since = "1.5.0")]
65 pub fn timed_out(&self) -> bool {
70 /// A Condition Variable
72 /// Condition variables represent the ability to block a thread such that it
73 /// consumes no CPU time while waiting for an event to occur. Condition
74 /// variables are typically associated with a boolean predicate (a condition)
75 /// and a mutex. The predicate is always verified inside of the mutex before
76 /// determining that a thread must block.
78 /// Functions in this module will block the current **thread** of execution and
79 /// are bindings to system-provided condition variables where possible. Note
80 /// that this module places one additional restriction over the system condition
81 /// variables: each condvar can be used with precisely one mutex at runtime. Any
82 /// attempt to use multiple mutexes on the same condition variable will result
83 /// in a runtime panic. If this is not desired, then the unsafe primitives in
84 /// `sys` do not have this restriction but may result in undefined behavior.
89 /// use std::sync::{Arc, Mutex, Condvar};
92 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
93 /// let pair2 = pair.clone();
95 /// // Inside of our lock, spawn a new thread, and then wait for it to start.
96 /// thread::spawn(move|| {
97 /// let &(ref lock, ref cvar) = &*pair2;
98 /// let mut started = lock.lock().unwrap();
100 /// // We notify the condvar that the value has changed.
101 /// cvar.notify_one();
104 /// // Wait for the thread to start up.
105 /// let &(ref lock, ref cvar) = &*pair;
106 /// let mut started = lock.lock().unwrap();
107 /// while !*started {
108 /// started = cvar.wait(started).unwrap();
111 #[stable(feature = "rust1", since = "1.0.0")]
113 inner: Box<sys::Condvar>,
118 /// Creates a new condition variable which is ready to be waited on and
124 /// use std::sync::Condvar;
126 /// let condvar = Condvar::new();
128 #[stable(feature = "rust1", since = "1.0.0")]
129 pub fn new() -> Condvar {
130 let mut c = Condvar {
131 inner: box sys::Condvar::new(),
132 mutex: AtomicUsize::new(0),
140 /// Blocks the current thread until this condition variable receives a
143 /// This function will atomically unlock the mutex specified (represented by
144 /// `guard`) and block the current thread. This means that any calls
145 /// to [`notify_one`] or [`notify_all`] which happen logically after the
146 /// mutex is unlocked are candidates to wake this thread up. When this
147 /// function call returns, the lock specified will have been re-acquired.
149 /// Note that this function is susceptible to spurious wakeups. Condition
150 /// variables normally have a boolean predicate associated with them, and
151 /// the predicate must always be checked each time this function returns to
152 /// protect against spurious wakeups.
156 /// This function will return an error if the mutex being waited on is
157 /// poisoned when this thread re-acquires the lock. For more information,
158 /// see information about [poisoning] on the [`Mutex`] type.
162 /// This function will [`panic!`] if it is used with more than one mutex
163 /// over time. Each condition variable is dynamically bound to exactly one
164 /// mutex to ensure defined behavior across platforms. If this functionality
165 /// is not desired, then unsafe primitives in `sys` are provided.
167 /// [`notify_one`]: #method.notify_one
168 /// [`notify_all`]: #method.notify_all
169 /// [poisoning]: ../sync/struct.Mutex.html#poisoning
170 /// [`Mutex`]: ../sync/struct.Mutex.html
171 /// [`panic!`]: ../../std/macro.panic.html
176 /// use std::sync::{Arc, Mutex, Condvar};
179 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
180 /// let pair2 = pair.clone();
182 /// thread::spawn(move|| {
183 /// let &(ref lock, ref cvar) = &*pair2;
184 /// let mut started = lock.lock().unwrap();
186 /// // We notify the condvar that the value has changed.
187 /// cvar.notify_one();
190 /// // Wait for the thread to start up.
191 /// let &(ref lock, ref cvar) = &*pair;
192 /// let mut started = lock.lock().unwrap();
193 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
194 /// while !*started {
195 /// started = cvar.wait(started).unwrap();
198 #[stable(feature = "rust1", since = "1.0.0")]
199 pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
200 -> LockResult<MutexGuard<'a, T>> {
201 let poisoned = unsafe {
202 let lock = mutex::guard_lock(&guard);
204 self.inner.wait(lock);
205 mutex::guard_poison(&guard).get()
208 Err(PoisonError::new(guard))
214 /// Blocks the current thread until this condition variable receives a
215 /// notification and the required condition is met. Spurious wakeups are
216 /// ignored and this function will only return once the condition has been
219 /// This function will atomically unlock the mutex specified (represented by
220 /// `guard`) and block the current thread. This means that any calls
221 /// to [`notify_one`] or [`notify_all`] which happen logically after the
222 /// mutex is unlocked are candidates to wake this thread up. When this
223 /// function call returns, the lock specified will have been re-acquired.
227 /// This function will return an error if the mutex being waited on is
228 /// poisoned when this thread re-acquires the lock. For more information,
229 /// see information about [poisoning] on the [`Mutex`] type.
231 /// [`notify_one`]: #method.notify_one
232 /// [`notify_all`]: #method.notify_all
233 /// [poisoning]: ../sync/struct.Mutex.html#poisoning
234 /// [`Mutex`]: ../sync/struct.Mutex.html
239 /// #![feature(wait_until)]
241 /// use std::sync::{Arc, Mutex, Condvar};
244 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
245 /// let pair2 = pair.clone();
247 /// thread::spawn(move|| {
248 /// let &(ref lock, ref cvar) = &*pair2;
249 /// let mut started = lock.lock().unwrap();
251 /// // We notify the condvar that the value has changed.
252 /// cvar.notify_one();
255 /// // Wait for the thread to start up.
256 /// let &(ref lock, ref cvar) = &*pair;
257 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
258 /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
260 #[unstable(feature = "wait_until", issue = "47960")]
261 pub fn wait_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
263 -> LockResult<MutexGuard<'a, T>>
264 where F: FnMut(&mut T) -> bool {
265 while !condition(&mut *guard) {
266 guard = self.wait(guard)?;
272 /// Waits on this condition variable for a notification, timing out after a
273 /// specified duration.
275 /// The semantics of this function are equivalent to [`wait`]
276 /// except that the thread will be blocked for roughly no longer
277 /// than `ms` milliseconds. This method should not be used for
278 /// precise timing due to anomalies such as preemption or platform
279 /// differences that may not cause the maximum amount of time
280 /// waited to be precisely `ms`.
282 /// Note that the best effort is made to ensure that the time waited is
283 /// measured with a monotonic clock, and not affected by the changes made to
286 /// The returned boolean is `false` only if the timeout is known
289 /// Like [`wait`], the lock specified will be re-acquired when this function
290 /// returns, regardless of whether the timeout elapsed or not.
292 /// [`wait`]: #method.wait
297 /// use std::sync::{Arc, Mutex, Condvar};
300 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
301 /// let pair2 = pair.clone();
303 /// thread::spawn(move|| {
304 /// let &(ref lock, ref cvar) = &*pair2;
305 /// let mut started = lock.lock().unwrap();
307 /// // We notify the condvar that the value has changed.
308 /// cvar.notify_one();
311 /// // Wait for the thread to start up.
312 /// let &(ref lock, ref cvar) = &*pair;
313 /// let mut started = lock.lock().unwrap();
314 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
316 /// let result = cvar.wait_timeout_ms(started, 10).unwrap();
317 /// // 10 milliseconds have passed, or maybe the value changed!
318 /// started = result.0;
319 /// if *started == true {
320 /// // We received the notification and the value has been updated, we can leave.
325 #[stable(feature = "rust1", since = "1.0.0")]
326 #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::sync::Condvar::wait_timeout`")]
327 pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
328 -> LockResult<(MutexGuard<'a, T>, bool)> {
329 let res = self.wait_timeout(guard, Duration::from_millis(ms as u64));
330 poison::map_result(res, |(a, b)| {
335 /// Waits on this condition variable for a notification, timing out after a
336 /// specified duration.
338 /// The semantics of this function are equivalent to [`wait`] except that
339 /// the thread will be blocked for roughly no longer than `dur`. This
340 /// method should not be used for precise timing due to anomalies such as
341 /// preemption or platform differences that may not cause the maximum
342 /// amount of time waited to be precisely `dur`.
344 /// Note that the best effort is made to ensure that the time waited is
345 /// measured with a monotonic clock, and not affected by the changes made to
346 /// the system time. This function is susceptible to spurious wakeups.
347 /// Condition variables normally have a boolean predicate associated with
348 /// them, and the predicate must always be checked each time this function
349 /// returns to protect against spurious wakeups. Additionally, it is
350 /// typically desirable for the time-out to not exceed some duration in
351 /// spite of spurious wakes, thus the sleep-duration is decremented by the
352 /// amount slept. Alternatively, use the `wait_timeout_until` method
353 /// to wait until a condition is met with a total time-out regardless
354 /// of spurious wakes.
356 /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
357 /// known to have elapsed.
359 /// Like [`wait`], the lock specified will be re-acquired when this function
360 /// returns, regardless of whether the timeout elapsed or not.
362 /// [`wait`]: #method.wait
363 /// [`wait_timeout_until`]: #method.wait_timeout_until
364 /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
369 /// use std::sync::{Arc, Mutex, Condvar};
371 /// use std::time::Duration;
373 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
374 /// let pair2 = pair.clone();
376 /// thread::spawn(move|| {
377 /// let &(ref lock, ref cvar) = &*pair2;
378 /// let mut started = lock.lock().unwrap();
380 /// // We notify the condvar that the value has changed.
381 /// cvar.notify_one();
384 /// // wait for the thread to start up
385 /// let &(ref lock, ref cvar) = &*pair;
386 /// let mut started = lock.lock().unwrap();
387 /// // as long as the value inside the `Mutex<bool>` is `false`, we wait
389 /// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
390 /// // 10 milliseconds have passed, or maybe the value changed!
391 /// started = result.0;
392 /// if *started == true {
393 /// // We received the notification and the value has been updated, we can leave.
398 #[stable(feature = "wait_timeout", since = "1.5.0")]
399 pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
401 -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
402 let (poisoned, result) = unsafe {
403 let lock = mutex::guard_lock(&guard);
405 let success = self.inner.wait_timeout(lock, dur);
406 (mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
409 Err(PoisonError::new((guard, result)))
415 /// Waits on this condition variable for a notification, timing out after a
416 /// specified duration. Spurious wakes will not cause this function to
419 /// The semantics of this function are equivalent to [`wait_until`] except
420 /// that the thread will be blocked for roughly no longer than `dur`. This
421 /// method should not be used for precise timing due to anomalies such as
422 /// preemption or platform differences that may not cause the maximum
423 /// amount of time waited to be precisely `dur`.
425 /// Note that the best effort is made to ensure that the time waited is
426 /// measured with a monotonic clock, and not affected by the changes made to
429 /// The returned [`WaitTimeoutResult`] value indicates if the timeout is
430 /// known to have elapsed without the condition being met.
432 /// Like [`wait_until`], the lock specified will be re-acquired when this
433 /// function returns, regardless of whether the timeout elapsed or not.
435 /// [`wait_until`]: #method.wait_until
436 /// [`wait_timeout`]: #method.wait_timeout
437 /// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
442 /// #![feature(wait_timeout_until)]
444 /// use std::sync::{Arc, Mutex, Condvar};
446 /// use std::time::Duration;
448 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
449 /// let pair2 = pair.clone();
451 /// thread::spawn(move|| {
452 /// let &(ref lock, ref cvar) = &*pair2;
453 /// let mut started = lock.lock().unwrap();
455 /// // We notify the condvar that the value has changed.
456 /// cvar.notify_one();
459 /// // wait for the thread to start up
460 /// let &(ref lock, ref cvar) = &*pair;
461 /// let result = cvar.wait_timeout_until(
462 /// lock.lock().unwrap(),
463 /// Duration::from_millis(100),
464 /// |&mut started| started,
466 /// if result.1.timed_out() {
467 /// // timed-out without the condition ever evaluating to true.
469 /// // access the locked mutex via result.0
471 #[unstable(feature = "wait_timeout_until", issue = "47960")]
472 pub fn wait_timeout_until<'a, T, F>(&self, mut guard: MutexGuard<'a, T>,
473 dur: Duration, mut condition: F)
474 -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
475 where F: FnMut(&mut T) -> bool {
476 let start = Instant::now();
478 if condition(&mut *guard) {
479 return Ok((guard, WaitTimeoutResult(false)));
481 let timeout = match dur.checked_sub(start.elapsed()) {
482 Some(timeout) => timeout,
483 None => return Ok((guard, WaitTimeoutResult(true))),
485 guard = self.wait_timeout(guard, timeout)?.0;
489 /// Wakes up one blocked thread on this condvar.
491 /// If there is a blocked thread on this condition variable, then it will
492 /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to
493 /// `notify_one` are not buffered in any way.
495 /// To wake up all threads, see [`notify_all`].
497 /// [`wait`]: #method.wait
498 /// [`wait_timeout`]: #method.wait_timeout
499 /// [`notify_all`]: #method.notify_all
504 /// use std::sync::{Arc, Mutex, Condvar};
507 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
508 /// let pair2 = pair.clone();
510 /// thread::spawn(move|| {
511 /// let &(ref lock, ref cvar) = &*pair2;
512 /// let mut started = lock.lock().unwrap();
514 /// // We notify the condvar that the value has changed.
515 /// cvar.notify_one();
518 /// // Wait for the thread to start up.
519 /// let &(ref lock, ref cvar) = &*pair;
520 /// let mut started = lock.lock().unwrap();
521 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
522 /// while !*started {
523 /// started = cvar.wait(started).unwrap();
526 #[stable(feature = "rust1", since = "1.0.0")]
527 pub fn notify_one(&self) {
528 unsafe { self.inner.notify_one() }
531 /// Wakes up all blocked threads on this condvar.
533 /// This method will ensure that any current waiters on the condition
534 /// variable are awoken. Calls to `notify_all()` are not buffered in any
537 /// To wake up only one thread, see [`notify_one`].
539 /// [`notify_one`]: #method.notify_one
544 /// use std::sync::{Arc, Mutex, Condvar};
547 /// let pair = Arc::new((Mutex::new(false), Condvar::new()));
548 /// let pair2 = pair.clone();
550 /// thread::spawn(move|| {
551 /// let &(ref lock, ref cvar) = &*pair2;
552 /// let mut started = lock.lock().unwrap();
554 /// // We notify the condvar that the value has changed.
555 /// cvar.notify_all();
558 /// // Wait for the thread to start up.
559 /// let &(ref lock, ref cvar) = &*pair;
560 /// let mut started = lock.lock().unwrap();
561 /// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
562 /// while !*started {
563 /// started = cvar.wait(started).unwrap();
566 #[stable(feature = "rust1", since = "1.0.0")]
567 pub fn notify_all(&self) {
568 unsafe { self.inner.notify_all() }
571 fn verify(&self, mutex: &sys_mutex::Mutex) {
572 let addr = mutex as *const _ as usize;
573 match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
574 // If we got out 0, then we have successfully bound the mutex to
578 // If we get out a value that's the same as `addr`, then someone
579 // already beat us to the punch.
582 // Anything else and we're using more than one mutex on this cvar,
583 // which is currently disallowed.
584 _ => panic!("attempted to use a condition variable with two \
590 #[stable(feature = "std_debug", since = "1.16.0")]
591 impl fmt::Debug for Condvar {
592 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
593 f.pad("Condvar { .. }")
597 #[stable(feature = "condvar_default", since = "1.10.0")]
598 impl Default for Condvar {
599 /// Creates a `Condvar` which is ready to be waited on and notified.
600 fn default() -> Condvar {
605 #[stable(feature = "rust1", since = "1.0.0")]
606 impl Drop for Condvar {
608 unsafe { self.inner.destroy() }
614 /// #![feature(wait_until)]
615 use crate::sync::mpsc::channel;
616 use crate::sync::{Condvar, Mutex, Arc};
617 use crate::sync::atomic::{AtomicBool, Ordering};
619 use crate::time::Duration;
624 let c = Condvar::new();
630 #[cfg_attr(target_os = "emscripten", ignore)]
632 let m = Arc::new(Mutex::new(()));
634 let c = Arc::new(Condvar::new());
637 let g = m.lock().unwrap();
638 let _t = thread::spawn(move|| {
639 let _g = m2.lock().unwrap();
642 let g = c.wait(g).unwrap();
647 #[cfg_attr(target_os = "emscripten", ignore)]
651 let data = Arc::new((Mutex::new(0), Condvar::new()));
652 let (tx, rx) = channel();
654 let data = data.clone();
656 thread::spawn(move|| {
657 let &(ref lock, ref cond) = &*data;
658 let mut cnt = lock.lock().unwrap();
661 tx.send(()).unwrap();
664 cnt = cond.wait(cnt).unwrap();
666 tx.send(()).unwrap();
671 let &(ref lock, ref cond) = &*data;
673 let mut cnt = lock.lock().unwrap();
684 #[cfg_attr(target_os = "emscripten", ignore)]
686 let pair = Arc::new((Mutex::new(false), Condvar::new()));
687 let pair2 = pair.clone();
689 // Inside of our lock, spawn a new thread, and then wait for it to start.
690 thread::spawn(move|| {
691 let &(ref lock, ref cvar) = &*pair2;
692 let mut started = lock.lock().unwrap();
694 // We notify the condvar that the value has changed.
698 // Wait for the thread to start up.
699 let &(ref lock, ref cvar) = &*pair;
700 let guard = cvar.wait_until(lock.lock().unwrap(), |started| {
703 assert!(*guard.unwrap());
707 #[cfg_attr(target_os = "emscripten", ignore)]
708 fn wait_timeout_wait() {
709 let m = Arc::new(Mutex::new(()));
710 let c = Arc::new(Condvar::new());
713 let g = m.lock().unwrap();
714 let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap();
715 // spurious wakeups mean this isn't necessarily true
716 // so execute test again, if not timeout
717 if !no_timeout.timed_out() {
726 #[cfg_attr(target_os = "emscripten", ignore)]
727 fn wait_timeout_until_wait() {
728 let m = Arc::new(Mutex::new(()));
729 let c = Arc::new(Condvar::new());
731 let g = m.lock().unwrap();
732 let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| { false }).unwrap();
733 // no spurious wakeups. ensure it timed-out
734 assert!(wait.timed_out());
738 #[cfg_attr(target_os = "emscripten", ignore)]
739 fn wait_timeout_until_instant_satisfy() {
740 let m = Arc::new(Mutex::new(()));
741 let c = Arc::new(Condvar::new());
743 let g = m.lock().unwrap();
744 let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| { true }).unwrap();
745 // ensure it didn't time-out even if we were not given any time.
746 assert!(!wait.timed_out());
750 #[cfg_attr(target_os = "emscripten", ignore)]
751 fn wait_timeout_until_wake() {
752 let pair = Arc::new((Mutex::new(false), Condvar::new()));
753 let pair_copy = pair.clone();
755 let &(ref m, ref c) = &*pair;
756 let g = m.lock().unwrap();
757 let _t = thread::spawn(move || {
758 let &(ref lock, ref cvar) = &*pair_copy;
759 let mut started = lock.lock().unwrap();
760 thread::sleep(Duration::from_millis(1));
764 let (g2, wait) = c.wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| {
767 // ensure it didn't time-out even if we were not given any time.
768 assert!(!wait.timed_out());
773 #[cfg_attr(target_os = "emscripten", ignore)]
774 fn wait_timeout_wake() {
775 let m = Arc::new(Mutex::new(()));
776 let c = Arc::new(Condvar::new());
779 let g = m.lock().unwrap();
784 let notified = Arc::new(AtomicBool::new(false));
785 let notified_copy = notified.clone();
787 let t = thread::spawn(move || {
788 let _g = m2.lock().unwrap();
789 thread::sleep(Duration::from_millis(1));
790 notified_copy.store(true, Ordering::SeqCst);
793 let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap();
794 assert!(!timeout_res.timed_out());
795 // spurious wakeups mean this isn't necessarily true
796 // so execute test again, if not notified
797 if !notified.load(Ordering::SeqCst) {
811 #[cfg_attr(target_os = "emscripten", ignore)]
813 let m = Arc::new(Mutex::new(()));
815 let c = Arc::new(Condvar::new());
818 let mut g = m.lock().unwrap();
819 let _t = thread::spawn(move|| {
820 let _g = m2.lock().unwrap();
823 g = c.wait(g).unwrap();
826 let m = Mutex::new(());
827 let _ = c.wait(m.lock().unwrap()).unwrap();