mirror of
https://github.com/rust-lang/rust
synced 2024-11-02 13:50:48 +00:00
Stabilize basic timeout functionality
This commit renames and stabilizes: * `Condvar::wait_timeout_ms` (renamed from `wait_timeout`) * `thread::park_timeout_ms` (renamed from `park_timeout`) * `thread::sleep_ms` (renamed from `sleep`) In each case, the timeout is taken as a `u32` number of milliseconds, rather than a `Duration`. These functions are likely to be deprecated once a stable form of `Duration` is available, but there is little cost to having these named variants around, and it's crucial functionality for 1.0. [breaking-change]
This commit is contained in:
parent
d528aa9960
commit
371277fb0d
2 changed files with 54 additions and 28 deletions
|
@ -140,33 +140,43 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
|
|||
/// Wait on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
/// The semantics of this function are equivalent to `wait()` except that
|
||||
/// the thread will be blocked for roughly no longer than `dur`. This method
|
||||
/// should not be used for precise timing due to anomalies such as
|
||||
/// preemption or platform differences that may not cause the maximum amount
|
||||
/// of time waited to be precisely `dur`.
|
||||
/// The semantics of this function are equivalent to `wait()`
|
||||
/// except that the thread will be blocked for roughly no longer
|
||||
/// than `ms` milliseconds. This method should not be used for
|
||||
/// precise timing due to anomalies such as preemption or platform
|
||||
/// differences that may not cause the maximum amount of time
|
||||
/// waited to be precisely `ms`.
|
||||
///
|
||||
/// If the wait timed out, then `false` will be returned. Otherwise if a
|
||||
/// notification was received then `true` will be returned.
|
||||
/// The returned boolean is `false` only if the timeout is known
|
||||
/// to have elapsed.
|
||||
///
|
||||
/// Like `wait`, the lock specified will be re-acquired when this function
|
||||
/// returns, regardless of whether the timeout elapsed or not.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
unsafe {
|
||||
let me: &'static Condvar = &*(self as *const _);
|
||||
me.inner.wait_timeout(guard, dur)
|
||||
me.inner.wait_timeout_ms(guard, ms)
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated: use `wait_timeout_ms` instead.
|
||||
#[unstable(feature = "std_misc")]
|
||||
#[deprecated(since = "1.0.0", reason = "use wait_timeout_ms instead")]
|
||||
pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
self.wait_timeout_ms(guard, dur.num_milliseconds() as u32)
|
||||
}
|
||||
|
||||
/// Wait on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
/// The semantics of this function are equivalent to `wait_timeout` except
|
||||
/// that the implementation will repeatedly wait while the duration has not
|
||||
/// passed and the provided function returns `false`.
|
||||
#[unstable(feature = "std_misc")]
|
||||
#[unstable(feature = "wait_timeout_with",
|
||||
reason = "unsure if this API is broadly needed or what form it should take")]
|
||||
pub fn wait_timeout_with<'a, T, F>(&self,
|
||||
guard: MutexGuard<'a, T>,
|
||||
dur: Duration,
|
||||
|
@ -235,12 +245,12 @@ pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
|
|||
/// See `Condvar::wait_timeout`.
|
||||
#[unstable(feature = "std_misc",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
let (poisoned, success) = unsafe {
|
||||
let lock = mutex::guard_lock(&guard);
|
||||
self.verify(lock);
|
||||
let success = self.inner.wait_timeout(lock, dur);
|
||||
let success = self.inner.wait_timeout(lock, Duration::milliseconds(ms as i64));
|
||||
(mutex::guard_poison(&guard).get(), success)
|
||||
};
|
||||
if poisoned {
|
||||
|
@ -275,7 +285,8 @@ pub fn wait_timeout_with<'a, T, F>(&'static self,
|
|||
let now = SteadyTime::now();
|
||||
let consumed = &now - &start;
|
||||
let guard = guard_result.unwrap_or_else(|e| e.into_inner());
|
||||
let (new_guard_result, no_timeout) = match self.wait_timeout(guard, dur - consumed) {
|
||||
let res = self.wait_timeout_ms(guard, (dur - consumed).num_milliseconds() as u32);
|
||||
let (new_guard_result, no_timeout) = match res {
|
||||
Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout),
|
||||
Err(err) => {
|
||||
let (new_guard, no_timeout) = err.into_inner();
|
||||
|
@ -350,6 +361,7 @@ mod tests {
|
|||
use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||
use thread;
|
||||
use time::Duration;
|
||||
use u32;
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
|
@ -418,19 +430,19 @@ fn notify_all() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn wait_timeout() {
|
||||
fn wait_timeout_ms() {
|
||||
static C: StaticCondvar = CONDVAR_INIT;
|
||||
static M: StaticMutex = MUTEX_INIT;
|
||||
|
||||
let g = M.lock().unwrap();
|
||||
let (g, _no_timeout) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap();
|
||||
let (g, _no_timeout) = C.wait_timeout_ms(g, 1).unwrap();
|
||||
// spurious wakeups mean this isn't necessarily true
|
||||
// assert!(!no_timeout);
|
||||
let _t = thread::spawn(move || {
|
||||
let _g = M.lock().unwrap();
|
||||
C.notify_one();
|
||||
});
|
||||
let (g, no_timeout) = C.wait_timeout(g, Duration::days(1)).unwrap();
|
||||
let (g, no_timeout) = C.wait_timeout_ms(g, u32::MAX).unwrap();
|
||||
assert!(no_timeout);
|
||||
drop(g);
|
||||
unsafe { C.destroy(); M.destroy(); }
|
||||
|
|
|
@ -465,9 +465,16 @@ pub fn catch_panic<F, R>(f: F) -> Result<R>
|
|||
/// specifics or platform-dependent functionality. Note that on unix platforms
|
||||
/// this function will not return early due to a signal being received or a
|
||||
/// spurious wakeup.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn sleep_ms(ms: u32) {
|
||||
imp::sleep(Duration::milliseconds(ms as i64))
|
||||
}
|
||||
|
||||
/// Deprecated: use `sleep_ms` instead.
|
||||
#[unstable(feature = "thread_sleep",
|
||||
reason = "recently added, needs an RFC, and `Duration` itself is \
|
||||
unstable")]
|
||||
#[deprecated(since = "1.0.0", reason = "use sleep_ms instead")]
|
||||
pub fn sleep(dur: Duration) {
|
||||
imp::sleep(dur)
|
||||
}
|
||||
|
@ -501,17 +508,24 @@ pub fn park() {
|
|||
/// amount of time waited to be precisely *duration* long.
|
||||
///
|
||||
/// See the module doc for more detail.
|
||||
#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
|
||||
pub fn park_timeout(duration: Duration) {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn park_timeout_ms(ms: u32) {
|
||||
let thread = current();
|
||||
let mut guard = thread.inner.lock.lock().unwrap();
|
||||
if !*guard {
|
||||
let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap();
|
||||
let (g, _) = thread.inner.cvar.wait_timeout_ms(guard, ms).unwrap();
|
||||
guard = g;
|
||||
}
|
||||
*guard = false;
|
||||
}
|
||||
|
||||
/// Deprecated: use `park_timeout_ms`
|
||||
#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
|
||||
#[deprecated(since = "1.0.0", reason = "use park_timeout_ms instead")]
|
||||
pub fn park_timeout(duration: Duration) {
|
||||
park_timeout_ms(duration.num_milliseconds() as u32)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Thread
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -716,6 +730,7 @@ mod test {
|
|||
use thread;
|
||||
use thunk::Thunk;
|
||||
use time::Duration;
|
||||
use u32;
|
||||
|
||||
// !!! These tests are dangerous. If something is buggy, they will hang, !!!
|
||||
// !!! instead of exiting cleanly. This might wedge the buildbots. !!!
|
||||
|
@ -936,14 +951,14 @@ fn test_try_panic_message_unit_struct() {
|
|||
fn test_park_timeout_unpark_before() {
|
||||
for _ in 0..10 {
|
||||
thread::current().unpark();
|
||||
thread::park_timeout(Duration::seconds(10_000_000));
|
||||
thread::park_timeout_ms(u32::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_park_timeout_unpark_not_called() {
|
||||
for _ in 0..10 {
|
||||
thread::park_timeout(Duration::milliseconds(10));
|
||||
thread::park_timeout_ms(10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -959,14 +974,13 @@ fn test_park_timeout_unpark_called_other_thread() {
|
|||
th.unpark();
|
||||
});
|
||||
|
||||
thread::park_timeout(Duration::seconds(10_000_000));
|
||||
thread::park_timeout_ms(u32::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sleep_smoke() {
|
||||
thread::sleep(Duration::milliseconds(2));
|
||||
thread::sleep(Duration::milliseconds(-2));
|
||||
fn sleep_ms_smoke() {
|
||||
thread::sleep_ms(2);
|
||||
}
|
||||
|
||||
// NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
|
||||
|
|
Loading…
Reference in a new issue