32 #ifndef VSMC_UTILITY_PROGRESS_HPP 33 #define VSMC_UTILITY_PROGRESS_HPP 48 : thread_ptr_(nullptr)
83 void start(std::size_t total,
const std::string &msg = std::string(),
84 std::size_t length = 0,
bool show_iter =
true,
double interval_s = 0.1)
89 show_iter_ = show_iter;
90 interval_ms_ = std::max(1.0, interval_s * 1000);
103 void stop(
bool finished =
true)
106 if (finished && iter_ < total_)
120 void message(
const std::string &msg) { msg_ = msg; }
123 static constexpr std::size_t max_val_ =
124 std::numeric_limits<std::size_t>::max();
127 std::thread *thread_ptr_;
130 std::atomic<std::size_t> iter_;
137 std::size_t num_equal_;
138 std::size_t percent_;
139 std::size_t seconds_;
140 std::size_t last_iter_;
144 char cstr_percent_[32];
156 thread_ptr_ =
new std::thread([
this]() { print_start(); });
161 in_progress_ =
false;
162 if (thread_ptr_ !=
nullptr) {
163 if (thread_ptr_->joinable())
166 thread_ptr_ =
nullptr;
172 while (in_progress_) {
174 os_ <<
'\r' << std::flush;
175 std::this_thread::sleep_for(std::chrono::milliseconds(
176 static_cast<std::chrono::milliseconds::rep>(interval_ms_)));
183 os_ <<
'\n' << std::flush;
186 void print_progress()
190 const std::size_t seconds =
static_cast<std::size_t
>(watch_.
seconds());
192 std::size_t iter = iter_;
193 std::size_t display_iter = std::min(iter, total_);
194 std::size_t num_equal = (length_ == 0 || total_ == 0) ? 0 : length_ *
195 display_iter / total_;
196 std::size_t percent = total_ == 0 ? 100 : 100 * display_iter / total_;
199 print_first_ =
false;
200 num_equal_ = max_val_;
203 last_iter_ = max_val_;
206 if (length_ != 0 && num_equal_ != num_equal) {
207 num_equal_ = num_equal;
208 std::size_t num_space = length_ - num_equal;
209 std::size_t num_dash = 0;
215 char *cstr = cstr_bar_;
216 std::size_t offset = 0;
217 cstr[offset++] =
'[';
218 for (std::size_t i = 0; i != num_equal; ++i)
219 cstr[offset++] =
'=';
220 for (std::size_t i = 0; i != num_dash; ++i)
221 cstr[offset++] =
'-';
222 for (std::size_t i = 0; i != num_space; ++i)
223 cstr[offset++] =
' ';
224 cstr[offset++] =
']';
225 cstr[offset++] =
'\0';
228 if (percent_ != percent) {
230 const std::size_t num_space = 3 - uint_digit(percent);
232 char *cstr = cstr_percent_;
233 std::size_t offset = 0;
234 cstr[offset++] =
'[';
235 for (std::size_t i = 0; i != num_space; ++i)
236 cstr[offset++] =
' ';
237 uint_to_char(percent, cstr, offset);
238 cstr[offset++] =
'%';
239 cstr[offset++] =
']';
240 cstr[offset++] =
'\0';
243 if (seconds_ != seconds) {
245 const std::size_t display_second = seconds % 60;
246 const std::size_t display_minute = (seconds / 60) % 60;
247 const std::size_t display_hour = seconds / 3600;
249 char *cstr = cstr_time_;
250 std::size_t offset = 0;
251 cstr[offset++] =
'[';
252 if (display_hour > 0) {
253 uint_to_char(display_hour, cstr, offset);
254 cstr[offset++] =
':';
256 cstr[offset++] =
static_cast<char>(
'0' + display_minute / 10);
257 cstr[offset++] =
static_cast<char>(
'0' + display_minute % 10);
258 cstr[offset++] =
':';
259 cstr[offset++] =
static_cast<char>(
'0' + display_second / 10);
260 cstr[offset++] =
static_cast<char>(
'0' + display_second % 10);
261 cstr[offset++] =
']';
262 cstr[offset++] =
'\0';
265 if (show_iter_ && last_iter_ != iter) {
267 const std::size_t dtotal = uint_digit(total_);
268 const std::size_t diter = uint_digit(iter);
269 const std::size_t num_space = dtotal > diter ? dtotal - diter : 0;
271 char *cstr = cstr_iter_;
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(iter, cstr, offset);
277 cstr[offset++] =
'/';
278 uint_to_char(total_, cstr, offset);
279 cstr[offset++] =
']';
280 cstr[offset++] =
'\0';
286 os_ << cstr_percent_;
290 if (msg_.size() != 0)
291 os_ <<
'[' << msg_ <<
']';
294 template <
typename UIntType>
295 static void uint_to_char(UIntType num,
char *cstr, std::size_t &offset)
298 cstr[offset++] =
'0';
303 std::size_t unum = 0;
305 utmp[unum++] =
static_cast<char>(
'0' + num % 10);
308 for (std::size_t i = unum; i != 0; --i)
309 cstr[offset++] = utmp[i - 1];
312 template <
typename UIntType>
313 static std::size_t uint_digit(UIntType num)
318 std::size_t digit = 0;
330 #endif // VSMC_UTILITY_PROGRESS_HPP Progress(std::ostream &os=std::cout)
Construct a Progress with an output stream.
std::basic_ostream< CharT, Traits > & ostream(std::basic_ostream< CharT, Traits > &os, const std::array< T, N > &ary)
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.
Progress & operator=(const Progress &other)=delete
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.