aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sync/condvar.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ctr-std/src/sync/condvar.rs')
-rw-r--r--ctr-std/src/sync/condvar.rs86
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]