| ... | @@ -35,7 +35,7 @@ root: Node = undefined, | ... | @@ -35,7 +35,7 @@ root: Node = undefined, |
| 35 | | 35 | |
| 36 | /// Keeps track of how much time has passed since the beginning. | 36 | /// Keeps track of how much time has passed since the beginning. |
| 37 | /// Used to compare with `initial_delay_ms` and `refresh_rate_ms`. | 37 | /// Used to compare with `initial_delay_ms` and `refresh_rate_ms`. |
| 38 | timer: std.time.Timer = undefined, | 38 | timer: ?std.time.Timer = null, |
| 39 | | 39 | |
| 40 | /// When the previous refresh was written to the terminal. | 40 | /// When the previous refresh was written to the terminal. |
| 41 | /// Used to compare with `refresh_rate_ms`. | 41 | /// Used to compare with `refresh_rate_ms`. |
| ... | @@ -139,7 +139,7 @@ pub const Node = struct { | ... | @@ -139,7 +139,7 @@ pub const Node = struct { |
| 139 | /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this | 139 | /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this |
| 140 | /// API to return Progress rather than accept it as a parameter. | 140 | /// API to return Progress rather than accept it as a parameter. |
| 141 | /// `estimated_total_items` value of 0 means unknown. | 141 | /// `estimated_total_items` value of 0 means unknown. |
| 142 | pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !*Node { | 142 | pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) *Node { |
| 143 | const stderr = std.io.getStdErr(); | 143 | const stderr = std.io.getStdErr(); |
| 144 | self.terminal = null; | 144 | self.terminal = null; |
| 145 | if (stderr.supportsAnsiEscapeCodes()) { | 145 | if (stderr.supportsAnsiEscapeCodes()) { |
| ... | @@ -161,22 +161,24 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !* | ... | @@ -161,22 +161,24 @@ pub fn start(self: *Progress, name: []const u8, estimated_total_items: usize) !* |
| 161 | }; | 161 | }; |
| 162 | self.columns_written = 0; | 162 | self.columns_written = 0; |
| 163 | self.prev_refresh_timestamp = 0; | 163 | self.prev_refresh_timestamp = 0; |
| 164 | self.timer = try std.time.Timer.start(); | 164 | self.timer = std.time.Timer.start() catch null; |
| 165 | self.done = false; | 165 | self.done = false; |
| 166 | return &self.root; | 166 | return &self.root; |
| 167 | } | 167 | } |
| 168 | | 168 | |
| 169 | /// Updates the terminal if enough time has passed since last update. Thread-safe. | 169 | /// Updates the terminal if enough time has passed since last update. Thread-safe. |
| 170 | pub fn maybeRefresh(self: *Progress) void { | 170 | pub fn maybeRefresh(self: *Progress) void { |
| 171 | const now = self.timer.read(); | 171 | if (self.timer) |*timer| { |
| 172 | if (now < self.initial_delay_ns) return; | 172 | const now = timer.read(); |
| 173 | if (!self.update_mutex.tryLock()) return; | 173 | if (now < self.initial_delay_ns) return; |
| 174 | defer self.update_mutex.unlock(); | 174 | if (!self.update_mutex.tryLock()) return; |
| 175 | // TODO I have observed this to happen sometimes. I think we need to follow Rust's | 175 | defer self.update_mutex.unlock(); |
| 176 | // lead and guarantee monotonically increasing times in the std lib itself. | 176 | // TODO I have observed this to happen sometimes. I think we need to follow Rust's |
| 177 | if (now < self.prev_refresh_timestamp) return; | 177 | // lead and guarantee monotonically increasing times in the std lib itself. |
| 178 | if (now - self.prev_refresh_timestamp < self.refresh_rate_ns) return; | 178 | if (now < self.prev_refresh_timestamp) return; |
| 179 | return self.refreshWithHeldLock(); | 179 | if (now - self.prev_refresh_timestamp < self.refresh_rate_ns) return; |
| | 180 | return self.refreshWithHeldLock(); |
| | 181 | } |
| 180 | } | 182 | } |
| 181 | | 183 | |
| 182 | /// Updates the terminal and resets `self.next_refresh_timestamp`. Thread-safe. | 184 | /// Updates the terminal and resets `self.next_refresh_timestamp`. Thread-safe. |
| ... | @@ -285,7 +287,9 @@ fn refreshWithHeldLock(self: *Progress) void { | ... | @@ -285,7 +287,9 @@ fn refreshWithHeldLock(self: *Progress) void { |
| 285 | // Stop trying to write to this file once it errors. | 287 | // Stop trying to write to this file once it errors. |
| 286 | self.terminal = null; | 288 | self.terminal = null; |
| 287 | }; | 289 | }; |
| 288 | self.prev_refresh_timestamp = self.timer.read(); | 290 | if (self.timer) |*timer| { |
| | 291 | self.prev_refresh_timestamp = timer.read(); |
| | 292 | } |
| 289 | } | 293 | } |
| 290 | | 294 | |
| 291 | pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void { | 295 | pub fn log(self: *Progress, comptime format: []const u8, args: anytype) void { |
| ... | @@ -327,7 +331,7 @@ test "basic functionality" { | ... | @@ -327,7 +331,7 @@ test "basic functionality" { |
| 327 | return error.SkipZigTest; | 331 | return error.SkipZigTest; |
| 328 | } | 332 | } |
| 329 | var progress = Progress{}; | 333 | var progress = Progress{}; |
| 330 | const root_node = try progress.start("", 100); | 334 | const root_node = progress.start("", 100); |
| 331 | defer root_node.end(); | 335 | defer root_node.end(); |
| 332 | | 336 | |
| 333 | const sub_task_names = [_][]const u8{ | 337 | const sub_task_names = [_][]const u8{ |