stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
progress.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023-2024 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#include "interval.hpp"
10#include <atomic>
11#include <chrono>
12#include <shared_mutex>
13#include <vector>
14
15namespace stdex
16{
20 template <class T>
22 {
23 public:
29 virtual void set_text(_In_z_ const char* msg)
30 {
31 _Unreferenced_(msg);
32 }
33
40 virtual void set_range(_In_ T start, _In_ T end)
41 {
42 start; end;
43 }
44
50 virtual void set(_In_ T value)
51 {
52 value;
53 }
54
60 virtual void show(_In_ bool show = true)
61 {
62 _Unreferenced_(show);
63 }
64
68 virtual bool cancel()
69 {
70 return false;
71 }
72 };
73
79 template <class T>
80 class lazy_progress : public progress<T>
81 {
82 public:
88 lazy_progress(_In_ const std::chrono::nanoseconds& timeout = std::chrono::milliseconds(500)) :
89 m_timeout(timeout),
90 m_start(0),
91 m_end(0),
92 m_value(-1)
93 {}
94
101 virtual void set_range(_In_ T start, _In_ T end)
102 {
103 m_start = start;
104 m_end = end;
105 }
106
112 virtual void set(_In_ T value)
113 {
114 if (value == m_start || value == m_end)
115 m_last = std::chrono::high_resolution_clock::now();
116 else if (value == m_value)
117 return;
118 else {
119 auto now = std::chrono::high_resolution_clock::now();
120 if (now - m_last < m_timeout)
121 return;
122 m_last = now;
123 }
124 m_value = value;
125 do_set();
126 }
127
128 protected:
132 virtual void do_set() {}
133
134 protected:
135 std::chrono::nanoseconds m_timeout;
136 std::chrono::system_clock::time_point m_last;
137 T m_start, m_end, m_value;
138 };
139
145 template <class T>
146 class timeout_progress : public progress<T>
147 {
148 public:
154 timeout_progress(_In_ const std::chrono::nanoseconds& timeout = std::chrono::seconds(60), _In_opt_ progress<T>* host = nullptr) :
155 m_host(host),
156 m_deadline(std::chrono::high_resolution_clock::now() + timeout)
157 {}
158
164 virtual void set_text(_In_z_ const char* msg)
165 {
166 if (m_host)
167 m_host->set_text(msg);
168 }
169
176 virtual void set_range(_In_ T start, _In_ T end)
177 {
178 if (m_host)
179 m_host->set_range(start, end);
180 }
181
187 virtual void set(_In_ T value)
188 {
189 if (m_host)
190 m_host->set(value);
191 }
192
198 virtual void show(_In_ bool show = true)
199 {
200 if (m_host)
201 m_host->show(show);
202 }
203
207 virtual bool cancel()
208 {
209 return
210 m_host && m_host->cancel() ||
211 m_deadline < std::chrono::high_resolution_clock::now();
212 }
213
214 protected:
215 progress<T>* m_host;
216 std::chrono::high_resolution_clock::time_point m_deadline;
217 };
218
224 template <class T>
225 class global_progress : public progress<T>
226 {
227 public:
233 global_progress(_In_opt_ progress<T>* host = nullptr) : m_host(host)
234 {}
235
241 void attach(_In_opt_ progress<T>* host)
242 {
243 m_host = host;
244 }
245
252 {
253 progress<T>* k = m_host;
254 m_host = nullptr;
255 return k;
256 }
257
264 void set_global_range(_In_ T start, _In_ T end)
265 {
266 m_global.start = start;
267 m_global.end = end;
268 if (m_host)
269 m_host->set_range(m_global.start, m_global.end);
270 }
271
278 void set_section_range(_In_ T start, _In_ T end)
279 {
280 m_section.start = start;
281 m_section.end = end;
282 }
283
289 virtual void set_text(_In_ const char* msg)
290 {
291 if (m_host)
292 m_host->set_text(msg);
293 }
294
301 virtual void set_range(_In_ T start, _In_ T end)
302 {
303 m_local.start = start;
304 m_local.end = end;
305 }
306
312 virtual void set(_In_ T value)
313 {
314 if (m_host) {
315 T size = m_local.size();
316 if (size != 0) {
317 // TODO: Implement with muldiv.
318 m_host->set(((value - m_local.start) * m_section.size() / size) + m_section.start);
319 }
320 }
321 }
322
328 virtual void show(_In_ bool show = true)
329 {
330 if (m_host)
331 m_host->show(show);
332 }
333
337 virtual bool cancel()
338 {
339 return m_host && m_host->cancel();
340 }
341
342 protected:
343 progress<T>* m_host;
344 interval<T> m_local, m_global, m_section;
345 };
346
352 template <class T>
354 {
355 public:
357 global_progress<T>(host),
358 m_host_ref(host)
359 {
360 m_host_ref = this;
361 }
362
364 {
365 m_host_ref = this->detach();
366 }
367
368 protected:
369 progress<T>*& m_host_ref;
370 };
371
377 template <class T>
379 {
380 protected:
384 class worker_progress : public progress<T>
385 {
386 protected:
387 aggregate_progress<T>& m_host;
388 T m_start, m_end, m_value;
389
390 public:
392 m_host(host),
393 m_start(0), m_end(0),
394 m_value(0)
395 {}
396
402 virtual void set_text(_In_ const char* msg)
403 {
404 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
405 if (m_host.m_host)
406 m_host.m_host->set_text(msg);
407 }
408
415 virtual void set_range(_In_ T start, _In_ T end)
416 {
417 T
418 combined_start = m_host.m_start += start - m_start,
419 combined_end = m_host.m_end += end - m_end;
420 m_start = start;
421 m_end = end;
422 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
423 if (m_host.m_host)
424 m_host.m_host->set_range(combined_start, combined_end);
425 }
426
432 virtual void set(_In_ T value)
433 {
434 T combined_value = m_host.m_value += value - m_value;
435 m_value = value;
436 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
437 if (m_host.m_host)
438 m_host.m_host->set(combined_value);
439 }
440
446 virtual void show(_In_ bool show = true)
447 {
448 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
449 if (m_host.m_host)
450 m_host.m_host->show(show);
451 }
452
456 virtual bool cancel()
457 {
458 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
459 return m_host.m_host && m_host.m_host->cancel();
460 }
461 };
462
463 progress<T>* m_host;
464 std::atomic<T> m_start, m_end, m_value;
465 std::vector<worker_progress> m_workers;
466 std::shared_mutex m_mutex;
467
468 public:
475 aggregate_progress(_In_ size_t num_workers, _In_opt_ progress<T>* host = nullptr) :
476 m_host(host),
477 m_start(0), m_end(0),
478 m_value(0)
479 {
480 m_workers.reserve(num_workers);
481 for (size_t i = 0; i < num_workers; ++i)
482 m_workers.push_back(std::move(worker_progress(*this)));
483 if (m_host) {
484 m_host->set_range(m_start, m_end);
485 m_host->set(m_value);
486 }
487 }
488
494 void attach(_In_opt_ progress<T>* host)
495 {
496 std::unique_lock<std::shared_mutex> lk(m_mutex);
497 m_host = host;
498 if (m_host) {
499 m_host->set_range(m_start, m_end);
500 m_host->set(m_value);
501 }
502 }
503
510 {
511 std::unique_lock<std::shared_mutex> lk(m_mutex);
512 progress<T>* k = m_host;
513 m_host = nullptr;
514 return k;
515 }
516
524 progress<T>& operator[](_In_ size_t index)
525 {
526 return m_workers[index];
527 }
528 };
529}
Progress indicator for individual worker.
Definition progress.hpp:385
virtual void set(T value)
Set local current progress.
Definition progress.hpp:432
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:456
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:446
virtual void set_range(T start, T end)
Set local extend of the progress indicator.
Definition progress.hpp:415
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:402
Aggregated progress indicator.
Definition progress.hpp:379
progress< T > & operator[](size_t index)
Returns progress indicator for specific worker.
Definition progress.hpp:524
void attach(progress< T > *host)
Attach to a host progress indicator.
Definition progress.hpp:494
progress< T > * detach()
Detach host progress indicator.
Definition progress.hpp:509
aggregate_progress(size_t num_workers, progress< T > *host=nullptr)
Constructs a progress indicator.
Definition progress.hpp:475
Global progress indicator.
Definition progress.hpp:226
void set_section_range(T start, T end)
Set section extend of the progress indicator.
Definition progress.hpp:278
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:328
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:337
virtual void set(T value)
Set local current progress.
Definition progress.hpp:312
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:289
progress< T > * detach()
Detach host progress indicator.
Definition progress.hpp:251
void set_global_range(T start, T end)
Set global extend of the progress indicator.
Definition progress.hpp:264
global_progress(progress< T > *host=nullptr)
Constructs a progress indicator.
Definition progress.hpp:233
void attach(progress< T > *host)
Attach to a host progress indicator.
Definition progress.hpp:241
virtual void set_range(T start, T end)
Set local extend of the progress indicator.
Definition progress.hpp:301
Lazy progress indicator.
Definition progress.hpp:81
lazy_progress(const std::chrono::nanoseconds &timeout=std::chrono::milliseconds(500))
Constructs a lazy progress indicator.
Definition progress.hpp:88
virtual void set(T value)
Set current progress.
Definition progress.hpp:112
virtual void do_set()
Called when progress reporting is due. Should override this method to implement actual progress refre...
Definition progress.hpp:132
virtual void set_range(T start, T end)
Set progress range extent.
Definition progress.hpp:101
Progress indicator switcher.
Definition progress.hpp:354
Progress indicator base class.
Definition progress.hpp:22
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:68
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:29
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:60
virtual void set(T value)
Set current progress.
Definition progress.hpp:50
virtual void set_range(T start, T end)
Set progress range extent.
Definition progress.hpp:40
Timeout progress indicator.
Definition progress.hpp:147
virtual void set_range(T start, T end)
Set progress range extent.
Definition progress.hpp:176
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:164
virtual void set(T value)
Set current progress.
Definition progress.hpp:187
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:207
timeout_progress(const std::chrono::nanoseconds &timeout=std::chrono::seconds(60), progress< T > *host=nullptr)
Constructs a timeout progress indicator.
Definition progress.hpp:154
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:198
Numerical interval.
Definition interval.hpp:18