Developer documentation
Version 3.0.3-105-gd3941f44
progressbar.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __progressbar_h__
18#define __progressbar_h__
19
20#include <string>
21#include <memory>
22#include <mutex>
23#include <condition_variable>
24#include <chrono>
25
26
27#include "mrtrix.h"
28#include "timer.h"
29#include "types.h"
30#include "math/math.h"
31#include "debug.h"
32
33#define BUSY_INTERVAL 0.1
34
35namespace MR
36{
37
38
40
59 public:
60
62 ProgressBar () : show (false) { }
63 ProgressBar (const ProgressBar& p) = delete;
64 ProgressBar (ProgressBar&& p) = default;
65
67 done();
68 }
69
71
76 ProgressBar (const std::string& text, size_t target = 0, int log_level = 1);
77
79
82 FORCE_INLINE operator bool () const {
83 return show;
84 }
85
87
90 FORCE_INLINE bool operator! () const {
91 return !show;
92 }
93
94 FORCE_INLINE size_t value () const { return _value; }
95 FORCE_INLINE size_t count () const { return current_val; }
96 FORCE_INLINE bool show_percent () const { return _multiplier; }
97 FORCE_INLINE bool text_has_been_modified () const { return _text_has_been_modified; }
98 FORCE_INLINE const std::string& text () const { return _text; }
99 FORCE_INLINE const std::string& ellipsis () const { return _ellipsis; }
100
102
106 FORCE_INLINE void set_max (size_t new_target);
107
108 FORCE_INLINE void set_text (const std::string& new_text);
109
111
131 template <class TextFunc>
132 FORCE_INLINE void update (TextFunc&& text_func, bool increment = true);
133
136 FORCE_INLINE void operator++ (int) { ++ (*this); }
137
139 if (show) {
140 done_func (*this);
141 progressbar_active = false;
142 }
143 }
144
145 template <class ThreadType>
146 void run_update_thread (const ThreadType& threads) const;
147
151 };
152
153
154
155 static bool set_update_method ();
156 static void (*display_func) (const ProgressBar& p);
157 static void (*done_func) (const ProgressBar& p);
158 static void (*previous_display_func) (const ProgressBar& p);
159
160 static std::condition_variable notifier;
162 static std::mutex mutex;;
163 static void* data;
164
165 mutable bool first_time;
166 mutable size_t last_value;
167
168 private:
169
170 const bool show;
171 std::string _text, _ellipsis;
172 size_t _value, current_val, next_percent;
173 double next_time;
174 float _multiplier;
175 Timer timer;
176 bool _text_has_been_modified;
177
178 FORCE_INLINE void display_now () { display_func (*this); }
179
180 static bool progressbar_active;
181 };
182
183
184
185
186
187
188
189
190
191
192 FORCE_INLINE ProgressBar::ProgressBar (const std::string& text, size_t target, int log_level) :
193 first_time (true),
194 last_value (0),
195 show (std::this_thread::get_id() == ::MR::App::main_thread_ID && !progressbar_active && App::log_level >= log_level),
196 _text (text),
197 _ellipsis ("..."),
198 _value (0),
199 current_val (0),
200 next_percent (0),
201 next_time (0.0),
202 _multiplier (0.0),
203 _text_has_been_modified (false) {
204 if (show) {
205 set_max (target);
206 progressbar_active = true;
207 }
208 }
209
210
211
212
213 inline void ProgressBar::set_max (size_t target)
214 {
215 if (!show)
216 return;
217 if (target) {
218 _multiplier = 0.01 * target;
219 }
220 else {
221 _multiplier = 0.0;
222 timer.start();
223 }
224 }
225
226
227
228 FORCE_INLINE void ProgressBar::set_text (const std::string& new_text)
229 {
230 if (!show)
231 return;
232 _text_has_been_modified = true;
233 if (new_text.size()) {
234#ifdef MRTRIX_WINDOWS
235 size_t old_size = _text.size();
236#endif
237 _text = new_text;
238#ifdef MRTRIX_WINDOWS
239 if (_text.size() < old_size)
240 _text.resize (old_size, ' ');
241#endif
242 }
243 }
244
245
246
247
248
249 template <class TextFunc>
250 FORCE_INLINE void ProgressBar::update (TextFunc&& text_func, const bool increment)
251 {
252 if (!show)
253 return;
254 double time = timer.elapsed();
255 if (increment && _multiplier) {
256 if (++current_val >= next_percent) {
257 set_text (text_func());
258 _ellipsis.clear();
259 _value = std::round (current_val / _multiplier);
260 next_percent = std::ceil ((_value+1) * _multiplier);
261 next_time = time;
262 display_now();
263 return;
264 }
265 }
266 if (time >= next_time) {
267 set_text (text_func());
268 _ellipsis.clear();
269 if (_multiplier)
270 next_time = time + BUSY_INTERVAL;
271 else {
272 _value = time / BUSY_INTERVAL;
273 do { next_time += BUSY_INTERVAL; }
274 while (next_time <= time);
275 }
276 display_now();
277 }
278 }
279
280
281
282
284 {
285 if (!show)
286 return;
287 if (_multiplier) {
288 if (++current_val >= next_percent) {
289 _value = std::round (current_val / _multiplier);
290 next_percent = std::ceil ((_value+1) * _multiplier);
291 display_now();
292 }
293 }
294 else {
295 double time = timer.elapsed();
296 if (time >= next_time) {
297 _value = time / BUSY_INTERVAL;
298 do { next_time += BUSY_INTERVAL; }
299 while (next_time <= time);
300 display_now();
301 }
302 }
303 }
304
305
306
307
308
309 template <class ThreadType>
310 inline void ProgressBar::run_update_thread (const ThreadType& threads) const
311 {
312 if (!show)
313 return;
314 std::unique_lock<std::mutex> lock (mutex);
315 while (!threads.finished()) {
316 notifier.wait_for (lock, std::chrono::milliseconds(1), []{ return notification_is_genuine; });
318 previous_display_func (*this);
320 }
321 }
322 }
323
324}
325
326#endif
327
implements a progress meter to provide feedback to the user
Definition: progressbar.h:58
ProgressBar()
Create an unusable ProgressBar.
Definition: progressbar.h:62
static void * data
Definition: progressbar.h:162
bool text_has_been_modified() const
Definition: progressbar.h:97
static bool notification_is_genuine
Definition: progressbar.h:161
void operator++()
increment the current value by one.
Definition: progressbar.h:283
bool operator!() const
returns whether the progress will be shown
Definition: progressbar.h:90
size_t value() const
Definition: progressbar.h:94
void run_update_thread(const ThreadType &threads) const
Definition: progressbar.h:310
static void(* display_func)(const ProgressBar &p)
Definition: progressbar.h:156
const std::string & text() const
Definition: progressbar.h:98
static void(* previous_display_func)(const ProgressBar &p)
Definition: progressbar.h:158
static bool set_update_method()
size_t count() const
Definition: progressbar.h:95
void set_max(size_t new_target)
set the maximum target value of the ProgressBar
Definition: progressbar.h:213
ProgressBar(const ProgressBar &p)=delete
const std::string & ellipsis() const
Definition: progressbar.h:99
static void(* done_func)(const ProgressBar &p)
Definition: progressbar.h:157
static std::condition_variable notifier
Definition: progressbar.h:160
void update(TextFunc &&text_func, bool increment=true)
update text displayed and optionally increment counter
Definition: progressbar.h:250
ProgressBar(ProgressBar &&p)=default
bool show_percent() const
Definition: progressbar.h:96
void set_text(const std::string &new_text)
Definition: progressbar.h:228
static std::mutex mutex
Definition: progressbar.h:162
void start()
Definition: timer.h:33
double elapsed()
Definition: timer.h:36
constexpr I ceil(const T x)
template function with cast to different type
Definition: math.h:86
constexpr I round(const T x)
Definition: math.h:64
#define NOMEMALIGN
Definition: memory.h:22
int log_level
Definition: exception.h:34
const std::thread::id main_thread_ID
Definition: base.h:24
Definition: types.h:303
#define BUSY_INTERVAL
Definition: progressbar.h:33
#define FORCE_INLINE
Definition: types.h:156
vector< std::future< void > > threads
Definition: thread.h:201