pub const Clock = enum
pub const Clock = enum {
/// A settable system-wide clock that measures real (i.e. wall-clock)
/// time. This clock is affected by discontinuous jumps in the system
/// time (e.g., if the system administrator manually changes the
/// clock), and by frequency adjustments performed by NTP and similar
/// applications.
///
/// This clock normally counts the number of seconds since 1970-01-01
/// 00:00:00 Coordinated Universal Time (UTC) except that it ignores
/// leap seconds; near a leap second it is typically adjusted by NTP to
/// stay roughly in sync with UTC.
///
/// Timestamps returned by implementations of this clock represent time
/// elapsed since 1970-01-01T00:00:00Z, the POSIX/Unix epoch, ignoring
/// leap seconds. This is colloquially known as "Unix time". If the
/// underlying OS uses a different epoch for native timestamps (e.g.,
/// Windows, which uses 1601-01-01) they are translated accordingly.
real,
/// A nonsettable system-wide clock that represents time since some
/// unspecified point in the past.
///
/// Monotonic: Guarantees that the time returned by consecutive calls
/// will not go backwards, but successive calls may return identical
/// (not-increased) time values.
///
/// Not affected by discontinuous jumps in the system time (e.g., if
/// the system administrator manually changes the clock), but may be
/// affected by frequency adjustments.
///
/// This clock expresses intent to **exclude time that the system is
/// suspended**. However, implementations may be unable to satisify
/// this, and may include that time.
///
/// * On Linux, corresponds `CLOCK_MONOTONIC`.
/// * On macOS, corresponds to `CLOCK_UPTIME_RAW`.
awake,
/// Identical to `awake` except it expresses intent to **include time
/// that the system is suspended**, however, due to limitations it may
/// behave identically to `awake`.
///
/// * On Linux, corresponds `CLOCK_BOOTTIME`.
/// * On macOS, corresponds to `CLOCK_MONOTONIC_RAW`.
boot,
/// Tracks the amount of CPU in user or kernel mode used by the calling
/// process.
cpu_process,
/// Tracks the amount of CPU in user or kernel mode used by the calling
/// thread.
cpu_thread,
/// This function is not cancelable because it does not block.
///
/// Resolution is determined by `resolution` which may be 0 if the
/// clock is unsupported.
///
/// See also:
/// * `Clock.Timestamp.now`
pub fn now(clock: Clock, io: Io) Io.Timestamp {
return io.vtable.now(io.userdata, clock);
}
pub const ResolutionError = error{
ClockUnavailable,
Unexpected,
};
/// Reveals the granularity of `clock`. May be zero, indicating
/// unsupported clock.
pub fn resolution(clock: Clock, io: Io) ResolutionError!Io.Duration {
return io.vtable.clockResolution(io.userdata, clock);
}
pub const Timestamp = struct {
raw: Io.Timestamp,
clock: Clock,
/// This function is not cancelable because it does not block.
///
/// Resolution is determined by `resolution` which may be 0 if
/// the clock is unsupported.
///
/// See also:
/// * `Clock.now`
pub fn now(io: Io, clock: Clock) Clock.Timestamp {
return .{
.raw = io.vtable.now(io.userdata, clock),
.clock = clock,
};
}
/// Sleeps until the timestamp arrives.
///
/// See also:
/// * `Io.sleep`
/// * `Clock.Duration.sleep`
/// * `Timeout.sleep`
pub fn wait(t: Clock.Timestamp, io: Io) Cancelable!void {
return io.vtable.sleep(io.userdata, .{ .deadline = t });
}
pub fn durationTo(from: Clock.Timestamp, to: Clock.Timestamp) Clock.Duration {
assert(from.clock == to.clock);
return .{
.raw = from.raw.durationTo(to.raw),
.clock = from.clock,
};
}
pub fn addDuration(from: Clock.Timestamp, duration: Clock.Duration) Clock.Timestamp {
assert(from.clock == duration.clock);
return .{
.raw = from.raw.addDuration(duration.raw),
.clock = from.clock,
};
}
pub fn subDuration(from: Clock.Timestamp, duration: Clock.Duration) Clock.Timestamp {
assert(from.clock == duration.clock);
return .{
.raw = from.raw.subDuration(duration.raw),
.clock = from.clock,
};
}
/// Resolution is determined by `resolution` which may be 0 if
/// the clock is unsupported.
pub fn fromNow(io: Io, duration: Clock.Duration) Clock.Timestamp {
return .{
.clock = duration.clock,
.raw = duration.clock.now(io).addDuration(duration.raw),
};
}
/// Resolution is determined by `resolution` which may be 0 if
/// the clock is unsupported.
pub fn untilNow(timestamp: Clock.Timestamp, io: Io) Clock.Duration {
const now_ts = Clock.Timestamp.now(io, timestamp.clock);
return timestamp.durationTo(now_ts);
}
/// Resolution is determined by `resolution` which may be 0 if
/// the clock is unsupported.
pub fn durationFromNow(timestamp: Clock.Timestamp, io: Io) Clock.Duration {
const now_ts = timestamp.clock.now(io);
return .{
.clock = timestamp.clock,
.raw = now_ts.durationTo(timestamp.raw),
};
}
/// Resolution is determined by `resolution` which may be 0 if
/// the clock is unsupported.
pub fn toClock(t: Clock.Timestamp, io: Io, clock: Clock) Clock.Timestamp {
if (t.clock == clock) return t;
const now_old = t.clock.now(io);
const now_new = clock.now(io);
const duration = now_old.durationTo(t.raw);
return .{
.clock = clock,
.raw = now_new.addDuration(duration),
};
}
pub fn compare(lhs: Clock.Timestamp, op: math.CompareOperator, rhs: Clock.Timestamp) bool {
assert(lhs.clock == rhs.clock);
return math.compare(lhs.raw.nanoseconds, op, rhs.raw.nanoseconds);
}
};
pub const Duration = struct {
raw: Io.Duration,
clock: Clock,
/// Waits until a specified amount of time has passed on `clock`.
///
/// See also:
/// * `Io.sleep`
/// * `Clock.Timestamp.wait`
/// * `Timeout.sleep`
pub fn sleep(duration: Clock.Duration, io: Io) Cancelable!void {
return io.vtable.sleep(io.userdata, .{ .duration = duration });
}
};
}