mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
std.Progress: make the API infallible
by handling `error.TimerUnsupported`. In this case, only explicit calls to refresh() will cause the progress line to be printed.
This commit is contained in:
parent
fd6c351263
commit
5a00e24963
4 changed files with 21 additions and 23 deletions
|
|
@ -35,7 +35,7 @@ root: Node = undefined,
|
||||||
|
|
||||||
/// Keeps track of how much time has passed since the beginning.
|
/// Keeps track of how much time has passed since the beginning.
|
||||||
/// Used to compare with `initial_delay_ms` and `refresh_rate_ms`.
|
/// Used to compare with `initial_delay_ms` and `refresh_rate_ms`.
|
||||||
timer: std.time.Timer = undefined,
|
timer: ?std.time.Timer = null,
|
||||||
|
|
||||||
/// When the previous refresh was written to the terminal.
|
/// When the previous refresh was written to the terminal.
|
||||||
/// Used to compare with `refresh_rate_ms`.
|
/// Used to compare with `refresh_rate_ms`.
|
||||||
|
|
@ -139,7 +139,7 @@ pub const Node = struct {
|
||||||
/// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this
|
/// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this
|
||||||
/// API to return Progress rather than accept it as a parameter.
|
/// API to return Progress rather than accept it as a parameter.
|
||||||
/// `estimated_total_items` value of 0 means unknown.
|
/// `estimated_total_items` value of 0 means unknown.
|
||||||
pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !*Node {
|
pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) *Node {
|
||||||
const stderr = std.io.getStdErr();
|
const stderr = std.io.getStdErr();
|
||||||
self.terminal = null;
|
self.terminal = null;
|
||||||
if (stderr.supportsAnsiEscapeCodes()) {
|
if (stderr.supportsAnsiEscapeCodes()) {
|
||||||
|
|
@ -161,22 +161,24 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !*
|
||||||
};
|
};
|
||||||
self.columns_written = 0;
|
self.columns_written = 0;
|
||||||
self.prev_refresh_timestamp = 0;
|
self.prev_refresh_timestamp = 0;
|
||||||
self.timer = try std.time.Timer.start();
|
self.timer = std.time.Timer.start() catch null;
|
||||||
self.done = false;
|
self.done = false;
|
||||||
return &self.root;
|
return &self.root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the terminal if enough time has passed since last update. Thread-safe.
|
/// Updates the terminal if enough time has passed since last update. Thread-safe.
|
||||||
pub fn maybeRefresh(self: *Progress) void {
|
pub fn maybeRefresh(self: *Progress) void {
|
||||||
const now = self.timer.read();
|
if (self.timer) |*timer| {
|
||||||
if (now < self.initial_delay_ns) return;
|
const now = timer.read();
|
||||||
if (!self.update_mutex.tryLock()) return;
|
if (now < self.initial_delay_ns) return;
|
||||||
defer self.update_mutex.unlock();
|
if (!self.update_mutex.tryLock()) return;
|
||||||
// TODO I have observed this to happen sometimes. I think we need to follow Rust's
|
defer self.update_mutex.unlock();
|
||||||
// lead and guarantee monotonically increasing times in the std lib itself.
|
// TODO I have observed this to happen sometimes. I think we need to follow Rust's
|
||||||
if (now < self.prev_refresh_timestamp) return;
|
// lead and guarantee monotonically increasing times in the std lib itself.
|
||||||
if (now - self.prev_refresh_timestamp < self.refresh_rate_ns) return;
|
if (now < self.prev_refresh_timestamp) return;
|
||||||
return self.refreshWithHeldLock();
|
if (now - self.prev_refresh_timestamp < self.refresh_rate_ns) return;
|
||||||
|
return self.refreshWithHeldLock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the terminal and resets `self.next_refresh_timestamp`. Thread-safe.
|
/// Updates the terminal and resets `self.next_refresh_timestamp`. Thread-safe.
|
||||||
|
|
@ -285,7 +287,9 @@ fn refreshWithHeldLock(self: *Progress) void {
|
||||||
// Stop trying to write to this file once it errors.
|
// Stop trying to write to this file once it errors.
|
||||||
self.terminal = null;
|
self.terminal = null;
|
||||||
};
|
};
|
||||||
self.prev_refresh_timestamp = self.timer.read();
|
if (self.timer) |*timer| {
|
||||||
|
self.prev_refresh_timestamp = timer.read();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void {
|
pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void {
|
||||||
|
|
@ -327,7 +331,7 @@ test "basic functionality" {
|
||||||
return error.SkipZigTest;
|
return error.SkipZigTest;
|
||||||
}
|
}
|
||||||
var progress = Progress{};
|
var progress = Progress{};
|
||||||
const root_node = try progress.start("", 100);
|
const root_node = progress.start("", 100);
|
||||||
defer root_node.end();
|
defer root_node.end();
|
||||||
|
|
||||||
const sub_task_names = [_][]const u8{
|
const sub_task_names = [_][]const u8{
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,7 @@ pub fn main() void {
|
||||||
var progress = std.Progress{
|
var progress = std.Progress{
|
||||||
.dont_print_on_dumb = true,
|
.dont_print_on_dumb = true,
|
||||||
};
|
};
|
||||||
const root_node = progress.start("Test", test_fn_list.len) catch |err| switch (err) {
|
const root_node = progress.start("Test", test_fn_list.len);
|
||||||
// TODO still run tests in this case
|
|
||||||
error.TimerUnsupported => @panic("timer unsupported"),
|
|
||||||
};
|
|
||||||
const have_tty = progress.terminal != null and progress.supports_ansi_escape_codes;
|
const have_tty = progress.terminal != null and progress.supports_ansi_escape_codes;
|
||||||
|
|
||||||
var async_frame_buffer: []align(std.Target.stack_align) u8 = undefined;
|
var async_frame_buffer: []align(std.Target.stack_align) u8 = undefined;
|
||||||
|
|
|
||||||
|
|
@ -2586,7 +2586,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
|
||||||
// If the terminal is dumb, we dont want to show the user all the
|
// If the terminal is dumb, we dont want to show the user all the
|
||||||
// output.
|
// output.
|
||||||
var progress: std.Progress = .{ .dont_print_on_dumb = true };
|
var progress: std.Progress = .{ .dont_print_on_dumb = true };
|
||||||
var main_progress_node = try progress.start("", 0);
|
var main_progress_node = progress.start("", 0);
|
||||||
defer main_progress_node.end();
|
defer main_progress_node.end();
|
||||||
if (self.color == .off) progress.terminal = null;
|
if (self.color == .off) progress.terminal = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -305,10 +305,7 @@ export fn stage2_progress_start_root(
|
||||||
name_len: usize,
|
name_len: usize,
|
||||||
estimated_total_items: usize,
|
estimated_total_items: usize,
|
||||||
) *std.Progress.Node {
|
) *std.Progress.Node {
|
||||||
return progress.start(
|
return progress.start(name_ptr[0..name_len], estimated_total_items);
|
||||||
name_ptr[0..name_len],
|
|
||||||
estimated_total_items,
|
|
||||||
) catch @panic("timer unsupported");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ABI warning
|
// ABI warning
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue