diff options
Diffstat (limited to 'ctr-std/src/sync/condvar.rs')
| -rw-r--r-- | ctr-std/src/sync/condvar.rs | 86 |
1 files changed, 61 insertions, 25 deletions
diff --git a/ctr-std/src/sync/condvar.rs b/ctr-std/src/sync/condvar.rs index 68c7e88..5640217 100644 --- a/ctr-std/src/sync/condvar.rs +++ b/ctr-std/src/sync/condvar.rs @@ -150,7 +150,7 @@ impl Condvar { /// /// This function will atomically unlock the mutex specified (represented by /// `guard`) and block the current thread. This means that any calls - /// to [`notify_one()`] or [`notify_all()`] which happen logically after the + /// to [`notify_one`] or [`notify_all`] which happen logically after the /// mutex is unlocked are candidates to wake this thread up. When this /// function call returns, the lock specified will have been re-acquired. /// @@ -167,16 +167,16 @@ impl Condvar { /// /// # Panics /// - /// This function will [`panic!()`] if it is used with more than one mutex + /// This function will [`panic!`] if it is used with more than one mutex /// over time. Each condition variable is dynamically bound to exactly one /// mutex to ensure defined behavior across platforms. If this functionality /// is not desired, then unsafe primitives in `sys` are provided. /// - /// [`notify_one()`]: #method.notify_one - /// [`notify_all()`]: #method.notify_all + /// [`notify_one`]: #method.notify_one + /// [`notify_all`]: #method.notify_all /// [poisoning]: ../sync/struct.Mutex.html#poisoning /// [`Mutex`]: ../sync/struct.Mutex.html - /// [`panic!()`]: ../../std/macro.panic.html + /// [`panic!`]: ../../std/macro.panic.html /// /// # Examples /// @@ -359,11 +359,11 @@ impl Condvar { /// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to /// `notify_one` are not buffered in any way. /// - /// To wake up all threads, see [`notify_all()`]. + /// To wake up all threads, see [`notify_all`]. /// /// [`wait`]: #method.wait /// [`wait_timeout`]: #method.wait_timeout - /// [`notify_all()`]: #method.notify_all + /// [`notify_all`]: #method.notify_all /// /// # Examples /// @@ -401,9 +401,9 @@ impl Condvar { /// variable are awoken. Calls to `notify_all()` are not buffered in any /// way. /// - /// To wake up only one thread, see [`notify_one()`]. + /// To wake up only one thread, see [`notify_one`]. /// - /// [`notify_one()`]: #method.notify_one + /// [`notify_one`]: #method.notify_one /// /// # Examples /// @@ -461,7 +461,7 @@ impl fmt::Debug for Condvar { } } -#[stable(feature = "condvar_default", since = "1.9.0")] +#[stable(feature = "condvar_default", since = "1.10.0")] impl Default for Condvar { /// Creates a `Condvar` which is ready to be waited on and notified. fn default() -> Condvar { @@ -480,9 +480,10 @@ impl Drop for Condvar { mod tests { use sync::mpsc::channel; use sync::{Condvar, Mutex, Arc}; + use sync::atomic::{AtomicBool, Ordering}; use thread; use time::Duration; - use u32; + use u64; #[test] fn smoke() { @@ -547,23 +548,58 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] - fn wait_timeout_ms() { + fn wait_timeout_wait() { let m = Arc::new(Mutex::new(())); - let m2 = m.clone(); let c = Arc::new(Condvar::new()); - let c2 = c.clone(); - let g = m.lock().unwrap(); - let (g, _no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); - // spurious wakeups mean this isn't necessarily true - // assert!(!no_timeout); - let _t = thread::spawn(move || { - let _g = m2.lock().unwrap(); - c2.notify_one(); - }); - let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u32::MAX as u64)).unwrap(); - assert!(!timeout_res.timed_out()); - drop(g); + loop { + let g = m.lock().unwrap(); + let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap(); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not timeout + if !no_timeout.timed_out() { + continue; + } + + break; + } + } + + #[test] + #[cfg_attr(target_os = "emscripten", ignore)] + fn wait_timeout_wake() { + let m = Arc::new(Mutex::new(())); + let c = Arc::new(Condvar::new()); + + loop { + let g = m.lock().unwrap(); + + let c2 = c.clone(); + let m2 = m.clone(); + + let notified = Arc::new(AtomicBool::new(false)); + let notified_copy = notified.clone(); + + let t = thread::spawn(move || { + let _g = m2.lock().unwrap(); + thread::sleep(Duration::from_millis(1)); + notified_copy.store(true, Ordering::SeqCst); + c2.notify_one(); + }); + let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap(); + assert!(!timeout_res.timed_out()); + // spurious wakeups mean this isn't necessarily true + // so execute test again, if not notified + if !notified.load(Ordering::SeqCst) { + t.join().unwrap(); + continue; + } + drop(g); + + t.join().unwrap(); + + break; + } } #[test] |