32 #ifndef VSMC_UTILITY_PROGRESS_HPP    33 #define VSMC_UTILITY_PROGRESS_HPP    48         : thread_ptr_(nullptr)
    79     void start(std::size_t total, 
const std::string &msg = std::string(),
    80         std::size_t length = 0, 
bool show_iter = 
true, 
double interval_s = 0.1)
    85         show_iter_ = show_iter;
    86         interval_ms_ = std::max(1.0, interval_s * 1000);
    99     void stop(
bool finished = 
true)
   102         if (finished && iter_ < total_)
   116     void message(
const std::string &msg) { msg_ = msg; }
   119     static constexpr std::size_t max_val_ =
   120         std::numeric_limits<std::size_t>::max();
   123     std::thread *thread_ptr_;
   126     std::atomic<std::size_t> iter_;
   133     std::size_t num_equal_;
   134     std::size_t percent_;
   135     std::size_t seconds_;
   136     std::size_t last_iter_;
   140     char cstr_percent_[32];
   152         thread_ptr_ = 
new std::thread(print_start_, 
this);
   157         in_progress_ = 
false;
   158         if (thread_ptr_ != 
nullptr) {
   159             if (thread_ptr_->joinable())
   162             thread_ptr_ = 
nullptr;
   166     static void print_start_(
void *context)
   169         while (ptr->in_progress_) {
   170             print_progress(context);
   171             ptr->os_ << 
'\r' << std::flush;
   172             std::this_thread::sleep_for(std::chrono::milliseconds(
   173                 static_cast<std::chrono::milliseconds::rep>(
   174                     ptr->interval_ms_)));
   178     static void print_stop_(
void *context)
   181         print_progress(context);
   182         ptr->os_ << 
'\n' << std::flush;
   185     static void print_progress(
void *context)
   191         const std::size_t seconds =
   192             static_cast<std::size_t
>(ptr->watch_.
seconds());
   194         std::size_t iter = ptr->iter_;
   195         std::size_t display_iter = std::min(iter, ptr->total_);
   196         std::size_t num_equal = (ptr->length_ == 0 || ptr->total_ == 0) ?
   198             ptr->length_ * display_iter / ptr->total_;
   199         std::size_t percent =
   200             ptr->total_ == 0 ? 100 : 100 * display_iter / ptr->total_;
   202         if (ptr->print_first_) {
   203             ptr->print_first_ = 
false;
   204             ptr->num_equal_ = max_val_;
   205             ptr->percent_ = max_val_;
   206             ptr->seconds_ = max_val_;
   207             ptr->last_iter_ = max_val_;
   210         if (ptr->length_ != 0 && ptr->num_equal_ != num_equal) {
   211             ptr->num_equal_ = num_equal;
   212             std::size_t num_space = ptr->length_ - num_equal;
   213             std::size_t num_dash = 0;
   219             char *cstr = ptr->cstr_bar_;
   220             std::size_t offset = 0;
   221             cstr[offset++] = 
'[';
   222             for (std::size_t i = 0; i != num_equal; ++i)
   223                 cstr[offset++] = 
'=';
   224             for (std::size_t i = 0; i != num_dash; ++i)
   225                 cstr[offset++] = 
'-';
   226             for (std::size_t i = 0; i != num_space; ++i)
   227                 cstr[offset++] = 
' ';
   228             cstr[offset++] = 
']';
   229             cstr[offset++] = 
'\0';
   232         if (ptr->percent_ != percent) {
   233             ptr->percent_ = percent;
   234             const std::size_t num_space = 3 - uint_digit(percent);
   236             char *cstr = ptr->cstr_percent_;
   237             std::size_t offset = 0;
   238             cstr[offset++] = 
'[';
   239             for (std::size_t i = 0; i != num_space; ++i)
   240                 cstr[offset++] = 
' ';
   241             uint_to_char(percent, cstr, offset);
   242             cstr[offset++] = 
'%';
   243             cstr[offset++] = 
']';
   244             cstr[offset++] = 
'\0';
   247         if (ptr->seconds_ != seconds) {
   248             ptr->seconds_ = seconds;
   249             const std::size_t display_second = seconds % 60;
   250             const std::size_t display_minute = (seconds / 60) % 60;
   251             const std::size_t display_hour = seconds / 3600;
   253             char *cstr = ptr->cstr_time_;
   254             std::size_t offset = 0;
   255             cstr[offset++] = 
'[';
   256             if (display_hour > 0) {
   257                 uint_to_char(display_hour, cstr, offset);
   258                 cstr[offset++] = 
':';
   260             cstr[offset++] = 
'0' + 
static_cast<char>(display_minute / 10);
   261             cstr[offset++] = 
'0' + 
static_cast<char>(display_minute % 10);
   262             cstr[offset++] = 
':';
   263             cstr[offset++] = 
'0' + 
static_cast<char>(display_second / 10);
   264             cstr[offset++] = 
'0' + 
static_cast<char>(display_second % 10);
   265             cstr[offset++] = 
']';
   266             cstr[offset++] = 
'\0';
   269         if (ptr->show_iter_ && ptr->last_iter_ != iter) {
   270             ptr->last_iter_ = iter;
   271             const std::size_t dtotal = uint_digit(ptr->total_);
   272             const std::size_t diter = uint_digit(iter);
   273             const std::size_t num_space = dtotal > diter ? dtotal - diter : 0;
   275             char *cstr = ptr->cstr_iter_;
   276             std::size_t offset = 0;
   277             cstr[offset++] = 
'[';
   278             for (std::size_t i = 0; i < num_space; ++i)
   279                 cstr[offset++] = 
' ';
   280             uint_to_char(iter, cstr, offset);
   281             cstr[offset++] = 
'/';
   282             uint_to_char(ptr->total_, cstr, offset);
   283             cstr[offset++] = 
']';
   284             cstr[offset++] = 
'\0';
   288         if (ptr->length_ != 0)
   289             ptr->os_ << ptr->cstr_bar_;
   290         ptr->os_ << ptr->cstr_percent_;
   291         ptr->os_ << ptr->cstr_time_;
   293             ptr->os_ << ptr->cstr_iter_;
   294         if (ptr->msg_.size() != 0)
   295             ptr->os_ << 
'[' << ptr->msg_ << 
']';
   298     template <
typename UIntType>
   299     static void uint_to_char(UIntType num, 
char *cstr, std::size_t &offset)
   302             cstr[offset++] = 
'0';
   307         std::size_t unum = 0;
   309             utmp[unum++] = 
'0' + 
static_cast<char>(num % 10);
   312         for (std::size_t i = unum; i != 0; --i)
   313             cstr[offset++] = utmp[i - 1];
   316     template <
typename UIntType>
   317     static std::size_t uint_digit(UIntType num)
   322         std::size_t digit = 0;
   334 #endif // VSMC_UTILITY_PROGRESS_HPP Progress(std::ostream &os=std::cout)
Construct a Progress with an output stream. 
 
void stop(bool finished=true)
Stop to print the progress. 
 
void increment(std::size_t step=1)
Increment the iteration count. 
 
void reset()
Stop and reset the elapsed time to zero. 
 
void start(std::size_t total, const std::string &msg=std::string(), std::size_t length=0, bool show_iter=true, double interval_s=0.1)
Start to print the progress. 
 
bool stop()
Stop the watch, no effect if already stopped. 
 
bool start()
Start the watch, no effect if already started. 
 
Display a progress bar while algorithm proceed. 
 
double seconds() const 
Return the accumulated elapsed time in seconds. 
 
void message(const std::string &msg)
Set a new message for display.