Skip to content

std.time: renamed Timer to Stopwatch #24372

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/std/Build/Step.zig
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
const b = s.owner;
const arena = b.allocator;

var timer = try std.time.Timer.start();
var stopwatch = try std.time.Stopwatch.start();

try sendMessage(zp.child.stdin.?, .update);
if (!watch) try sendMessage(zp.child.stdin.?, .exit);
Expand Down Expand Up @@ -617,7 +617,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
stdout.discard(body.len);
}

s.result_duration_ns = timer.read();
s.result_duration_ns = stopwatch.read();

const stderr = zp.poller.fifo(.stderr);
if (stderr.readableLength() > 0) {
Expand Down
14 changes: 7 additions & 7 deletions lib/std/Thread/Futex.zig
Original file line number Diff line number Diff line change
Expand Up @@ -406,10 +406,10 @@ const OpenbsdImpl = struct {
const DragonflyImpl = struct {
fn wait(ptr: *const atomic.Value(u32), expect: u32, timeout: ?u64) error{Timeout}!void {
// Dragonfly uses a scheme where 0 timeout means wait until signaled or spurious wake.
// It's reporting of timeout's is also unrealiable so we use an external timing source (Timer) instead.
// It's reporting of timeouts is also unreliable so we use an external timing source (Stopwatch) instead.
var timeout_us: c_int = 0;
var timeout_overflowed = false;
var sleep_timer: std.time.Timer = undefined;
var sleep_stopwatch: std.time.Stopwatch = undefined;

if (timeout) |delay| {
assert(delay != 0); // handled by timedWait().
Expand All @@ -420,7 +420,7 @@ const DragonflyImpl = struct {

// Only need to record the start time if we can provide somewhat accurate error.Timeout's
if (!timeout_overflowed) {
sleep_timer = std.time.Timer.start() catch unreachable;
sleep_stopwatch = std.time.Stopwatch.start() catch unreachable;
}
}

Expand All @@ -435,7 +435,7 @@ const DragonflyImpl = struct {
if (timeout) |timeout_ns| {
// Report error.Timeout only if we know the timeout duration has passed.
// If not, there's not much choice other than treating it as a spurious wake.
if (!timeout_overflowed and sleep_timer.read() >= timeout_ns) {
if (!timeout_overflowed and sleep_stopwatch.read() >= timeout_ns) {
return error.Timeout;
}
}
Expand Down Expand Up @@ -1015,17 +1015,17 @@ test "broadcasting" {
/// to Futex timedWait() can block for and report more accurate error.Timeouts.
pub const Deadline = struct {
timeout: ?u64,
started: std.time.Timer,
started: std.time.Stopwatch,

/// Create the deadline to expire after the given amount of time in nanoseconds passes.
/// Pass in `null` to have the deadline call `Futex.wait()` and never expire.
pub fn init(expires_in_ns: ?u64) Deadline {
var deadline: Deadline = undefined;
deadline.timeout = expires_in_ns;

// std.time.Timer is required to be supported for somewhat accurate reportings of error.Timeout.
// std.time.Stopwatch is required to be supported for somewhat accurate reportings of error.Timeout.
if (deadline.timeout != null) {
deadline.started = std.time.Timer.start() catch unreachable;
deadline.started = std.time.Stopwatch.start() catch unreachable;
}

return deadline;
Expand Down
46 changes: 23 additions & 23 deletions lib/std/time.zig
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pub const s_per_week = s_per_day * 7;
///
/// It tries to sample the system's fastest and most precise timer available.
/// It also tries to be monotonic, but this is not a guarantee due to OS/hardware bugs.
/// If you need monotonic readings for elapsed time, consider `Timer` instead.
/// If you need monotonic readings for elapsed time, consider `Stopwatch` instead.
pub const Instant = struct {
timestamp: if (is_posix) posix.timespec else u64,

Expand Down Expand Up @@ -220,52 +220,52 @@ pub const Instant = struct {
}
};

/// A monotonic, high performance timer.
/// A monotonic, high performance stopwatch.
///
/// Timer.start() is used to initialize the timer
/// Stopwatch.start() is used to initialize the stopwatch
/// and gives the caller an opportunity to check for the existence of a supported clock.
/// Once a supported clock is discovered,
/// it is assumed that it will be available for the duration of the Timer's use.
/// it is assumed that it will be available while the Stopwatch is in use.
///
/// Monotonicity is ensured by saturating on the most previous sample.
/// This means that while timings reported are monotonic,
/// they're not guaranteed to tick at a steady rate as this is up to the underlying system.
pub const Timer = struct {
pub const Stopwatch = struct {
started: Instant,
previous: Instant,

pub const Error = error{TimerUnsupported};
pub const Error = error{StopwatchUnsupported};

/// Initialize the timer by querying for a supported clock.
/// Returns `error.TimerUnsupported` when such a clock is unavailable.
/// Initialize the stopwatch by querying for a supported clock.
/// Returns `error.StopwatchUnsupported` when such a clock is unavailable.
/// This should only fail in hostile environments such as linux seccomp misuse.
pub fn start() Error!Timer {
const current = Instant.now() catch return error.TimerUnsupported;
return Timer{ .started = current, .previous = current };
pub fn start() Error!Stopwatch {
const current = Instant.now() catch return .StopwatchUnsupported;
return Stopwatch{ .started = current, .previous = current };
}

/// Reads the timer value since start or the last reset in nanoseconds.
pub fn read(self: *Timer) u64 {
/// Reads the stopwatch value since start or the last reset in nanoseconds.
pub fn read(self: *Stopwatch) u64 {
const current = self.sample();
return current.since(self.started);
}

/// Resets the timer value to 0/now.
pub fn reset(self: *Timer) void {
/// Resets the stopwatch value to 0/now.
pub fn reset(self: *Stopwatch) void {
const current = self.sample();
self.started = current;
}

/// Returns the current value of the timer in nanoseconds, then resets it.
pub fn lap(self: *Timer) u64 {
/// Returns the current value of the stopwatch in nanoseconds, then resets it.
pub fn lap(self: *Stopwatch) u64 {
const current = self.sample();
defer self.started = current;
return current.since(self.started);
}

/// Returns an Instant sampled at the callsite that is
/// guaranteed to be monotonic with respect to the timer's starting point.
fn sample(self: *Timer) Instant {
/// guaranteed to be monotonic with respect to the starting point of the stopwatch.
fn sample(self: *Stopwatch) Instant {
const current = Instant.now() catch unreachable;
if (current.order(self.previous) == .gt) {
self.previous = current;
Expand All @@ -274,14 +274,14 @@ pub const Timer = struct {
}
};

test Timer {
var timer = try Timer.start();
test Stopwatch {
var stopwatch = try Stopwatch.start();

std.Thread.sleep(10 * ns_per_ms);
const time_0 = timer.read();
const time_0 = stopwatch.read();
try testing.expect(time_0 > 0);

const time_1 = timer.lap();
const time_1 = stopwatch.lap();
try testing.expect(time_1 >= time_0);
}

Expand Down