rust-lang / rust-lang/libs-team

allow specifying whether `Instant` should be suspend-aware

Open
#733 10 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

ACP-accepted api-change-proposal
Dominant language
Rust
Stars
178
Forks
28
Avg merge
15m
Merged PRs (30d)
1

Description

Proposal

Problem statement

Currently, whether Instant counts time during system sleep or hibernation is platform-dependent, but quite a lot of programs need to decide this explicitly.

Motivating examples or use cases

Quite a lot of system and interactive software needs to explicitly decide whether to count time during suspend/hibernate. For instance, an audio player might not want to count suspended time against the audio play time, since nothing was actually played during suspend. An audio streaming solution, on the other hand, needs to be aware of suspend time in order to better track latencies. Similarly, a network server might want to count suspend times against timeout, but a browser might want to freeze animations across a suspend.

Solution sketch

I'd like to propose modifying the API of Instant to take account the clock choice:

// in std::time

struct Instant<C: Clock = ContinuousClock> { .. }

impl Instant<ContinuousClock> {
    fn now() -> Instant;
}

impl<C: Clock> Instant<C> {
    /* all methods except now */
}

trait Clock: Sealed {
    fn now(&self) -> Instant<Self>;

    // And potentially:
    fn resolution(&self) -> Duration;
    fn sleep(&self, duration: Duration);
    fn sleep_until(&self, deadline: Instant<Self>);
}

struct ContinuousClock;

impl Clock for ContinuousClock {}

struct SuspendingClock;

impl Clock for SuspendingClock {}

and (perhaps) deprecate Instant::now in favour of ContinuousClock.now()/SuspendingClock.now(). Solving this using generics means that it is impossible to compare times across clocks, which is (in most cases) meaningless anyway.

Drawbacks

This is difficult to implement on Windows. While the QueryInterruptTimePrecise and QueryUnbiasedInterruptTimePrecise display the correct behaviour, they have less precision (up to 100 ns precision) than the QueryPerformanceCounter API (potentially nanosecond precision, although realistically at least 5 ns since RDTSC takes a few cycles itself) currently used for Instant. Also, Windows (AFAIK) doesn't have a suspend-tracking sleep operation.

This switches the current behaviour of Instant on macOS and Linux, where Instant currently doesn't count time during suspend.

Alternatives

  • Make SuspendingClock the default clock – this preserves the current Instant behaviour on Linux and macOS, but changes behaviour on Windows (QueryPerformanceCounter advances time during sleep). I find that most uses of Instant are related to timeouts and deadlines – for those, tracking suspend time is a good idea.
  • Make now generic and implement it for Clock + Default.
  • Add a new Instant-like type for the other clock type.
  • Also add WalltimeClock and make SystemTime an alias for Instant<WalltimeClock>. That would result in problems for the time arithmetic functions however, as e.g. SystemTime::duration_since returns a Result<Duration, SystemTimeError, but the current Instant::duration_since is infallible.

Links and related work

This is heavily inspired by Swift's clock support, see SE-0329 and the API documentation that resulted from it.

What happens now?

This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

Possible responses

The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):

  • We think this problem seems worth solving, and the standard library might be the right place to solve it.
  • We think that this probably doesn't belong in the standard library.

Second, if there's a concrete solution:

  • We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
  • We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the proposed std::time API for Instant, Clock, ContinuousClock, and SuspendingClock, then read the linked feature lifecycle. Compare the Windows, macOS, and Linux clock behavior described in the issue and review the listed alternatives. Done means an agreed libs-api direction or approved design, not an implementation patch.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design, operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.