progress-bar: Add unbuffered variant
The progress_bar functions do their own buffering: they reconfigure stderr, then print, then flush and disable buffering on their own. In situations where multiple progress bars are being drawn at a time (for example, in updatectl), it's even more efficient to hoist the buffering and flushing to the call site, and avoid drawing each progress bar individually. To that end, new _unbuffered variants of the progress_bar functions. And we use them in updatectl.
This commit is contained in:
+25
-16
@@ -460,14 +460,7 @@ bool shall_tint_background(void) {
|
||||
return cache != 0;
|
||||
}
|
||||
|
||||
void draw_progress_bar(const char *prefix, double percentage) {
|
||||
|
||||
/* We are going output a bunch of small strings that shall appear as a single line to STDERR which is
|
||||
* unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty
|
||||
* as a single buffer, to make things more efficient. */
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
void draw_progress_bar_unbuffered(const char *prefix, double percentage) {
|
||||
fputc('\r', stderr);
|
||||
if (prefix) {
|
||||
fputs(prefix, stderr);
|
||||
@@ -520,17 +513,10 @@ void draw_progress_bar(const char *prefix, double percentage) {
|
||||
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
||||
|
||||
fputc('\r', stderr);
|
||||
fflush(stderr);
|
||||
|
||||
/* Disable buffering again */
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
void clear_progress_bar(const char *prefix) {
|
||||
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
void clear_progress_bar_unbuffered(const char *prefix) {
|
||||
fputc('\r', stderr);
|
||||
|
||||
if (terminal_is_dumb())
|
||||
@@ -542,8 +528,31 @@ void clear_progress_bar(const char *prefix) {
|
||||
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
||||
|
||||
fputc('\r', stderr);
|
||||
}
|
||||
|
||||
void draw_progress_bar(const char *prefix, double percentage) {
|
||||
|
||||
/* We are going output a bunch of small strings that shall appear as a single line to STDERR which is
|
||||
* unbuffered by default. Let's temporarily turn on full buffering, so that this is passed to the tty
|
||||
* as a single buffer, to make things more efficient. */
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
draw_progress_bar_unbuffered(prefix, percentage);
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
/* Disable buffering again */
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
void clear_progress_bar(const char *prefix) {
|
||||
char buffer[LONG_LINE_MAX];
|
||||
setvbuf(stderr, buffer, _IOFBF, sizeof(buffer));
|
||||
|
||||
clear_progress_bar_unbuffered(prefix);
|
||||
|
||||
fflush(stderr);
|
||||
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
@@ -55,3 +55,5 @@ bool shall_tint_background(void);
|
||||
|
||||
void draw_progress_bar(const char *prefix, double percentage);
|
||||
void clear_progress_bar(const char *prefix);
|
||||
void draw_progress_bar_unbuffered(const char *prefix, double percentage);
|
||||
void clear_progress_bar_unbuffered(const char *prefix);
|
||||
|
||||
Reference in New Issue
Block a user