rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.91k stars 12.67k forks source link

Tracking Issue for thread::sleep_until #113752

Open dvdsk opened 1 year ago

dvdsk commented 1 year ago

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

dvdsk commented 1 year ago

The clock

Each of the three options has its downsides:

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:

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?

SUPERCILEX commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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

joboet commented 1 year ago

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 commented 1 year ago

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

dvdsk commented 11 months ago

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 commented 11 months ago

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

Ignored

biabbas commented 2 months ago

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