32 #ifndef VSMC_UTILITY_PROGRESS_HPP
33 #define VSMC_UTILITY_PROGRESS_HPP
38 #if VSMC_HAS_CXX11LIB_CHRONO && VSMC_HAS_CXX11LIB_THREAD
45 #if VSMC_HAS_CXX11LIB_CHRONO && VSMC_HAS_CXX11LIB_THREAD
52 double ms = std::floor(s * 1000);
55 std::this_thread::sleep_for(std::chrono::milliseconds(
56 static_cast<std::chrono::milliseconds::rep>(ms)));
94 #if VSMC_HAS_CXX11LIB_CHRONO && VSMC_HAS_CXX11LIB_THREAD
95 template <
typename ThreadType = std::thread,
96 typename ThisThread = internal::ProgressThisThread>
98 template <
typename ThreadType,
typename ThisThread>
108 thread_ptr_(
VSMC_NULLPTR), interval_(0), iter_(0), total_(0),
109 length_(0), show_iter_(false), print_first_(true), in_progress_(false),
110 num_equal_(0), percent_(0), seconds_(0), last_iter_(0),
111 cstr_bar_(), cstr_percent_(), cstr_time_(), cstr_iter_(), os_(os) {}
122 void start (std::size_t total,
const std::string &msg = std::string(),
123 std::size_t length = 0,
bool show_iter =
false,
124 double interval = 0.1)
129 show_iter_ = show_iter;
130 interval_ = interval;
147 void stop (
bool finished =
false)
149 in_progress_ =
false;
151 if (finished && iter_ < total_)
163 thread_type *thread_ptr_;
173 std::size_t num_equal_;
174 std::size_t percent_;
175 std::size_t seconds_;
176 std::size_t last_iter_;
180 char cstr_percent_[32];
195 if (thread_ptr_->joinable())
202 static void print_start_ (
void *context)
205 while (ptr->in_progress_) {
206 print_progress(context);
207 ptr->os_ <<
'\r' << std::flush;
208 ThisThread::sleep(ptr->interval_);
212 static void print_stop_ (
void *context)
215 print_progress(context);
216 ptr->os_ <<
'\n' << std::flush;
219 static void print_progress (
void *context)
225 const std::size_t seconds =
226 static_cast<std::size_t
>(ptr->watch_.seconds());
228 const std::size_t display_iter = ptr->iter_ <= ptr->total_ ?
229 ptr->iter_ : ptr->total_;
230 std::size_t num_equal = (ptr->total_ | ptr->length_) == 0 ?
231 ptr->length_ : ptr->length_ * display_iter / ptr->total_;
232 num_equal = num_equal <= ptr->length_ ? num_equal : ptr->length_;
233 std::size_t percent = ptr->total_ == 0 ? 100 :
234 100 * display_iter / ptr->total_;
235 percent = percent <= 100 ? percent : 100;
237 if (ptr->print_first_) {
238 ptr->print_first_ =
false;
239 ptr->num_equal_ = num_equal + 1;
240 ptr->percent_ = percent + 1;
241 ptr->seconds_ = seconds + 1;
242 ptr->last_iter_ = ptr->iter_ + 1;
245 if (ptr->length_ != 0 && ptr->num_equal_ != num_equal) {
246 ptr->num_equal_ = num_equal;
247 std::size_t num_space = ptr->length_ - num_equal;
248 std::size_t num_dash = 0;
254 char *cstr = ptr->cstr_bar_;
255 std::size_t offset = 0;
256 cstr[offset++] =
'[';
257 for (std::size_t i = 0; i != num_equal; ++i)
258 cstr[offset++] =
'=';
259 for (std::size_t i = 0; i != num_dash; ++i)
260 cstr[offset++] =
'-';
261 for (std::size_t i = 0; i != num_space; ++i)
262 cstr[offset++] =
' ';
263 cstr[offset++] =
']';
264 cstr[offset++] =
'\0';
267 if (ptr->percent_ != percent) {
268 ptr->percent_ = percent;
269 const std::size_t num_space = 3 - uint_digit(percent);
271 char *cstr = ptr->cstr_percent_;
272 std::size_t offset = 0;
273 cstr[offset++] =
'[';
274 for (std::size_t i = 0; i != num_space; ++i)
275 cstr[offset++] =
' ';
276 uint_to_char(percent, cstr, offset);
277 cstr[offset++] =
'%';
278 cstr[offset++] =
']';
279 cstr[offset++] =
'\0';
282 if (ptr->seconds_ != seconds) {
283 ptr->seconds_ = seconds;
284 const std::size_t display_second = seconds % 60;
285 const std::size_t display_minute = (seconds / 60) % 60;
286 const std::size_t display_hour = seconds / 3600;
288 char *cstr = ptr->cstr_time_;
289 std::size_t offset = 0;
290 cstr[offset++] =
'[';
291 if (display_hour > 0) {
292 uint_to_char(display_hour, cstr, offset);
293 cstr[offset++] =
':';
295 cstr[offset++] =
'0' +
static_cast<char>(display_minute / 10);
296 cstr[offset++] =
'0' +
static_cast<char>(display_minute % 10);
297 cstr[offset++] =
':';
298 cstr[offset++] =
'0' +
static_cast<char>(display_second / 10);
299 cstr[offset++] =
'0' +
static_cast<char>(display_second % 10);
300 cstr[offset++] =
']';
301 cstr[offset++] =
'\0';
304 if (ptr->show_iter_ && ptr->last_iter_ != ptr->iter_) {
305 ptr->last_iter_ = ptr->iter_;
306 const std::size_t dtotal = uint_digit(ptr->total_);
307 const std::size_t diter = uint_digit(ptr->iter_);
308 const std::size_t num_space = dtotal > diter ? dtotal - diter : 0;
310 char *cstr = ptr->cstr_iter_;
311 std::size_t offset = 0;
312 cstr[offset++] =
'[';
313 for (std::size_t i = 0; i < num_space; ++i)
314 cstr[offset++] =
' ';
315 uint_to_char(ptr->iter_, cstr, offset);
316 cstr[offset++] =
'/';
317 uint_to_char(ptr->total_, cstr, offset);
318 cstr[offset++] =
']';
319 cstr[offset++] =
'\0';
323 if (ptr->length_ != 0) ptr->os_ << ptr->cstr_bar_;
324 ptr->os_ << ptr->cstr_percent_;
325 ptr->os_ << ptr->cstr_time_;
326 if (ptr->show_iter_) ptr->os_ << ptr->cstr_iter_;
327 if (ptr->msg_.size() != 0) ptr->os_ <<
'[' << ptr->msg_ <<
']';
330 template <
typename UIntType>
331 static void uint_to_char (UIntType num,
char *cstr, std::size_t &offset)
334 cstr[offset++] =
'0';
339 std::size_t unum = 0;
341 utmp[unum++] =
'0' +
static_cast<char>(num % 10);
344 for (std::size_t i = unum; i != 0; --i)
345 cstr[offset++] = utmp[i - 1];
348 template <
typename UIntType>
349 static std::size_t uint_digit (UIntType num)
354 std::size_t digit = 0;
366 #endif // VSMC_UTILITY_PROGRESS_HPP
Progress(std::ostream &os=std::cout)
Construct a Progress with an output stream.
static void sleep(double s)
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=false, double interval=0.1)
Start to print the progress.
void increment(std::size_t step=1)
Increment the iteration count.
StopWatch as an adapter of C++11 clock.
bool stop()
Stop the watch, no effect if already stopped.
#define VSMC_NULLPTR
nullptr
bool start()
Start the watch, no effect if already started.
void stop(bool finished=false)
Stop to print the progress.
Display a progress bar while algorithm proceed.