authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 10:29:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 20:56:48-07:00
logdc3a192ae841706bb965218c68b0085bbec2b35e
tree24aa6cca1ca96e9ceeedc528942c55ab372fcc5a
parent6145819c0ba00924b37bab78200aeab6306c1672

std.Progress: count newlines more accurately

Split newline_count into written_newline_count and accumulated_newline_count. This handle the case when the tryLock() fails to obtain the lock, because in such case there would not be any newlines written to the terminal but the system would incorrectly think there were. Now, written_newline_count is only adjusted when the write() call succeeds. Furthermore, write() call failure is handled by exiting the update thread.

1 files changed, 21 insertions(+), 16 deletions(-)

lib/std/Progress.zig+21-16
...@@ -32,9 +32,11 @@ initial_delay_ns: u64,...@@ -32,9 +32,11 @@ initial_delay_ns: u64,
3232
33rows: u16,33rows: u16,
34cols: u16,34cols: u16,
35/// Needed because terminal escape codes require one to take scrolling into35/// Tracks the number of newlines that have been actually written to the terminal.
36/// account.36written_newline_count: u16,
37newline_count: u16,37/// Tracks the number of newlines that will be written to the terminal if the
38/// draw buffer is sent.
39accumulated_newline_count: u16,
3840
39/// Accessed only by the update thread.41/// Accessed only by the update thread.
40draw_buffer: []u8,42draw_buffer: []u8,
...@@ -284,7 +286,8 @@ var global_progress: Progress = .{...@@ -284,7 +286,8 @@ var global_progress: Progress = .{
284 .initial_delay_ns = undefined,286 .initial_delay_ns = undefined,
285 .rows = 0,287 .rows = 0,
286 .cols = 0,288 .cols = 0,
287 .newline_count = 0,289 .written_newline_count = 0,
290 .accumulated_newline_count = 0,
288 .draw_buffer = undefined,291 .draw_buffer = undefined,
289 .done = false,292 .done = false,
290293
...@@ -423,7 +426,7 @@ fn updateThreadRun() void {...@@ -423,7 +426,7 @@ fn updateThreadRun() void {
423 const buffer = computeRedraw(&serialized_buffer);426 const buffer = computeRedraw(&serialized_buffer);
424 if (stderr_mutex.tryLock()) {427 if (stderr_mutex.tryLock()) {
425 defer stderr_mutex.unlock();428 defer stderr_mutex.unlock();
426 write(buffer);429 write(buffer) catch return;
427 }430 }
428 }431 }
429432
...@@ -440,7 +443,7 @@ fn updateThreadRun() void {...@@ -440,7 +443,7 @@ fn updateThreadRun() void {
440 const buffer = computeRedraw(&serialized_buffer);443 const buffer = computeRedraw(&serialized_buffer);
441 if (stderr_mutex.tryLock()) {444 if (stderr_mutex.tryLock()) {
442 defer stderr_mutex.unlock();445 defer stderr_mutex.unlock();
443 write(buffer);446 write(buffer) catch return;
444 }447 }
445 }448 }
446}449}
...@@ -499,7 +502,7 @@ const tree_line = "\x1B\x28\x30\x78\x1B\x28\x42 "; // │...@@ -499,7 +502,7 @@ const tree_line = "\x1B\x28\x30\x78\x1B\x28\x42 "; // │
499const tree_langle = "\x1B\x28\x30\x6d\x71\x1B\x28\x42 "; // └─502const tree_langle = "\x1B\x28\x30\x6d\x71\x1B\x28\x42 "; // └─
500503
501fn clearTerminal() void {504fn clearTerminal() void {
502 if (global_progress.newline_count == 0) return;505 if (global_progress.written_newline_count == 0) return;
503506
504 var i: usize = 0;507 var i: usize = 0;
505 const buf = global_progress.draw_buffer;508 const buf = global_progress.draw_buffer;
...@@ -512,15 +515,17 @@ fn clearTerminal() void {...@@ -512,15 +515,17 @@ fn clearTerminal() void {
512 buf[i..][0..finish_sync.len].* = finish_sync.*;515 buf[i..][0..finish_sync.len].* = finish_sync.*;
513 i += finish_sync.len;516 i += finish_sync.len;
514517
515 write(buf[0..i]);518 global_progress.accumulated_newline_count = 0;
519 write(buf[0..i]) catch {
520 global_progress.terminal = null;
521 };
516}522}
517523
518fn computeClear(buf: []u8, start_i: usize) usize {524fn computeClear(buf: []u8, start_i: usize) usize {
519 var i = start_i;525 var i = start_i;
520526
521 const prev_nl_n = global_progress.newline_count;527 const prev_nl_n = global_progress.written_newline_count;
522 if (prev_nl_n > 0) {528 if (prev_nl_n > 0) {
523 global_progress.newline_count = 0;
524 buf[i] = '\r';529 buf[i] = '\r';
525 i += 1;530 i += 1;
526 for (0..prev_nl_n) |_| {531 for (0..prev_nl_n) |_| {
...@@ -854,6 +859,7 @@ fn computeRedraw(serialized_buffer: *Serialized.Buffer) []u8 {...@@ -854,6 +859,7 @@ fn computeRedraw(serialized_buffer: *Serialized.Buffer) []u8 {
854859
855 i = computeClear(buf, i);860 i = computeClear(buf, i);
856861
862 global_progress.accumulated_newline_count = 0;
857 const root_node_index: Node.Index = @enumFromInt(0);863 const root_node_index: Node.Index = @enumFromInt(0);
858 i = computeNode(buf, i, serialized, children, root_node_index);864 i = computeNode(buf, i, serialized, children, root_node_index);
859865
...@@ -937,7 +943,7 @@ fn computeNode(...@@ -937,7 +943,7 @@ fn computeNode(
937 i = @min(global_progress.cols + start_i, i);943 i = @min(global_progress.cols + start_i, i);
938 buf[i] = '\n';944 buf[i] = '\n';
939 i += 1;945 i += 1;
940 global_progress.newline_count += 1;946 global_progress.accumulated_newline_count += 1;
941 }947 }
942948
943 if (global_progress.withinRowLimit()) {949 if (global_progress.withinRowLimit()) {
...@@ -959,14 +965,13 @@ fn withinRowLimit(p: *Progress) bool {...@@ -959,14 +965,13 @@ fn withinRowLimit(p: *Progress) bool {
959 // The +2 here is so that the PS1 is not scrolled off the top of the terminal.965 // The +2 here is so that the PS1 is not scrolled off the top of the terminal.
960 // one because we keep the cursor on the next line966 // one because we keep the cursor on the next line
961 // one more to account for the PS1967 // one more to account for the PS1
962 return p.newline_count + 2 < p.rows;968 return p.accumulated_newline_count + 2 < p.rows;
963}969}
964970
965fn write(buf: []const u8) void {971fn write(buf: []const u8) anyerror!void {
966 const tty = global_progress.terminal orelse return;972 const tty = global_progress.terminal orelse return;
967 tty.writeAll(buf) catch {973 try tty.writeAll(buf);
968 global_progress.terminal = null;974 global_progress.written_newline_count = global_progress.accumulated_newline_count;
969 };
970}975}
971976
972fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {977fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {