@@ -178,7 +178,7 @@ use crate::sys_common::thread;
178178use crate :: sys_common:: thread_info;
179179use crate :: sys_common:: thread_parking:: Parker ;
180180use crate :: sys_common:: { AsInner , IntoInner } ;
181- use crate :: time:: Duration ;
181+ use crate :: time:: { Duration , Instant } ;
182182
183183#[ stable( feature = "scoped_threads" , since = "1.63.0" ) ]
184184mod scoped;
@@ -872,6 +872,86 @@ pub fn sleep(dur: Duration) {
872872 imp:: Thread :: sleep ( dur)
873873}
874874
875+ /// Puts the current thread to sleep until the specified deadline has passed.
876+ ///
877+ /// The thread may still be asleep after the deadline specified due to
878+ /// scheduling specifics or platform-dependent functionality. It will never
879+ /// wake before.
880+ ///
881+ /// This function is blocking, and should not be used in `async` functions.
882+ ///
883+ /// # Platform-specific behavior
884+ ///
885+ /// This function uses [`sleep`] internally, see its platform-specific behaviour.
886+ ///
887+ ///
888+ /// # Examples
889+ ///
890+ /// A simple game loop that limits the game to 60 frames per second.
891+ ///
892+ /// ```no_run
893+ /// #![feature(thread_sleep_until)]
894+ /// # use std::time::{Duration, Instant};
895+ /// # use std::thread;
896+ /// #
897+ /// # fn update() {}
898+ /// # fn render() {}
899+ /// #
900+ /// let max_fps = 60.0;
901+ /// let frame_time = Duration::from_secs_f32(1.0/max_fps);
902+ /// let mut next_frame = Instant::now();
903+ /// loop {
904+ /// thread::sleep_until(next_frame);
905+ /// next_frame += frame_time;
906+ /// update();
907+ /// render();
908+ /// }
909+ /// ```
910+ ///
911+ /// A slow api we must not call too fast and which takes a few
912+ /// tries before succeeding. By using `sleep_until` the time the
913+ /// api call takes does not influence when we retry or when we give up
914+ ///
915+ /// ```no_run
916+ /// #![feature(thread_sleep_until)]
917+ /// # use std::time::{Duration, Instant};
918+ /// # use std::thread;
919+ /// #
920+ /// # enum Status {
921+ /// # Ready(usize),
922+ /// # Waiting,
923+ /// # }
924+ /// # fn slow_web_api_call() -> Status { Status::Ready(42) }
925+ /// #
926+ /// # const MAX_DURATION: Duration = Duration::from_secs(10);
927+ /// #
928+ /// # fn try_api_call() -> Result<usize, ()> {
929+ /// let deadline = Instant::now() + MAX_DURATION;
930+ /// let delay = Duration::from_millis(250);
931+ /// let mut next_attempt = Instant::now();
932+ /// loop {
933+ /// if Instant::now() > deadline {
934+ /// break Err(());
935+ /// }
936+ /// if let Status::Ready(data) = slow_web_api_call() {
937+ /// break Ok(data);
938+ /// }
939+ ///
940+ /// next_attempt = deadline.min(next_attempt + delay);
941+ /// thread::sleep_until(next_attempt);
942+ /// }
943+ /// # }
944+ /// # let _data = try_api_call();
945+ /// ```
946+ #[ unstable( feature = "thread_sleep_until" , issue = "113752" ) ]
947+ pub fn sleep_until ( deadline : Instant ) {
948+ let now = Instant :: now ( ) ;
949+
950+ if let Some ( delay) = deadline. checked_duration_since ( now) {
951+ sleep ( delay) ;
952+ }
953+ }
954+
875955/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
876956/// cause undefined behaviour if not handled correctly (see #102398 for context).
877957struct PanicGuard ;
0 commit comments