Skip to content

Commit fe4340a

Browse files
committed
Auto merge of #21788 - carllerche:master, r=alexcrichton
The implementation is similar to `Thread::park`
2 parents a2aee62 + 60ba03d commit fe4340a

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

src/libstd/thread.rs

+56-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@
123123
//! * The `Thread::park()` function blocks the current thread unless or until
124124
//! the token is available for its thread handle, at which point It atomically
125125
//! consumes the token. It may also return *spuriously*, without consuming the
126-
//! token.
126+
//! token. `Thread::park_timeout()` does the same, but allows specifying a
127+
//! maximum time to block the thread for.
127128
//!
128129
//! * The `unpark()` method on a `Thread` atomically makes the token available
129130
//! if it wasn't already.
@@ -160,6 +161,7 @@ use string::String;
160161
use rt::{self, unwind};
161162
use old_io::{Writer, stdio};
162163
use thunk::Thunk;
164+
use time::Duration;
163165

164166
use sys::thread as imp;
165167
use sys_common::{stack, thread_info};
@@ -414,6 +416,27 @@ impl Thread {
414416
*guard = false;
415417
}
416418

419+
/// Block unless or until the current thread's token is made available or
420+
/// the specified duration has been reached (may wake spuriously).
421+
///
422+
/// The semantics of this function are equivalent to `park()` except that the
423+
/// thread will be blocked for roughly no longer than dur. This method
424+
/// should not be used for precise timing due to anomalies such as
425+
/// preemption or platform differences that may not cause the maximum
426+
/// amount of time waited to be precisely dur
427+
///
428+
/// See the module doc for more detail.
429+
#[unstable(feature = "std_misc", reason = "recently introduced")]
430+
pub fn park_timeout(dur: Duration) {
431+
let thread = Thread::current();
432+
let mut guard = thread.inner.lock.lock().unwrap();
433+
if !*guard {
434+
let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
435+
guard = g;
436+
}
437+
*guard = false;
438+
}
439+
417440
/// Atomically makes the handle's token available if it is not already.
418441
///
419442
/// See the module doc for more detail.
@@ -519,6 +542,7 @@ mod test {
519542
use std::old_io::{ChanReader, ChanWriter};
520543
use super::{Thread, Builder};
521544
use thunk::Thunk;
545+
use time::Duration;
522546

523547
// !!! These tests are dangerous. If something is buggy, they will hang, !!!
524548
// !!! instead of exiting cleanly. This might wedge the buildbots. !!!
@@ -733,6 +757,37 @@ mod test {
733757
assert_eq!(output, "Hello, world!".to_string());
734758
}
735759

760+
#[test]
761+
fn test_park_timeout_unpark_before() {
762+
for _ in 0..10 {
763+
Thread::current().unpark();
764+
Thread::park_timeout(Duration::seconds(10_000_000));
765+
}
766+
}
767+
768+
#[test]
769+
fn test_park_timeout_unpark_not_called() {
770+
for _ in 0..10 {
771+
Thread::park_timeout(Duration::milliseconds(10));
772+
}
773+
}
774+
775+
#[test]
776+
fn test_park_timeout_unpark_called_other_thread() {
777+
use std::old_io;
778+
779+
for _ in 0..10 {
780+
let th = Thread::current();
781+
782+
let _guard = Thread::scoped(move || {
783+
old_io::timer::sleep(Duration::milliseconds(50));
784+
th.unpark();
785+
});
786+
787+
Thread::park_timeout(Duration::seconds(10_000_000));
788+
}
789+
}
790+
736791
// NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
737792
// to the test harness apparently interfering with stderr configuration.
738793
}

0 commit comments

Comments
 (0)