Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking Issue for thread::sleep_until #113752

Open
2 of 5 tasks
dvdsk opened this issue Jul 16, 2023 · 11 comments
Open
2 of 5 tasks

Tracking Issue for thread::sleep_until #113752

dvdsk opened this issue Jul 16, 2023 · 11 comments
Labels
C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-sleep_until `#![feature(sleep_until)]` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@dvdsk
Copy link
Contributor

dvdsk commented Jul 16, 2023

Feature gate: #![feature(sleep_until)]

This is a tracking issue for the thread::sleep_until method. It pauses the
current thread until a given deadline.

Public API

// std::thread

pub fn sleep_until(deadline: Instant)

Steps / History

Unresolved Questions

  • Clock used: should the clock be the same as thread::sleep, something different or passed
    in by the user?
  • Deadline type: should the argument be an Instant, a SystemTime or do we support both?

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

@dvdsk dvdsk added C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Jul 16, 2023
@dvdsk
Copy link
Contributor Author

dvdsk commented Jul 16, 2023

The clock

Each of the three options has its downsides:

  • Sleep is not consistent between platforms. For example on Linux time
    suspended is not counted while on other Unixes it is. Not counting time
    suspended is a bad default, kernel devs tried to fix, which caused enough issues it was reverted soon after. That just underlines the need to get this right before stabilizing.

  • Using a different clock could get confusing, for example when the time slept
    by sleep_until was different from what a sleep call would yield. Finally, if
    the argument is of type Instant then the time slept should match what
    Instant::elapsed reports. It currently uses the Monotonic clock on all
    platforms.

  • Making the clock a choice, means designing a new clock API (proposed in the
    APC by @the8472). It would make 'sleep_until' more complex to use and breaks
    the similarity between it and sleep.

I think the clock question is not constrained to sleep_until. There are more
APIs that could support configurable clocks. I propose we separate that question
from sleep_until and address it in its own APC.

There we can figure out:

  • Whether configurable clocks fit in the std.
  • Which parts of the std to extend/support.
  • What form the new API takes.
  • How to support all platforms and deal with platforms without a real OS but
    that still support the std such as the esp32.

I would love to write a Pre-Rfc for such an API if we decide to go that route.

Type of the deadline argument

I am in favor of using Instant, that implies monotonic behavior which is
needed for most use cases (cache invalidation etc.). We could offer a version
that can take a SystemTime as argument. I am not aware of any use cases for
that though I would love to hear them.

If we decide to support both we need to figure out if we want two functions or
a generic argument. The latter would involve introducing a trait, maybe
Deadline?

bors added a commit to rust-lang-ci/rust that referenced this issue Sep 17, 2023
Add implementation for thread::sleep_until

- Feature gate is `thread::sleep_until`
- Tracking issue is: rust-lang#113752
- APC: rust-lang/libs-team#237
@SUPERCILEX
Copy link
Contributor

SUPERCILEX commented Sep 24, 2023

Are there OS APIs that support sleeping to a deadline? The current implementation will have large tail latencies:

    let now = Instant::now();

    if let Some(delay) = deadline.checked_duration_since(now) {
        // Context switch here. Oops, now we'll end up arbitrarily blowing past the deadline
        sleep(delay);
    }

@the8472
Copy link
Member

the8472 commented Sep 24, 2023

There's clock_nanosleep that supports deadlines, it has been part of POSIX for a while so I assume a lot of unices have it.

@the8472
Copy link
Member

the8472 commented Sep 24, 2023

We could offer a version that can take a SystemTime as argument. I am not aware of any use cases for that though I would love to hear them.

Wall-time based synchronization/execution of events. E.g. if something is supposed to run in a cronjob-like fashion. Or a distributed protocol that says "nodes try to rendezvous every 5 minutes, at the start of a minute divisible by 5, UTC".

@dvdsk
Copy link
Contributor Author

dvdsk commented Sep 24, 2023

There's clock_nanosleep that supports deadlines, it has been part of POSIX for a while so I assume a lot of unices have it.

Thanks for bringing this up! We can freely use that on Linux, the minimum kernel version current Rust supports includes it. I would have to check it for POSIX. Even if that does not pan out we should 'specialize' this method on Linux.

Before we go down that road I would like to nail down the API. To answer that we must know whether we want a Clock API in Rust. That however is better addressed in a separate proposal. I am more then willing to write that up however I would like to estimate interest first.

I am not sure how to proceed there, an option would be to create a crate that adds a clock API to std-lib functions/types where appropriate (using traits). Then look at how popular that gets over time. (taking care to prevent an itertools situation). Another easier path would be a users forum post or github code search.

@the8472
Copy link
Member

the8472 commented Sep 24, 2023

You could also look at prior art in other languages and frequently used libraries. E.g. C++ has it std::chrono.

@joboet
Copy link
Contributor

joboet commented Sep 24, 2023

There's clock_nanosleep that supports deadlines, it has been part of POSIX for a while so I assume a lot of unices have it.

macOS and the other Apple platforms don't have it, even on the newest versions.

@the8472
Copy link
Member

the8472 commented Sep 24, 2023

There seems to be a function called mach_wait_until but I can't find any docs for it.

@dvdsk
Copy link
Contributor Author

dvdsk commented Nov 23, 2023

Replying to @neachdainn who commented on the RFC

I just want to point out that the proposed solution isn't a full.

It's temporary, the idea was to see if we could take the clock choice further and introduce a clock API. That would allow use of clocks that are not supported on each platform (such as clock BOOTTIME). Unfortunately I haven't done that yet.

I am gonna paraphrase your use case here, I think it is an important one:

use case: running a robotic control. Using an OS. Need to make sure that the thread is going to wake up at exactly the specified time:

fn run() {
  let deadline = Instant::now() + INTERVAL;
  loop {
    do_quick_calculation_and_set_pins();
    thread::sleep_until(deadline);
    deadline += INTERVAL;
  }
}

As it is critical to the above use case I will open a PR to switch over the placeholder implementation for Linux to use clock_nanosleep with TIMER_ABSTIME. We should also document the behavior when using real time schedulers.

Then I will see if we can get the same behavior on the other operation systems.

@dvdsk
Copy link
Contributor Author

dvdsk commented Nov 26, 2023

This is a tracking comment tracking the effort to specialize/optimizing the sleep_until implementation for major target_os's.

Possible/In progress:

Seems impossible for now

Hard

  • espidf, could not find a documentation listing supported Libc api's/Syscalls

Ignored

  • aix
  • emscripten
  • haiku
  • hermit
  • horizon
  • hurd
  • l4re
  • nto
  • psp
  • redox
  • solid_asp3
  • uefi
  • unknown
  • vita
  • vxworks
  • xous

@biabbas
Copy link
Contributor

biabbas commented Aug 9, 2024

@dvdsk Clock Nano sleep is available in libc for VxWorks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-sleep_until `#![feature(sleep_until)]` T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants