@@ -178,7 +178,7 @@ use crate::sys_common::thread;
178
178
use crate :: sys_common:: thread_info;
179
179
use crate :: sys_common:: thread_parking:: Parker ;
180
180
use crate :: sys_common:: { AsInner , IntoInner } ;
181
- use crate :: time:: Duration ;
181
+ use crate :: time:: { Duration , Instant } ;
182
182
183
183
#[ stable( feature = "scoped_threads" , since = "1.63.0" ) ]
184
184
mod scoped;
@@ -872,6 +872,86 @@ pub fn sleep(dur: Duration) {
872
872
imp:: Thread :: sleep ( dur)
873
873
}
874
874
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
+
875
955
/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
876
956
/// cause undefined behaviour if not handled correctly (see #102398 for context).
877
957
struct PanicGuard ;
0 commit comments