Skip to content

Commit cb6122d

Browse files
committed
Auto merge of #67076 - mbrubeck:condvar, r=dtolnay
Stabilize Condvar::wait_while and wait_timeout_while (previously wait_until, wait_timeout_until) Closes #47960.
2 parents c06e4ac + 98d054a commit cb6122d

File tree

1 file changed

+34
-43
lines changed

1 file changed

+34
-43
lines changed

src/libstd/sync/condvar.rs

+34-43
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,7 @@ impl Condvar {
204204
}
205205

206206
/// Blocks the current thread until this condition variable receives a
207-
/// notification and the required condition is met. Spurious wakeups are
208-
/// ignored and this function will only return once the condition has been
209-
/// met.
207+
/// notification and the provided condition is false.
210208
///
211209
/// This function will atomically unlock the mutex specified (represented by
212210
/// `guard`) and block the current thread. This means that any calls
@@ -228,37 +226,35 @@ impl Condvar {
228226
/// # Examples
229227
///
230228
/// ```
231-
/// #![feature(wait_until)]
232-
///
233229
/// use std::sync::{Arc, Mutex, Condvar};
234230
/// use std::thread;
235231
///
236-
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
232+
/// let pair = Arc::new((Mutex::new(true), Condvar::new()));
237233
/// let pair2 = pair.clone();
238234
///
239235
/// thread::spawn(move|| {
240236
/// let (lock, cvar) = &*pair2;
241-
/// let mut started = lock.lock().unwrap();
242-
/// *started = true;
237+
/// let mut pending = lock.lock().unwrap();
238+
/// *pending = false;
243239
/// // We notify the condvar that the value has changed.
244240
/// cvar.notify_one();
245241
/// });
246242
///
247243
/// // Wait for the thread to start up.
248244
/// let (lock, cvar) = &*pair;
249-
/// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
250-
/// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
245+
/// // As long as the value inside the `Mutex<bool>` is `true`, we wait.
246+
/// let _guard = cvar.wait_while(lock.lock().unwrap(), |pending| { *pending }).unwrap();
251247
/// ```
252-
#[unstable(feature = "wait_until", issue = "47960")]
253-
pub fn wait_until<'a, T, F>(
248+
#[stable(feature = "wait_until", since = "1.42.0")]
249+
pub fn wait_while<'a, T, F>(
254250
&self,
255251
mut guard: MutexGuard<'a, T>,
256252
mut condition: F,
257253
) -> LockResult<MutexGuard<'a, T>>
258254
where
259255
F: FnMut(&mut T) -> bool,
260256
{
261-
while !condition(&mut *guard) {
257+
while condition(&mut *guard) {
262258
guard = self.wait(guard)?;
263259
}
264260
Ok(guard)
@@ -343,11 +339,10 @@ impl Condvar {
343339
/// Condition variables normally have a boolean predicate associated with
344340
/// them, and the predicate must always be checked each time this function
345341
/// returns to protect against spurious wakeups. Additionally, it is
346-
/// typically desirable for the time-out to not exceed some duration in
342+
/// typically desirable for the timeout to not exceed some duration in
347343
/// spite of spurious wakes, thus the sleep-duration is decremented by the
348-
/// amount slept. Alternatively, use the `wait_timeout_until` method
349-
/// to wait until a condition is met with a total time-out regardless
350-
/// of spurious wakes.
344+
/// amount slept. Alternatively, use the `wait_timeout_while` method
345+
/// to wait with a timeout while a predicate is true.
351346
///
352347
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
353348
/// known to have elapsed.
@@ -356,7 +351,7 @@ impl Condvar {
356351
/// returns, regardless of whether the timeout elapsed or not.
357352
///
358353
/// [`wait`]: #method.wait
359-
/// [`wait_timeout_until`]: #method.wait_timeout_until
354+
/// [`wait_timeout_while`]: #method.wait_timeout_while
360355
/// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
361356
///
362357
/// # Examples
@@ -407,10 +402,9 @@ impl Condvar {
407402
}
408403

409404
/// Waits on this condition variable for a notification, timing out after a
410-
/// specified duration. Spurious wakes will not cause this function to
411-
/// return.
405+
/// specified duration.
412406
///
413-
/// The semantics of this function are equivalent to [`wait_until`] except
407+
/// The semantics of this function are equivalent to [`wait_while`] except
414408
/// that the thread will be blocked for roughly no longer than `dur`. This
415409
/// method should not be used for precise timing due to anomalies such as
416410
/// preemption or platform differences that may not cause the maximum
@@ -423,47 +417,45 @@ impl Condvar {
423417
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
424418
/// known to have elapsed without the condition being met.
425419
///
426-
/// Like [`wait_until`], the lock specified will be re-acquired when this
420+
/// Like [`wait_while`], the lock specified will be re-acquired when this
427421
/// function returns, regardless of whether the timeout elapsed or not.
428422
///
429-
/// [`wait_until`]: #method.wait_until
423+
/// [`wait_while`]: #method.wait_while
430424
/// [`wait_timeout`]: #method.wait_timeout
431425
/// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
432426
///
433427
/// # Examples
434428
///
435429
/// ```
436-
/// #![feature(wait_timeout_until)]
437-
///
438430
/// use std::sync::{Arc, Mutex, Condvar};
439431
/// use std::thread;
440432
/// use std::time::Duration;
441433
///
442-
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
434+
/// let pair = Arc::new((Mutex::new(true), Condvar::new()));
443435
/// let pair2 = pair.clone();
444436
///
445437
/// thread::spawn(move|| {
446438
/// let (lock, cvar) = &*pair2;
447-
/// let mut started = lock.lock().unwrap();
448-
/// *started = true;
439+
/// let mut pending = lock.lock().unwrap();
440+
/// *pending = false;
449441
/// // We notify the condvar that the value has changed.
450442
/// cvar.notify_one();
451443
/// });
452444
///
453445
/// // wait for the thread to start up
454446
/// let (lock, cvar) = &*pair;
455-
/// let result = cvar.wait_timeout_until(
447+
/// let result = cvar.wait_timeout_while(
456448
/// lock.lock().unwrap(),
457449
/// Duration::from_millis(100),
458-
/// |&mut started| started,
450+
/// |&mut pending| pending,
459451
/// ).unwrap();
460452
/// if result.1.timed_out() {
461-
/// // timed-out without the condition ever evaluating to true.
453+
/// // timed-out without the condition ever evaluating to false.
462454
/// }
463455
/// // access the locked mutex via result.0
464456
/// ```
465-
#[unstable(feature = "wait_timeout_until", issue = "47960")]
466-
pub fn wait_timeout_until<'a, T, F>(
457+
#[stable(feature = "wait_timeout_until", since = "1.42.0")]
458+
pub fn wait_timeout_while<'a, T, F>(
467459
&self,
468460
mut guard: MutexGuard<'a, T>,
469461
dur: Duration,
@@ -474,7 +466,7 @@ impl Condvar {
474466
{
475467
let start = Instant::now();
476468
loop {
477-
if condition(&mut *guard) {
469+
if !condition(&mut *guard) {
478470
return Ok((guard, WaitTimeoutResult(false)));
479471
}
480472
let timeout = match dur.checked_sub(start.elapsed()) {
@@ -613,7 +605,6 @@ impl Drop for Condvar {
613605
#[cfg(test)]
614606
mod tests {
615607
use crate::sync::atomic::{AtomicBool, Ordering};
616-
/// #![feature(wait_until)]
617608
use crate::sync::mpsc::channel;
618609
use crate::sync::{Arc, Condvar, Mutex};
619610
use crate::thread;
@@ -683,7 +674,7 @@ mod tests {
683674

684675
#[test]
685676
#[cfg_attr(target_os = "emscripten", ignore)]
686-
fn wait_until() {
677+
fn wait_while() {
687678
let pair = Arc::new((Mutex::new(false), Condvar::new()));
688679
let pair2 = pair.clone();
689680

@@ -698,7 +689,7 @@ mod tests {
698689

699690
// Wait for the thread to start up.
700691
let &(ref lock, ref cvar) = &*pair;
701-
let guard = cvar.wait_until(lock.lock().unwrap(), |started| *started);
692+
let guard = cvar.wait_while(lock.lock().unwrap(), |started| !*started);
702693
assert!(*guard.unwrap());
703694
}
704695

@@ -725,32 +716,32 @@ mod tests {
725716
#[test]
726717
#[cfg_attr(target_os = "emscripten", ignore)]
727718
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
728-
fn wait_timeout_until_wait() {
719+
fn wait_timeout_while_wait() {
729720
let m = Arc::new(Mutex::new(()));
730721
let c = Arc::new(Condvar::new());
731722

732723
let g = m.lock().unwrap();
733-
let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(1), |_| false).unwrap();
724+
let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(1), |_| true).unwrap();
734725
// no spurious wakeups. ensure it timed-out
735726
assert!(wait.timed_out());
736727
}
737728

738729
#[test]
739730
#[cfg_attr(target_os = "emscripten", ignore)]
740-
fn wait_timeout_until_instant_satisfy() {
731+
fn wait_timeout_while_instant_satisfy() {
741732
let m = Arc::new(Mutex::new(()));
742733
let c = Arc::new(Condvar::new());
743734

744735
let g = m.lock().unwrap();
745-
let (_g, wait) = c.wait_timeout_until(g, Duration::from_millis(0), |_| true).unwrap();
736+
let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(0), |_| false).unwrap();
746737
// ensure it didn't time-out even if we were not given any time.
747738
assert!(!wait.timed_out());
748739
}
749740

750741
#[test]
751742
#[cfg_attr(target_os = "emscripten", ignore)]
752743
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
753-
fn wait_timeout_until_wake() {
744+
fn wait_timeout_while_wake() {
754745
let pair = Arc::new((Mutex::new(false), Condvar::new()));
755746
let pair_copy = pair.clone();
756747

@@ -764,7 +755,7 @@ mod tests {
764755
cvar.notify_one();
765756
});
766757
let (g2, wait) = c
767-
.wait_timeout_until(g, Duration::from_millis(u64::MAX), |&mut notified| notified)
758+
.wait_timeout_while(g, Duration::from_millis(u64::MAX), |&mut notified| !notified)
768759
.unwrap();
769760
// ensure it didn't time-out even if we were not given any time.
770761
assert!(!wait.timed_out());

0 commit comments

Comments
 (0)