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.