summaryrefslogtreecommitdiffstats
path: root/library/std/src/thread
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/thread')
-rw-r--r--library/std/src/thread/mod.rs82
1 files changed, 81 insertions, 1 deletions
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index e4581c2de..7b26068c2 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -178,7 +178,7 @@ use crate::sys_common::thread;
use crate::sys_common::thread_info;
use crate::sys_common::thread_parking::Parker;
use crate::sys_common::{AsInner, IntoInner};
-use crate::time::Duration;
+use crate::time::{Duration, Instant};
#[stable(feature = "scoped_threads", since = "1.63.0")]
mod scoped;
@@ -872,6 +872,86 @@ pub fn sleep(dur: Duration) {
imp::Thread::sleep(dur)
}
+/// Puts the current thread to sleep until the specified deadline has passed.
+///
+/// The thread may still be asleep after the deadline specified due to
+/// scheduling specifics or platform-dependent functionality. It will never
+/// wake before.
+///
+/// This function is blocking, and should not be used in `async` functions.
+///
+/// # Platform-specific behavior
+///
+/// This function uses [`sleep`] internally, see its platform-specific behaviour.
+///
+///
+/// # Examples
+///
+/// A simple game loop that limits the game to 60 frames per second.
+///
+/// ```no_run
+/// #![feature(thread_sleep_until)]
+/// # use std::time::{Duration, Instant};
+/// # use std::thread;
+/// #
+/// # fn update() {}
+/// # fn render() {}
+/// #
+/// let max_fps = 60.0;
+/// let frame_time = Duration::from_secs_f32(1.0/max_fps);
+/// let mut next_frame = Instant::now();
+/// loop {
+/// thread::sleep_until(next_frame);
+/// next_frame += frame_time;
+/// update();
+/// render();
+/// }
+/// ```
+///
+/// A slow api we must not call too fast and which takes a few
+/// tries before succeeding. By using `sleep_until` the time the
+/// api call takes does not influence when we retry or when we give up
+///
+/// ```no_run
+/// #![feature(thread_sleep_until)]
+/// # use std::time::{Duration, Instant};
+/// # use std::thread;
+/// #
+/// # enum Status {
+/// # Ready(usize),
+/// # Waiting,
+/// # }
+/// # fn slow_web_api_call() -> Status { Status::Ready(42) }
+/// #
+/// # const MAX_DURATION: Duration = Duration::from_secs(10);
+/// #
+/// # fn try_api_call() -> Result<usize, ()> {
+/// let deadline = Instant::now() + MAX_DURATION;
+/// let delay = Duration::from_millis(250);
+/// let mut next_attempt = Instant::now();
+/// loop {
+/// if Instant::now() > deadline {
+/// break Err(());
+/// }
+/// if let Status::Ready(data) = slow_web_api_call() {
+/// break Ok(data);
+/// }
+///
+/// next_attempt = deadline.min(next_attempt + delay);
+/// thread::sleep_until(next_attempt);
+/// }
+/// # }
+/// # let _data = try_api_call();
+/// ```
+#[unstable(feature = "thread_sleep_until", issue = "113752")]
+pub fn sleep_until(deadline: Instant) {
+ let now = Instant::now();
+
+ if let Some(delay) = deadline.checked_duration_since(now) {
+ sleep(delay);
+ }
+}
+
/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
/// cause undefined behaviour if not handled correctly (see #102398 for context).
struct PanicGuard;