From 12324130c9301961e1404067b04fe48ce06d95bf Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 29 Mar 2019 01:48:04 +0100 Subject: [PATCH 01/29] update --- progress_bar.cpp | 139 +++++++++++++++++++++++++---------------------- progress_bar.hpp | 40 ++++++-------- 2 files changed, 93 insertions(+), 86 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 745844a..d17899d 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -1,104 +1,115 @@ #include "progress_bar.hpp" -ProgressBar::ProgressBar() {} +#include -ProgressBar::ProgressBar(unsigned long n_, const char* description_, std::ostream& out_){ - - n = n_; - frequency_update = n_; - description = description_; +const size_t kMessageSize = 25; +const double kTotalPercentage = 100.0; +const size_t kCharacterWidthPercentage = 4; + + +ProgressBar::ProgressBar(uint64_t total, + const std::string &description, + std::ostream &out_) + : total_(total), description_(description) { + frequency_update = std::min(static_cast(1000), total_); out = &out_; - - unit_bar = "="; - unit_space = " "; - desc_width = std::strlen(description); // character width of description field + *out << "\n"; + assert(description_.size() <= kMessageSize); + description_.resize(kMessageSize, ' '); } -void ProgressBar::SetFrequencyUpdate(unsigned long frequency_update_){ - - if(frequency_update_ > n){ - frequency_update = n; // prevents crash if freq_updates_ > n_ - } - else{ - frequency_update = frequency_update_; - } +ProgressBar::~ProgressBar() { + *out << "\n"; } -void ProgressBar::SetStyle(const char* unit_bar_, const char* unit_space_){ - - unit_bar = unit_bar_; - unit_space = unit_space_; +void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { + if(frequency_update_ > total_){ + frequency_update = total_; // prevents crash if freq_updates_ > total_ + } else{ + frequency_update = frequency_update_; + } } -int ProgressBar::GetConsoleWidth(){ +void ProgressBar::SetStyle(char unit_bar, char unit_space){ + unit_bar_ = unit_bar; + unit_space_ = unit_space; +} +int ProgressBar::GetConsoleWidth() { int width; - #ifdef _WINDOWS - CONSOLE_SCREEN_BUFFER_INFO csbi; - GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); - width = csbi.srWindow.Right - csbi.srWindow.Left; - #else - struct winsize win; - ioctl(0, TIOCGWINSZ, &win); + #ifdef _WINDOWS + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + width = csbi.srWindow.Right - csbi.srWindow.Left; + #else + struct winsize win; + ioctl(0, TIOCGWINSZ, &win); width = win.ws_col; - #endif + #endif return width; } -int ProgressBar::GetBarLength(){ - - // get console width and according adjust the length of the progress bar - - int bar_length = static_cast((GetConsoleWidth() - desc_width - CHARACTER_WIDTH_PERCENTAGE) / 2.); - - return bar_length; +int ProgressBar::GetBarLength() { + // get console width and according adjust the length of the progress bar + return (GetConsoleWidth() - description_.size() + - kCharacterWidthPercentage) / 2.; } -void ProgressBar::ClearBarField(){ - - for(int i=0;i n) throw idx_; +void ProgressBar::Progressed(uint64_t idx_) { + try { + if (idx_ > total_) + throw idx_; + + progress_ = idx_; // determines whether to update the progress bar from frequency_update - if ((idx_ != n) && (idx_ % (n/frequency_update) != 0)) return; + if ((idx_ != total_) && (idx_ % (total_ / frequency_update) != 0)) + return; // calculate the size of the progress bar - int bar_size = GetBarLength(); - + int bar_size = GetBarLength(); + // calculate percentage of progress - double progress_percent = idx_* TOTAL_PERCENTAGE/n; + double progress_percent = idx_* kTotalPercentage / total_; - // calculate the percentage value of a unit bar - double percent_per_unit_bar = TOTAL_PERCENTAGE/bar_size; + // calculate the percentage value of a unit bar + double percent_per_unit_bar = kTotalPercentage / bar_size; // display progress bar - *out << " " << description << " ["; - - for(int bar_length=0;bar_length<=bar_size-1;++bar_length){ - if(bar_length*percent_per_unit_barProgressed(progress_ + 1); + return *this; } diff --git a/progress_bar.hpp b/progress_bar.hpp index 0a4a0ed..befc03b 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -8,39 +8,35 @@ #endif #include -#include -#include +#include -#define TOTAL_PERCENTAGE 100.0 -#define CHARACTER_WIDTH_PERCENTAGE 4 class ProgressBar{ + public: + ProgressBar(uint64_t total, + const std::string &description = "", + std::ostream &out = std::cerr); + ~ProgressBar(); -public: + void SetFrequencyUpdate(uint64_t frequency_update_); + void SetStyle(char unit_bar, char unit_space); - ProgressBar(); - ProgressBar(unsigned long n_, const char *description_="", std::ostream& out_=std::cerr); + void Progressed(uint64_t idx_); + ProgressBar& operator++(); - void SetFrequencyUpdate(unsigned long frequency_update_); - void SetStyle(const char* unit_bar_, const char* unit_space_); + private: + uint64_t total_; + uint64_t progress_ = 0; + uint64_t frequency_update; + std::ostream *out; - void Progressed(unsigned long idx_); + std::string description_; + char unit_bar_ = '='; + char unit_space_ = ' '; -private: - - unsigned long n; - unsigned int desc_width; - unsigned long frequency_update; - std::ostream* out; - - const char *description; - const char *unit_bar; - const char *unit_space; - void ClearBarField(); int GetConsoleWidth(); int GetBarLength(); - }; #endif From f1b6d82a431e7afa82d4e3a3327f00b7a177abaa Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 29 Mar 2019 02:03:37 +0100 Subject: [PATCH 02/29] show actual progress --- progress_bar.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index d17899d..50ff519 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -1,8 +1,9 @@ #include "progress_bar.hpp" #include +#include -const size_t kMessageSize = 25; +const size_t kMessageSize = 20; const double kTotalPercentage = 100.0; const size_t kCharacterWidthPercentage = 4; @@ -55,7 +56,8 @@ int ProgressBar::GetConsoleWidth() { int ProgressBar::GetBarLength() { // get console width and according adjust the length of the progress bar return (GetConsoleWidth() - description_.size() - - kCharacterWidthPercentage) / 2.; + - kCharacterWidthPercentage + - std::log10(total_ * 2) * 2) / 2.; } void ProgressBar::ClearBarField() { @@ -80,7 +82,7 @@ void ProgressBar::Progressed(uint64_t idx_) { int bar_size = GetBarLength(); // calculate percentage of progress - double progress_percent = idx_* kTotalPercentage / total_; + double progress_percent = idx_ * kTotalPercentage / total_; // calculate the percentage value of a unit bar double percent_per_unit_bar = kTotalPercentage / bar_size; @@ -100,7 +102,8 @@ void ProgressBar::Progressed(uint64_t idx_) { *out << "]" << std::setw(kCharacterWidthPercentage + 1) << std::setprecision(1) << std::fixed - << progress_percent << "%\r" << std::flush; + << progress_percent << "%, " + << progress_ << "/" << total_ << "\r" << std::flush; } catch (uint64_t e) { ClearBarField(); std::cerr << "PROGRESS_BAR_EXCEPTION: _idx (" From f6bce3cfc7532212d6c2887c1a1a082d64d98675 Mon Sep 17 00:00:00 2001 From: Harun Mustafa Date: Fri, 29 Mar 2019 11:12:55 +0100 Subject: [PATCH 03/29] Need to include cassert to compile on some systems --- progress_bar.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/progress_bar.cpp b/progress_bar.cpp index 50ff519..1d132d5 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -2,6 +2,7 @@ #include #include +#include const size_t kMessageSize = 20; const double kTotalPercentage = 100.0; From e015bcd7d1455ae512465bae93ea8e5ea4535a50 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 26 Apr 2019 18:24:57 +0200 Subject: [PATCH 04/29] added operator --- progress_bar.cpp | 5 +++++ progress_bar.hpp | 1 + 2 files changed, 6 insertions(+) diff --git a/progress_bar.cpp b/progress_bar.cpp index 1d132d5..845fa22 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -117,3 +117,8 @@ ProgressBar& ProgressBar::operator++() { this->Progressed(progress_ + 1); return *this; } + +ProgressBar& ProgressBar::operator+=(uint64_t delta) { + this->Progressed(progress_ + delta); + return *this; +} diff --git a/progress_bar.hpp b/progress_bar.hpp index befc03b..5b08aff 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -23,6 +23,7 @@ class ProgressBar{ void Progressed(uint64_t idx_); ProgressBar& operator++(); + ProgressBar& operator+=(uint64_t delta); private: uint64_t total_; From eedf88687f8ebc674c50aa610bf59eec1cb8e1f0 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 26 Apr 2019 18:39:26 +0200 Subject: [PATCH 05/29] show progress bar right after initialization --- progress_bar.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/progress_bar.cpp b/progress_bar.cpp index 845fa22..d09e699 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -19,6 +19,8 @@ ProgressBar::ProgressBar(uint64_t total, assert(description_.size() <= kMessageSize); description_.resize(kMessageSize, ' '); + + Progressed(0); } ProgressBar::~ProgressBar() { From 0b44569b496a447e7ae84ca50bb73c2163d024c5 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 3 May 2019 21:09:05 +0200 Subject: [PATCH 06/29] fixed progress bar for zero total progress --- progress_bar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index d09e699..2f0dc91 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -60,7 +60,7 @@ int ProgressBar::GetBarLength() { // get console width and according adjust the length of the progress bar return (GetConsoleWidth() - description_.size() - kCharacterWidthPercentage - - std::log10(total_ * 2) * 2) / 2.; + - std::log10(std::max(uint64_t(1), total_) * 2) * 2) / 2.; } void ProgressBar::ClearBarField() { @@ -85,7 +85,8 @@ void ProgressBar::Progressed(uint64_t idx_) { int bar_size = GetBarLength(); // calculate percentage of progress - double progress_percent = idx_ * kTotalPercentage / total_; + double progress_percent = total_ ? idx_ * kTotalPercentage / total_ + : kTotalPercentage; // calculate the percentage value of a unit bar double percent_per_unit_bar = kTotalPercentage / bar_size; From 77eca4607f67e14e7f6d3d10080f62d7d17745d2 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Tue, 14 May 2019 14:36:03 +0000 Subject: [PATCH 07/29] prevent from copying --- progress_bar.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/progress_bar.hpp b/progress_bar.hpp index 5b08aff..b137f25 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -26,6 +26,9 @@ class ProgressBar{ ProgressBar& operator+=(uint64_t delta); private: + ProgressBar(const ProgressBar &) = delete; + ProgressBar& operator=(const ProgressBar &) = delete; + uint64_t total_; uint64_t progress_ = 0; uint64_t frequency_update; From f5c2a4e62e6784c126249bac6aec8ad8775da1d4 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Tue, 14 May 2019 14:37:09 +0000 Subject: [PATCH 08/29] silent mode --- progress_bar.cpp | 30 +++++++++++++++++++++--------- progress_bar.hpp | 11 +++++++---- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 2f0dc91..6b7e973 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -11,8 +11,12 @@ const size_t kCharacterWidthPercentage = 4; ProgressBar::ProgressBar(uint64_t total, const std::string &description, - std::ostream &out_) - : total_(total), description_(description) { + std::ostream &out_, + bool silent) + : silent_(silent), total_(total), description_(description) { + if (silent_) + return; + frequency_update = std::min(static_cast(1000), total_); out = &out_; *out << "\n"; @@ -24,7 +28,8 @@ ProgressBar::ProgressBar(uint64_t total, } ProgressBar::~ProgressBar() { - *out << "\n"; + if (!silent_) + *out << "\n"; } void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { @@ -35,12 +40,12 @@ void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { } } -void ProgressBar::SetStyle(char unit_bar, char unit_space){ +void ProgressBar::SetStyle(char unit_bar, char unit_space) { unit_bar_ = unit_bar; unit_space_ = unit_space; } -int ProgressBar::GetConsoleWidth() { +int ProgressBar::GetConsoleWidth() const { int width; #ifdef _WINDOWS @@ -56,7 +61,7 @@ int ProgressBar::GetConsoleWidth() { return width; } -int ProgressBar::GetBarLength() { +int ProgressBar::GetBarLength() const { // get console width and according adjust the length of the progress bar return (GetConsoleWidth() - description_.size() - kCharacterWidthPercentage @@ -64,6 +69,9 @@ int ProgressBar::GetBarLength() { } void ProgressBar::ClearBarField() { + if (silent_) + return; + for(int i = 0; i < GetConsoleWidth(); ++i) { *out << " "; } @@ -71,6 +79,9 @@ void ProgressBar::ClearBarField() { } void ProgressBar::Progressed(uint64_t idx_) { + if (silent_) + return; + try { if (idx_ > total_) throw idx_; @@ -117,11 +128,12 @@ void ProgressBar::Progressed(uint64_t idx_) { } ProgressBar& ProgressBar::operator++() { - this->Progressed(progress_ + 1); - return *this; + return (*this) += 1; } ProgressBar& ProgressBar::operator+=(uint64_t delta) { - this->Progressed(progress_ + delta); + if (!silent_) + this->Progressed(progress_ + delta); + return *this; } diff --git a/progress_bar.hpp b/progress_bar.hpp index b137f25..2b0f5e1 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -11,11 +11,13 @@ #include -class ProgressBar{ +class ProgressBar { public: ProgressBar(uint64_t total, const std::string &description = "", - std::ostream &out = std::cerr); + std::ostream &out = std::cerr, + bool silent = false); + ~ProgressBar(); void SetFrequencyUpdate(uint64_t frequency_update_); @@ -29,6 +31,7 @@ class ProgressBar{ ProgressBar(const ProgressBar &) = delete; ProgressBar& operator=(const ProgressBar &) = delete; + bool silent_; uint64_t total_; uint64_t progress_ = 0; uint64_t frequency_update; @@ -39,8 +42,8 @@ class ProgressBar{ char unit_space_ = ' '; void ClearBarField(); - int GetConsoleWidth(); - int GetBarLength(); + int GetConsoleWidth() const; + int GetBarLength() const; }; #endif From 9ca8c465db08426a2c6569a3fc7340ded679f780 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Tue, 14 May 2019 19:49:51 +0000 Subject: [PATCH 09/29] thread safe progress bar --- progress_bar.cpp | 36 +++++++++++++++++++++--------------- progress_bar.hpp | 17 ++++++++++------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 6b7e973..7b7662a 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -24,7 +24,7 @@ ProgressBar::ProgressBar(uint64_t total, assert(description_.size() <= kMessageSize); description_.resize(kMessageSize, ' '); - Progressed(0); + ShowProgress(); } ProgressBar::~ProgressBar() { @@ -33,6 +33,8 @@ ProgressBar::~ProgressBar() { } void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { + std::lock_guard lock(mu_); + if(frequency_update_ > total_){ frequency_update = total_; // prevents crash if freq_updates_ > total_ } else{ @@ -41,6 +43,8 @@ void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { } void ProgressBar::SetStyle(char unit_bar, char unit_space) { + std::lock_guard lock(mu_); + unit_bar_ = unit_bar; unit_space_ = unit_space; } @@ -68,7 +72,7 @@ int ProgressBar::GetBarLength() const { - std::log10(std::max(uint64_t(1), total_) * 2) * 2) / 2.; } -void ProgressBar::ClearBarField() { +void ProgressBar::ClearBarField() const { if (silent_) return; @@ -78,25 +82,18 @@ void ProgressBar::ClearBarField() { *out << "\r" << std::flush; } -void ProgressBar::Progressed(uint64_t idx_) { +void ProgressBar::ShowProgress() const { if (silent_) return; - try { - if (idx_ > total_) - throw idx_; - - progress_ = idx_; - - // determines whether to update the progress bar from frequency_update - if ((idx_ != total_) && (idx_ % (total_ / frequency_update) != 0)) - return; + std::lock_guard lock(mu_); + try { // calculate the size of the progress bar int bar_size = GetBarLength(); // calculate percentage of progress - double progress_percent = total_ ? idx_ * kTotalPercentage / total_ + double progress_percent = total_ ? progress_ * kTotalPercentage / total_ : kTotalPercentage; // calculate the percentage value of a unit bar @@ -132,8 +129,17 @@ ProgressBar& ProgressBar::operator++() { } ProgressBar& ProgressBar::operator+=(uint64_t delta) { - if (!silent_) - this->Progressed(progress_ + delta); + if (silent_ || !delta) + return *this; + + uint64_t after_update = (progress_ += delta); + + if (after_update > total_) + throw after_update; + + // determines whether to update the progress bar from frequency_update + if (after_update == total_ || after_update % (total_ / frequency_update) == 0) + ShowProgress(); return *this; } diff --git a/progress_bar.hpp b/progress_bar.hpp index 2b0f5e1..763ecd6 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -9,6 +9,8 @@ #include #include +#include +#include class ProgressBar { @@ -23,7 +25,6 @@ class ProgressBar { void SetFrequencyUpdate(uint64_t frequency_update_); void SetStyle(char unit_bar, char unit_space); - void Progressed(uint64_t idx_); ProgressBar& operator++(); ProgressBar& operator+=(uint64_t delta); @@ -31,19 +32,21 @@ class ProgressBar { ProgressBar(const ProgressBar &) = delete; ProgressBar& operator=(const ProgressBar &) = delete; + void ShowProgress() const; + void ClearBarField() const; + int GetConsoleWidth() const; + int GetBarLength() const; + bool silent_; uint64_t total_; - uint64_t progress_ = 0; + std::atomic progress_ = 0; uint64_t frequency_update; std::ostream *out; + mutable std::mutex mu_; std::string description_; char unit_bar_ = '='; char unit_space_ = ' '; - - void ClearBarField(); - int GetConsoleWidth() const; - int GetBarLength() const; }; -#endif +#endif // _PROGRESS_BAR_ From 9315d0d4a680b512b134627d63102e3e5f6527bd Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Tue, 14 May 2019 21:27:41 +0000 Subject: [PATCH 10/29] fixed blinking of the bar --- progress_bar.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 7b7662a..b2b5760 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -3,10 +3,11 @@ #include #include #include +#include const size_t kMessageSize = 20; const double kTotalPercentage = 100.0; -const size_t kCharacterWidthPercentage = 4; +const size_t kCharacterWidthPercentage = 7; ProgressBar::ProgressBar(uint64_t total, @@ -73,13 +74,8 @@ int ProgressBar::GetBarLength() const { } void ProgressBar::ClearBarField() const { - if (silent_) - return; - - for(int i = 0; i < GetConsoleWidth(); ++i) { - *out << " "; - } - *out << "\r" << std::flush; + if (!silent_) + *out << (std::string(GetConsoleWidth(), ' ') + '\r') << std::flush; } void ProgressBar::ShowProgress() const { @@ -100,22 +96,24 @@ void ProgressBar::ShowProgress() const { double percent_per_unit_bar = kTotalPercentage / bar_size; // display progress bar - // *out << " " << (percent_per_unit_bar < 1 - // ? description - // : std::string(' ', desc_width)) << " ["; - *out << " " << description_ << " ["; + std::string str = " " + description_ + " ["; for(int bar_length = 0; bar_length <= bar_size - 1; ++bar_length) { - *out << (bar_length * percent_per_unit_bar < progress_percent + str += (bar_length * percent_per_unit_bar < progress_percent ? unit_bar_ : unit_space_); } - *out << "]" << std::setw(kCharacterWidthPercentage + 1) - << std::setprecision(1) - << std::fixed - << progress_percent << "%, " - << progress_ << "/" << total_ << "\r" << std::flush; + str += "] " + std::string(kCharacterWidthPercentage, ' '); + + snprintf(&str[str.size() - kCharacterWidthPercentage], + kCharacterWidthPercentage, + "%5.1f%%", progress_percent); + + str += ", " + std::to_string(progress_) + "/" + std::to_string(total_) + "\r"; + + *out << str << std::flush; + } catch (uint64_t e) { ClearBarField(); std::cerr << "PROGRESS_BAR_EXCEPTION: _idx (" @@ -134,8 +132,7 @@ ProgressBar& ProgressBar::operator+=(uint64_t delta) { uint64_t after_update = (progress_ += delta); - if (after_update > total_) - throw after_update; + assert(after_update <= total_); // determines whether to update the progress bar from frequency_update if (after_update == total_ || after_update % (total_ / frequency_update) == 0) From e07b6f0a3a9b3714ea8126fd201de380d5edc798 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Wed, 15 May 2019 21:02:18 +0200 Subject: [PATCH 11/29] updated readme --- README.md | 162 ++++++++++++++++++++++++++---------------------------- 1 file changed, 78 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index ede3482..cdc24f3 100644 --- a/README.md +++ b/README.md @@ -28,50 +28,49 @@ To create a progress bar, the total number of jobs need to be known. int n = 10; ProgressBar progress_bar(n); ``` - - Optionally, small descriptions can also be added to the progress bar + +Optionally, small descriptions can also be added to the progress bar. ```C++ int n = 10; -ProgressBar progress_bar(n,"Example 1"); +ProgressBar progress_bar(n, "Example 1"); ``` - - - + + Updating a progress bar ------------------------- - -Updates to the progress bar are made using the `Progressed(int)` method by passing the index of the job - + +Updates to the progress bar are made using the increment operators. + **Example 1:** ```C++ int n = 10; -ProgressBar progress_bar(n,"Example 1"); - +ProgressBar progress_bar(n, "Example 1"); + int job_index = 0; - + do_some_work(); - + job_index++; -progress_bar.Progressed(job_index); - +progress_bar += 1; + do_some_more_work(); - + job_index++; -progress_bar.Progressed(job_index); +progress_bar += 1; ``` - + **Example 2:** ```C++ int n = 100; -ProgressBar *bar = new ProgressBar(n, "Example 1"); - -for(int i=0;i<=n;++i){ - bar1->Progressed(i); - std::this_thread::sleep_for (std::chrono::milliseconds(10)); +ProgressBar bar1(n, "Example 1"); + +for (int i = 0; i <= n; ++i) { + ++bar1; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } ``` @@ -83,11 +82,11 @@ If progressing through a large job list, iterating through every update will slo **Example 3:** ```C++ int n = 100000; -ProgressBar *bar2 = new ProgressBar(n, "Example 3"); -bar2->SetFrequencyUpdate(10); - -for(int i=0;i<=n;++i){ - bar2->Progressed(i); +ProgressBar bar2(n, "Example 3"); +bar2.SetFrequencyUpdate(10); + +for (int i = 0; i <= n; ++i){ + ++bar2; } ``` @@ -99,12 +98,12 @@ The progress bar can be customised using the `SetStyle(const char*, const char*) **Example 4** ```C++ n = 1000; -ProgressBar *bar3 = new ProgressBar(n, "Example 4"); -bar3->SetFrequencyUpdate(10); -bar3->SetStyle("\u2588", "-"); - -for(int i=0;i<=n;++i){ - bar3->Progressed(i); +ProgressBar bar3(n, "Example 4"); +bar3.SetFrequencyUpdate(10); +bar3.SetStyle("\u2588", "-"); + +for (int i = 0; i <= n; ++i) { + ++bar3; } ``` @@ -112,66 +111,61 @@ for(int i=0;i<=n;++i){ Main Example ========= - ```C++ -#include "progress_bar.hpp" #include #include #include -int main(){ - - int n; - - /// Example 1 /// - - n = 100; - ProgressBar *bar1 = new ProgressBar(n, "Example 1"); - - for(int i=0;i<=n;++i){ - bar1->Progressed(i); - std::this_thread::sleep_for (std::chrono::milliseconds(10)); - } +#include "progress_bar.hpp" - /// Example 2 /// - - n = 1000; - ProgressBar *bar2 = new ProgressBar(n, "Example 2"); - bar2->SetFrequencyUpdate(10); - bar2->SetStyle("|","-"); - //bar2->SetStyle("\u2588", "-"); for linux - - std::cout << std::endl; - for(int i=0;i<=n;++i){ - bar2->Progressed(i); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - n = 5; - ProgressBar bar3(n); - bar3.Progressed(0); - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(1); - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(2); - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(3); - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(4); - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(5); - // following tests exception error - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(6); - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(7); - return 0; -} -``` +int main() { + int n; + /// Example 1 /// + n = 100; + ProgressBar bar1(n, "Example 1"); + for (int i = 0; i <= n; ++i) { + ++bar1; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + /// Example 2 /// + n = 1000; + ProgressBar bar2(n, "Example 2"); + bar2.SetFrequencyUpdate(10); + bar2.SetStyle("|", "-"); + //bar2.SetStyle("\u2588", "-"); for linux + + std::cout << std::endl; + for (int i = 0; i <= n; ++i) { + ++bar2; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + n = 5; + ProgressBar bar3(n); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + // following tests exception error + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + + return 0; +} +``` From d2becaa585a19b7e38c9967566b03a0b3cf1a267 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Wed, 15 May 2019 21:04:48 +0200 Subject: [PATCH 12/29] correct update of the progress bar after resizing the window --- progress_bar.cpp | 53 ++++++++++++++++++++++++++---------------------- progress_bar.hpp | 1 + 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index b2b5760..37eb89b 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -68,9 +68,13 @@ int ProgressBar::GetConsoleWidth() const { int ProgressBar::GetBarLength() const { // get console width and according adjust the length of the progress bar - return (GetConsoleWidth() - description_.size() - - kCharacterWidthPercentage - - std::log10(std::max(uint64_t(1), total_) * 2) * 2) / 2.; + int max_size = GetConsoleWidth() + - 9 + - description_.size() + - kCharacterWidthPercentage + - std::ceil(std::log10(std::max(uint64_t(1), total_))) * 2; + + return max_size / 2; } void ProgressBar::ClearBarField() const { @@ -85,34 +89,35 @@ void ProgressBar::ShowProgress() const { std::lock_guard lock(mu_); try { + // clear previous progressbar + *out << std::string(buffer_.size(), ' ') + '\r' << std::flush; + buffer_.clear(); + // calculate the size of the progress bar int bar_size = GetBarLength(); + if (bar_size < 1) + return; // calculate percentage of progress - double progress_percent = total_ ? progress_ * kTotalPercentage / total_ - : kTotalPercentage; - - // calculate the percentage value of a unit bar - double percent_per_unit_bar = kTotalPercentage / bar_size; - - // display progress bar - std::string str = " " + description_ + " ["; - - for(int bar_length = 0; bar_length <= bar_size - 1; ++bar_length) { - str += (bar_length * percent_per_unit_bar < progress_percent - ? unit_bar_ - : unit_space_); - } - - str += "] " + std::string(kCharacterWidthPercentage, ' '); - - snprintf(&str[str.size() - kCharacterWidthPercentage], + double progress_ratio = total_ ? static_cast(progress_) / total_ + : 1.0; + assert(progress_ratio >= 0.0); + assert(progress_ratio <= 1.0); + + // write the state of the progress bar + buffer_ = " " + description_ + + " [" + + std::string(size_t(bar_size * progress_ratio), unit_bar_) + + std::string(bar_size - size_t(bar_size * progress_ratio), unit_space_) + + "] " + std::string(kCharacterWidthPercentage, ' '); + + snprintf(&buffer_[buffer_.size() - kCharacterWidthPercentage], kCharacterWidthPercentage, - "%5.1f%%", progress_percent); + "%5.1f%%", progress_ratio * kTotalPercentage); - str += ", " + std::to_string(progress_) + "/" + std::to_string(total_) + "\r"; + buffer_ += ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\r'; - *out << str << std::flush; + *out << buffer_ << std::flush; } catch (uint64_t e) { ClearBarField(); diff --git a/progress_bar.hpp b/progress_bar.hpp index 763ecd6..585d70b 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -43,6 +43,7 @@ class ProgressBar { uint64_t frequency_update; std::ostream *out; mutable std::mutex mu_; + mutable std::string buffer_; std::string description_; char unit_bar_ = '='; From 54f115260eca287d9757c1628dbea1dd64f073f3 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Sat, 18 May 2019 21:15:25 +0000 Subject: [PATCH 13/29] removed redundant newline --- progress_bar.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 37eb89b..91583b4 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -20,7 +20,6 @@ ProgressBar::ProgressBar(uint64_t total, frequency_update = std::min(static_cast(1000), total_); out = &out_; - *out << "\n"; assert(description_.size() <= kMessageSize); description_.resize(kMessageSize, ' '); From b69e6248fda7649a7f441593847eadabff0557e8 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 7 Jun 2019 00:05:13 +0200 Subject: [PATCH 14/29] properly update progress bar for operator+=(uint64_t) --- progress_bar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 91583b4..b0e78dd 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -139,7 +139,9 @@ ProgressBar& ProgressBar::operator+=(uint64_t delta) { assert(after_update <= total_); // determines whether to update the progress bar from frequency_update - if (after_update == total_ || after_update % (total_ / frequency_update) == 0) + if (after_update == total_ + || (after_update - delta) / frequency_update + < after_update / frequency_update) ShowProgress(); return *this; From 26793188cc5ac235e97b67283ac96ba9bedcb74d Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Mon, 26 Aug 2019 16:40:00 +0000 Subject: [PATCH 15/29] set max value for bar width --- progress_bar.cpp | 16 ++++++---------- progress_bar.hpp | 1 - 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index b0e78dd..5c572ce 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -8,6 +8,8 @@ const size_t kMessageSize = 20; const double kTotalPercentage = 100.0; const size_t kCharacterWidthPercentage = 7; +const int kDefaultConsoleWidth = 100; +const int kMaxBarWidth = 100; ProgressBar::ProgressBar(uint64_t total, @@ -50,7 +52,7 @@ void ProgressBar::SetStyle(char unit_bar, char unit_space) { } int ProgressBar::GetConsoleWidth() const { - int width; + int width = kDefaultConsoleWidth; #ifdef _WINDOWS CONSOLE_SCREEN_BUFFER_INFO csbi; @@ -58,8 +60,8 @@ int ProgressBar::GetConsoleWidth() const { width = csbi.srWindow.Right - csbi.srWindow.Left; #else struct winsize win; - ioctl(0, TIOCGWINSZ, &win); - width = win.ws_col; + if (ioctl(0, TIOCGWINSZ, &win) != -1) + width = win.ws_col; #endif return width; @@ -73,12 +75,7 @@ int ProgressBar::GetBarLength() const { - kCharacterWidthPercentage - std::ceil(std::log10(std::max(uint64_t(1), total_))) * 2; - return max_size / 2; -} - -void ProgressBar::ClearBarField() const { - if (!silent_) - *out << (std::string(GetConsoleWidth(), ' ') + '\r') << std::flush; + return std::min(max_size / 2, kMaxBarWidth); } void ProgressBar::ShowProgress() const { @@ -119,7 +116,6 @@ void ProgressBar::ShowProgress() const { *out << buffer_ << std::flush; } catch (uint64_t e) { - ClearBarField(); std::cerr << "PROGRESS_BAR_EXCEPTION: _idx (" << e << ") went out of bounds, greater than total_ (" << total_ << ")." << std::endl << std::flush; diff --git a/progress_bar.hpp b/progress_bar.hpp index 585d70b..332385a 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -33,7 +33,6 @@ class ProgressBar { ProgressBar& operator=(const ProgressBar &) = delete; void ShowProgress() const; - void ClearBarField() const; int GetConsoleWidth() const; int GetBarLength() const; From 5ab3bbd110db4b4ffe044a0b2ffca467800c65ff Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Mon, 26 Aug 2019 18:13:48 +0000 Subject: [PATCH 16/29] special logging mode for output other than to console --- progress_bar.cpp | 74 +++++++++++++++++++++++++++++++++++++----------- progress_bar.hpp | 1 + 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 5c572ce..453aa2b 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -5,6 +5,15 @@ #include #include +#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) + #include + #if !defined(_POSIX_VERSION) + #include + #endif +#else + #include +#endif + const size_t kMessageSize = 20; const double kTotalPercentage = 100.0; const size_t kCharacterWidthPercentage = 7; @@ -12,17 +21,36 @@ const int kDefaultConsoleWidth = 100; const int kMaxBarWidth = 100; +bool to_terminal(const std::ostream &os) { +#if _WINDOWS + if (os.rdbuf() == std::cout.rdbuf() && !_isatty(_fileno(stdout))) + return false; + if (os.rdbuf() == std::cerr.rdbuf() && !_isatty(_fileno(stderr))) + return false; +#else + if (os.rdbuf() == std::cout.rdbuf() && !isatty(fileno(stdout))) + return false; + if (os.rdbuf() == std::cerr.rdbuf() && !isatty(fileno(stderr))) + return false; +#endif + return true; +} + ProgressBar::ProgressBar(uint64_t total, const std::string &description, std::ostream &out_, bool silent) : silent_(silent), total_(total), description_(description) { + if (silent_) return; frequency_update = std::min(static_cast(1000), total_); out = &out_; + if ((logging_mode_ = !to_terminal(*out))) + *out << description_ + '\n' << std::flush; + assert(description_.size() <= kMessageSize); description_.resize(kMessageSize, ' '); @@ -54,15 +82,15 @@ void ProgressBar::SetStyle(char unit_bar, char unit_space) { int ProgressBar::GetConsoleWidth() const { int width = kDefaultConsoleWidth; - #ifdef _WINDOWS +#ifdef _WINDOWS CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); width = csbi.srWindow.Right - csbi.srWindow.Left; - #else +#else struct winsize win; if (ioctl(0, TIOCGWINSZ, &win) != -1) width = win.ws_col; - #endif +#endif return width; } @@ -78,12 +106,37 @@ int ProgressBar::GetBarLength() const { return std::min(max_size / 2, kMaxBarWidth); } +std::string get_progress_summary(double progress_ratio) { + std::string buffer = std::string(kCharacterWidthPercentage, ' '); + + // in some implementations, snprintf always appends null terminal character + snprintf(buffer.data(), kCharacterWidthPercentage, + "%5.1f%%", progress_ratio * kTotalPercentage); + + // erase the last null terminal character + buffer.pop_back(); + return buffer; +} + void ProgressBar::ShowProgress() const { if (silent_) return; std::lock_guard lock(mu_); + // calculate percentage of progress + double progress_ratio = total_ ? static_cast(progress_) / total_ + : 1.0; + assert(progress_ratio >= 0.0); + assert(progress_ratio <= 1.0); + + if (logging_mode_) { + *out << get_progress_summary(progress_ratio) + + ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\n'; + out->flush(); + return; + } + try { // clear previous progressbar *out << std::string(buffer_.size(), ' ') + '\r' << std::flush; @@ -94,24 +147,13 @@ void ProgressBar::ShowProgress() const { if (bar_size < 1) return; - // calculate percentage of progress - double progress_ratio = total_ ? static_cast(progress_) / total_ - : 1.0; - assert(progress_ratio >= 0.0); - assert(progress_ratio <= 1.0); - // write the state of the progress bar buffer_ = " " + description_ + " [" + std::string(size_t(bar_size * progress_ratio), unit_bar_) + std::string(bar_size - size_t(bar_size * progress_ratio), unit_space_) - + "] " + std::string(kCharacterWidthPercentage, ' '); - - snprintf(&buffer_[buffer_.size() - kCharacterWidthPercentage], - kCharacterWidthPercentage, - "%5.1f%%", progress_ratio * kTotalPercentage); - - buffer_ += ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\r'; + + "] " + get_progress_summary(progress_ratio) + + ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\r'; *out << buffer_ << std::flush; diff --git a/progress_bar.hpp b/progress_bar.hpp index 332385a..979a4f7 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -37,6 +37,7 @@ class ProgressBar { int GetBarLength() const; bool silent_; + bool logging_mode_; uint64_t total_; std::atomic progress_ = 0; uint64_t frequency_update; From f23e6fcbfcaa3ba9d5eb526d6684abe58e4e5ca2 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Mon, 26 Aug 2019 18:14:39 +0000 Subject: [PATCH 17/29] fixed frequency update --- progress_bar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 453aa2b..d22f36c 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -45,7 +45,7 @@ ProgressBar::ProgressBar(uint64_t total, if (silent_) return; - frequency_update = std::min(static_cast(1000), total_); + frequency_update = std::max(static_cast(1), total_ / 1000); out = &out_; if ((logging_mode_ = !to_terminal(*out))) From 0373926ebbed6fcb10d5ec5c587d743380f36d2e Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Mon, 11 May 2020 19:43:14 +0200 Subject: [PATCH 18/29] print time in status logs --- progress_bar.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index d22f36c..b463d68 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) #include @@ -131,9 +134,17 @@ void ProgressBar::ShowProgress() const { assert(progress_ratio <= 1.0); if (logging_mode_) { - *out << get_progress_summary(progress_ratio) - + ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\n'; - out->flush(); + // get current time + auto now = std::chrono::system_clock::now(); + std::time_t time = std::chrono::system_clock::to_time_t(now); + auto ms = std::chrono::duration_cast( + now.time_since_epoch()) % 1000; + std::stringstream os; + os << std::put_time(std::localtime(&time), "[%F %T.") + << std::setfill('0') << std::setw(3) << ms.count() << "]\t" + << get_progress_summary(progress_ratio) + << ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\n'; + *out << os.str() << std::flush; return; } From 4f07db06df0e059a883975eeecd4a99b22bdeb20 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Mon, 11 May 2020 19:43:56 +0200 Subject: [PATCH 19/29] use constant width in terminal --- progress_bar.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index b463d68..31393ff 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -52,9 +52,8 @@ ProgressBar::ProgressBar(uint64_t total, out = &out_; if ((logging_mode_ = !to_terminal(*out))) - *out << description_ + '\n' << std::flush; + *out << description_ << std::endl; - assert(description_.size() <= kMessageSize); description_.resize(kMessageSize, ' '); ShowProgress(); @@ -104,7 +103,7 @@ int ProgressBar::GetBarLength() const { - 9 - description_.size() - kCharacterWidthPercentage - - std::ceil(std::log10(std::max(uint64_t(1), total_))) * 2; + - std::ceil(std::log10(std::max(uint64_t(2), total_))) * 4; return std::min(max_size / 2, kMaxBarWidth); } From 7b2259ae91bbd30579408c1da9c73e373409f42a Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 12 Jun 2020 23:48:44 +0200 Subject: [PATCH 20/29] relaxed memory order --- progress_bar.cpp | 16 +++++++++------- progress_bar.hpp | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 31393ff..07eb7c8 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -56,10 +56,11 @@ ProgressBar::ProgressBar(uint64_t total, description_.resize(kMessageSize, ' '); - ShowProgress(); + ShowProgress(0); } ProgressBar::~ProgressBar() { + ShowProgress(progress_); if (!silent_) *out << "\n"; } @@ -120,14 +121,14 @@ std::string get_progress_summary(double progress_ratio) { return buffer; } -void ProgressBar::ShowProgress() const { +void ProgressBar::ShowProgress(uint64_t progress) const { if (silent_) return; std::lock_guard lock(mu_); // calculate percentage of progress - double progress_ratio = total_ ? static_cast(progress_) / total_ + double progress_ratio = total_ ? static_cast(progress) / total_ : 1.0; assert(progress_ratio >= 0.0); assert(progress_ratio <= 1.0); @@ -142,7 +143,7 @@ void ProgressBar::ShowProgress() const { os << std::put_time(std::localtime(&time), "[%F %T.") << std::setfill('0') << std::setw(3) << ms.count() << "]\t" << get_progress_summary(progress_ratio) - << ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\n'; + << ", " + std::to_string(progress) + "/" + std::to_string(total_) + '\n'; *out << os.str() << std::flush; return; } @@ -163,7 +164,7 @@ void ProgressBar::ShowProgress() const { + std::string(size_t(bar_size * progress_ratio), unit_bar_) + std::string(bar_size - size_t(bar_size * progress_ratio), unit_space_) + "] " + get_progress_summary(progress_ratio) - + ", " + std::to_string(progress_) + "/" + std::to_string(total_) + '\r'; + + ", " + std::to_string(progress) + "/" + std::to_string(total_) + '\r'; *out << buffer_ << std::flush; @@ -182,7 +183,8 @@ ProgressBar& ProgressBar::operator+=(uint64_t delta) { if (silent_ || !delta) return *this; - uint64_t after_update = (progress_ += delta); + uint64_t after_update + = progress_.fetch_add(delta, std::memory_order_relaxed) + delta; assert(after_update <= total_); @@ -190,7 +192,7 @@ ProgressBar& ProgressBar::operator+=(uint64_t delta) { if (after_update == total_ || (after_update - delta) / frequency_update < after_update / frequency_update) - ShowProgress(); + ShowProgress(after_update); return *this; } diff --git a/progress_bar.hpp b/progress_bar.hpp index 979a4f7..7f265c8 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -32,7 +32,7 @@ class ProgressBar { ProgressBar(const ProgressBar &) = delete; ProgressBar& operator=(const ProgressBar &) = delete; - void ShowProgress() const; + void ShowProgress(uint64_t progress) const; int GetConsoleWidth() const; int GetBarLength() const; From f3b1b0273c73939a6ef0fc4331afc8555e6d48ec Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Thu, 29 Oct 2020 17:42:43 +0100 Subject: [PATCH 21/29] flush new line right after the total process is achieved --- progress_bar.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 07eb7c8..fb6adb0 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -60,9 +60,12 @@ ProgressBar::ProgressBar(uint64_t total, } ProgressBar::~ProgressBar() { - ShowProgress(progress_); - if (!silent_) - *out << "\n"; + if (progress_ != total_) { + // this is not supposed to happen, but may be useful for debugging + ShowProgress(progress_); + if (!silent_) + *out << "\n"; + } } void ProgressBar::SetFrequencyUpdate(uint64_t frequency_update_) { @@ -189,10 +192,12 @@ ProgressBar& ProgressBar::operator+=(uint64_t delta) { assert(after_update <= total_); // determines whether to update the progress bar from frequency_update - if (after_update == total_ - || (after_update - delta) / frequency_update - < after_update / frequency_update) + if (after_update == total_ || delta >= frequency_update) { ShowProgress(after_update); + } + + if (after_update == total_) + *out << std::endl; return *this; } From 159801445df422cb523ed5dc283d1b6b6f6e975f Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Tue, 3 Nov 2020 14:09:06 +0100 Subject: [PATCH 22/29] fix progress increments --- progress_bar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index fb6adb0..69e617c 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -192,9 +192,10 @@ ProgressBar& ProgressBar::operator+=(uint64_t delta) { assert(after_update <= total_); // determines whether to update the progress bar from frequency_update - if (after_update == total_ || delta >= frequency_update) { + if (after_update == total_ + || (after_update - delta) / frequency_update + < after_update / frequency_update) ShowProgress(after_update); - } if (after_update == total_) *out << std::endl; From c19fc5227ac28864c0d7c701a82ef7ffe7f181a7 Mon Sep 17 00:00:00 2001 From: Atri Bhattacharya Date: Sat, 26 Dec 2020 02:13:25 +0100 Subject: [PATCH 23/29] Cast (const char *) to (char *) for snprintf arg. snprintf() accepts (char *) rather than (const char *) for its first argument. This fixes an `-fpermissive` warning/error when compiling progress_bar.o. --- progress_bar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progress_bar.cpp b/progress_bar.cpp index 69e617c..bbd0505 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -116,7 +116,7 @@ std::string get_progress_summary(double progress_ratio) { std::string buffer = std::string(kCharacterWidthPercentage, ' '); // in some implementations, snprintf always appends null terminal character - snprintf(buffer.data(), kCharacterWidthPercentage, + snprintf((char *)buffer.data(), kCharacterWidthPercentage, "%5.1f%%", progress_ratio * kTotalPercentage); // erase the last null terminal character From 2abb8c207c8ccc8ede5110f529d444b58a61069b Mon Sep 17 00:00:00 2001 From: Atri Bhattacharya Date: Sat, 26 Dec 2020 02:16:50 +0100 Subject: [PATCH 24/29] Fix atomic initialisation. --- progress_bar.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/progress_bar.hpp b/progress_bar.hpp index 7f265c8..9521e5f 100644 --- a/progress_bar.hpp +++ b/progress_bar.hpp @@ -39,7 +39,7 @@ class ProgressBar { bool silent_; bool logging_mode_; uint64_t total_; - std::atomic progress_ = 0; + std::atomic progress_ = {0}; uint64_t frequency_update; std::ostream *out; mutable std::mutex mu_; From 677bf88b39e2176976f905498a73971baa96a481 Mon Sep 17 00:00:00 2001 From: Atri Bhattacharya Date: Sat, 26 Dec 2020 02:18:00 +0100 Subject: [PATCH 25/29] main: Replace Progressed() by increment operators. ProgressBar::Progressed() has been replaced by increment operators. Adapt examples in main code accordingly. --- main.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/main.cpp b/main.cpp index 02648d8..9d24f40 100644 --- a/main.cpp +++ b/main.cpp @@ -13,7 +13,7 @@ int main(){ ProgressBar *bar1 = new ProgressBar(n, "Example 1"); for(int i=0;i<=n;++i){ - bar1->Progressed(i); + *bar1 += 1; std::this_thread::sleep_for (std::chrono::milliseconds(10)); } @@ -27,28 +27,28 @@ int main(){ std::cout << std::endl; for(int i=0;i<=n;++i){ - bar2->Progressed(i); + *bar2 += 1; std::this_thread::sleep_for(std::chrono::milliseconds(1)); } n = 5; ProgressBar bar3(n); - bar3.Progressed(0); + ++bar3; std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(1); + ++bar3; std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(2); + ++bar3; std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(3); + ++bar3; std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(4); + ++bar3; std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(5); + ++bar3; // following tests exception error std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(6); + ++bar3; std::this_thread::sleep_for (std::chrono::milliseconds(200)); - bar3.Progressed(7); + ++bar3; return 0; } From f8dfa61ddb03fa8143013ee19ca072d71877c8a8 Mon Sep 17 00:00:00 2001 From: Atri Bhattacharya Date: Sat, 26 Dec 2020 02:22:59 +0100 Subject: [PATCH 26/29] Pass char instead of (char *) to SetStyle(). This fixes compiling main.o without `-fpermissive`. --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 9d24f40..2438f81 100644 --- a/main.cpp +++ b/main.cpp @@ -22,7 +22,7 @@ int main(){ n = 1000; ProgressBar *bar2 = new ProgressBar(n, "Example 2"); bar2->SetFrequencyUpdate(10); - bar2->SetStyle("|","-"); + bar2->SetStyle('|','-'); //bar2->SetStyle("\u2588", "-"); for linux std::cout << std::endl; From a4f217fd3d377bb9162d3b0fdec45771264fe297 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Sat, 26 Dec 2020 17:43:34 +0100 Subject: [PATCH 27/29] cleanup, fixes of examples in main.cpp --- main.cpp | 72 +++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/main.cpp b/main.cpp index 2438f81..6ef7d85 100644 --- a/main.cpp +++ b/main.cpp @@ -8,47 +8,45 @@ int main(){ int n; /// Example 1 /// + { + n = 100; + ProgressBar bar1(n, "Example 1"); - n = 100; - ProgressBar *bar1 = new ProgressBar(n, "Example 1"); - - for(int i=0;i<=n;++i){ - *bar1 += 1; - std::this_thread::sleep_for (std::chrono::milliseconds(10)); - } + for (int i = 1; i <= n; ++i) { + bar1 += 1; + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } /// Example 2 /// + { + n = 1000; + ProgressBar bar2(n, "Example 2"); + bar2.SetFrequencyUpdate(10); + bar2.SetStyle('|','-'); + //bar2.SetStyle("\u2588", "-"); for linux + for (int i = 1; i <= n; ++i) { + bar2 += 1; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } - n = 1000; - ProgressBar *bar2 = new ProgressBar(n, "Example 2"); - bar2->SetFrequencyUpdate(10); - bar2->SetStyle('|','-'); - //bar2->SetStyle("\u2588", "-"); for linux - - std::cout << std::endl; - for(int i=0;i<=n;++i){ - *bar2 += 1; - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - n = 5; - ProgressBar bar3(n); - ++bar3; - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; - // following tests exception error - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; - std::this_thread::sleep_for (std::chrono::milliseconds(200)); - ++bar3; + ProgressBar bar3(5); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + // following tests exception error + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + ++bar3; return 0; } From 7208674d62eefc64ca870192825c4a3ce2cb88a7 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Sat, 26 Dec 2020 18:19:05 +0100 Subject: [PATCH 28/29] minor changes --- main.cpp | 9 +++------ progress_bar.cpp | 8 +++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index 6ef7d85..06122e2 100644 --- a/main.cpp +++ b/main.cpp @@ -3,13 +3,10 @@ #include #include -int main(){ - - int n; - +int main() { /// Example 1 /// { - n = 100; + int n = 100; ProgressBar bar1(n, "Example 1"); for (int i = 1; i <= n; ++i) { @@ -20,7 +17,7 @@ int main(){ /// Example 2 /// { - n = 1000; + int n = 1000; ProgressBar bar2(n, "Example 2"); bar2.SetFrequencyUpdate(10); bar2.SetStyle('|','-'); diff --git a/progress_bar.cpp b/progress_bar.cpp index bbd0505..61d879f 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -21,7 +21,7 @@ const size_t kMessageSize = 20; const double kTotalPercentage = 100.0; const size_t kCharacterWidthPercentage = 7; const int kDefaultConsoleWidth = 100; -const int kMaxBarWidth = 100; +const int kMaxBarWidth = 120; bool to_terminal(const std::ostream &os) { @@ -103,13 +103,11 @@ int ProgressBar::GetConsoleWidth() const { int ProgressBar::GetBarLength() const { // get console width and according adjust the length of the progress bar - int max_size = GetConsoleWidth() + return std::min(GetConsoleWidth(), kMaxBarWidth) - 9 - description_.size() - kCharacterWidthPercentage - - std::ceil(std::log10(std::max(uint64_t(2), total_))) * 4; - - return std::min(max_size / 2, kMaxBarWidth); + - std::floor(std::log10(std::max((uint64_t)2, total_)) + 1) * 2; } std::string get_progress_summary(double progress_ratio) { From 609addab173957f3a3150c048c9e736166e40e51 Mon Sep 17 00:00:00 2001 From: Mikhail Karasikov Date: Fri, 16 Apr 2021 11:50:01 +0200 Subject: [PATCH 29/29] fixed prints of 0/0 progress --- progress_bar.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/progress_bar.cpp b/progress_bar.cpp index 61d879f..86a5498 100644 --- a/progress_bar.cpp +++ b/progress_bar.cpp @@ -57,6 +57,8 @@ ProgressBar::ProgressBar(uint64_t total, description_.resize(kMessageSize, ' '); ShowProgress(0); + if (progress_ == total_) + *out << std::endl; } ProgressBar::~ProgressBar() {