builtin: implement unbuffer_stdout/0 (#20662)

This commit is contained in:
Delyan Angelov 2024-01-26 17:47:43 +02:00 committed by GitHub
parent 754c83a8ac
commit 2a68e2b7c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 0 deletions

View File

@ -223,6 +223,30 @@ pub fn flush_stderr() {
}
}
// unbuffer_stdout will turn off the default buffering done for stdout.
// It will affect all consequent print and println calls, effectively making them behave like
// eprint and eprintln do. It is useful for programs, that want to produce progress bars, without
// cluttering your code with a flush_stdout() call after every print() call. It is also useful for
// programs (sensors), that produce small chunks of output, that you want to be able to process
// immediately.
// Note 1: if used, *it should be called at the start of your program*, before using
// print or println().
// Note 2: most libc implementations, have logic that use line buffering for stdout, when the output
// stream is connected to an interactive device, like a terminal, and otherwise fully buffer it,
// which is good for the output performance for programs that can produce a lot of output (like
// filters, or cat etc), but bad for latency. Normally, it is usually what you want, so it is the
// default for V programs too.
// See https://www.gnu.org/software/libc/manual/html_node/Buffering-Concepts.html .
// See https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05 .
pub fn unbuffer_stdout() {
$if freestanding {
not_implemented := 'unbuffer_stdout is not implemented\n'
bare_eprint(not_implemented.str, u64(not_implemented.len))
} $else {
unsafe { C.setbuf(C.stdout, 0) }
}
}
// print prints a message to stdout. Note that unlike `eprint`, stdout is not automatically flushed.
@[manualfree]
pub fn print(s string) {

View File

@ -0,0 +1,17 @@
import time
fn test_unbuffer_stdout() {
// TODO: add a more extensive test, perhaps using expect,
// that does not require an active user to verify its validity.
// Currently this just tests that unbuffer_stdout/0 can be called,
// and its effects can be observed by commenting the call to it,
// on the next line, and then re-running the test:
unbuffer_stdout()
print('#---')
for i in 0 .. 21 {
print('\b\b\b> ${i:02}')
time.sleep(20 * time.millisecond)
}
println('\b\b\b done')
assert true
}