Skip to content

Commit be84872

Browse files
committed
adds specialized impl for sleep_until for windows
1 parent c9e56ac commit be84872

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

library/std/src/sys/pal/windows/thread.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
use crate::io;
2+
use crate::num::NonZeroUsize;
3+
use crate::os::windows::io::AsRawHandle;
4+
use crate::os::windows::io::HandleOrNull;
5+
use crate::ptr;
6+
use crate::sys::c;
7+
use crate::sys::handle::Handle;
8+
use crate::sys::stack_overflow;
9+
use crate::sys_common::FromInner;
10+
use crate::time::{Duration, Instant};
11+
112
use core::ffi::c_void;
213

314
use super::time::WaitableTimer;
@@ -106,11 +117,22 @@ impl Thread {
106117
}
107118

108119
pub fn sleep_until(deadline: Instant) {
109-
let now = Instant::now();
110-
111-
if let Some(delay) = deadline.checked_duration_since(now) {
112-
sleep(delay);
120+
fn high_precision_sleep(deadline: Instant) -> Result<(), ()> {
121+
let timer = WaitableTimer::high_resolution()?;
122+
timer.set_deadline(deadline.into_inner())?;
123+
timer.wait()
113124
}
125+
// Attempt to use high-precision sleep (Windows 10, version 1803+).
126+
// On error fallback to the standard `Sleep` function.
127+
// Also preserves the zero duration behaviour of `Sleep`.
128+
if high_precision_sleep(deadline).is_ok() {
129+
return;
130+
}
131+
132+
let now = Instant::now();
133+
if let Some(dur) = deadline.checked_duration_since(now) {
134+
unsafe { c::Sleep(super::dur2timeout(dur)) }
135+
};
114136
}
115137

116138
pub fn handle(&self) -> &Handle {

library/std/src/sys/pal/windows/time.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ impl WaitableTimer {
248248
let result = unsafe { c::SetWaitableTimer(self.handle, &time, 0, None, null(), c::FALSE) };
249249
if result != 0 { Ok(()) } else { Err(()) }
250250
}
251+
pub fn set_deadline(&self, deadline: Instant) -> Result<(), ()> {
252+
// Convert the Instant to a format similar to FILETIME.
253+
let time = checked_dur2intervals(&deadline.t).ok_or(())?;
254+
let result = unsafe { c::SetWaitableTimer(self.handle, &time, 0, None, null(), c::FALSE) };
255+
if result != 0 { Ok(()) } else { Err(()) }
256+
}
251257
pub fn wait(&self) -> Result<(), ()> {
252258
let result = unsafe { c::WaitForSingleObject(self.handle, c::INFINITE) };
253259
if result != c::WAIT_FAILED { Ok(()) } else { Err(()) }

0 commit comments

Comments
 (0)