diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index c5c86d8301d1..045082949812 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -287,10 +287,24 @@ pub fn sleep(dur: Duration) { }; // If we're awoken with a signal then the return value will be -1 and // nanosleep will fill in `ts` with the remaining time. - while libc::nanosleep(&ts, &mut ts) == -1 { + while dosleep(&mut ts) == -1 { assert_eq!(os::errno(), libc::EINTR); } } + + #[cfg(target_os = "linux")] + unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int { + extern { + fn clock_nanosleep(clock_id: libc::c_int, flags: libc::c_int, + request: *const libc::timespec, + remain: *mut libc::timespec) -> libc::c_int; + } + clock_nanosleep(libc::CLOCK_MONOTONIC, 0, ts, ts) + } + #[cfg(not(target_os = "linux"))] + unsafe fn dosleep(ts: *mut libc::timespec) -> libc::c_int { + libc::nanosleep(ts, ts) + } } // glibc >= 2.15 has a __pthread_get_minstack() function that returns diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index b361faba0f62..d1d4ad90081b 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -20,6 +20,7 @@ use ptr; use sys_common::stack::RED_ZONE; use sys_common::thread::*; use thunk::Thunk; +use time::Duration; pub type rust_thread = HANDLE; @@ -82,6 +83,20 @@ pub unsafe fn yield_now() { SwitchToThread(); } +pub fn sleep(dur: Duration) { + unsafe { + if dur < Duration::zero() { + return yield_now() + } + let ms = dur.num_milliseconds(); + // if we have a fractional number of milliseconds then add an extra + // millisecond to sleep for + let extra = dur - Duration::milliseconds(ms); + let ms = ms + if extra.is_zero() {0} else {1}; + Sleep(ms as DWORD); + } +} + #[allow(non_snake_case)] extern "system" { fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES, @@ -92,4 +107,5 @@ extern "system" { lpThreadId: LPDWORD) -> HANDLE; fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; fn SwitchToThread() -> BOOL; + fn Sleep(dwMilliseconds: DWORD); } diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index adc3b77407a6..0216f324fdbc 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -379,6 +379,19 @@ pub fn panicking() -> bool { unwind::panicking() } +/// Put the current thread to sleep for the specified amount of time. +/// +/// The thread may sleep longer than the duration specified due to scheduling +/// 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. +#[unstable(feature = "thread_sleep", + reason = "recently added, needs an RFC, and `Duration` itself is \ + unstable")] +pub fn sleep(dur: Duration) { + imp::sleep(dur) +} + /// Block unless or until the current thread's token is made available (may wake spuriously). /// /// See the module doc for more detail. @@ -935,6 +948,12 @@ mod test { } } + #[test] + fn sleep_smoke() { + thread::sleep(Duration::milliseconds(2)); + thread::sleep(Duration::milliseconds(-2)); + } + // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due // to the test harness apparently interfering with stderr configuration. }