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
15 namespace stdex
16{
20 template <class T>
21 class progress
22 {
23 public:
24 virtual ~progress() {}
25
31 virtual void set_text(_In_z_ const char* msg)
32 {
33 _Unreferenced_(msg);
34 }
35
42 virtual void set_range(_In_ T start, _In_ T end)
43 {
44 start; end;
45 }
46
52 virtual void set(_In_ T value)
53 {
54 value;
55 }
56
62 virtual void show(_In_ bool show = true)
63 {
64 _Unreferenced_(show);
65 }
66
70 virtual bool cancel()
71 {
72 return false;
73 }
74 };
75
81 template <class T>
82 class lazy_progress : public progress<T>
83 {
84 public:
90 lazy_progress(_In_ const std::chrono::nanoseconds& timeout = std::chrono::milliseconds(500)) :
91 m_timeout(timeout),
92 m_start(0),
93 m_end(0),
94 m_value(-1)
95 {}
96
103 virtual void set_range(_In_ T start, _In_ T end)
104 {
105 m_start = start;
106 m_end = end;
107 }
108
114 virtual void set(_In_ T value)
115 {
116 if (value == m_start || value == m_end)
117 m_last = std::chrono::high_resolution_clock::now();
118 else if (value == m_value)
119 return;
120 else {
121 auto now = std::chrono::high_resolution_clock::now();
122 if (now - m_last < m_timeout)
123 return;
124 m_last = now;
125 }
126 m_value = value;
127 do_set();
128 }
129
130 protected:
134 virtual void do_set() {}
135
136 protected:
137 std::chrono::nanoseconds m_timeout;
138 std::chrono::system_clock::time_point m_last;
139 T m_start, m_end, m_value;
140 };
141
147 template <class T>
148 class timeout_progress : public progress<T>
149 {
150 public:
156 timeout_progress(_In_ const std::chrono::nanoseconds& timeout = std::chrono::seconds(60), _In_opt_ progress<T>* host = nullptr) :
157 m_host(host),
158 m_deadline(std::chrono::high_resolution_clock::now() + timeout)
159 {}
160
166 virtual void set_text(_In_z_ const char* msg)
167 {
168 if (m_host)
169 m_host->set_text(msg);
170 }
171
178 virtual void set_range(_In_ T start, _In_ T end)
179 {
180 if (m_host)
181 m_host->set_range(start, end);
182 }
183
189 virtual void set(_In_ T value)
190 {
191 if (m_host)
192 m_host->set(value);
193 }
194
200 virtual void show(_In_ bool show = true)
201 {
202 if (m_host)
203 m_host->show(show);
204 }
205
209 virtual bool cancel()
210 {
211 return
212 (m_host && m_host->cancel()) ||
213 m_deadline < std::chrono::high_resolution_clock::now();
214 }
215
216 protected:
217 progress<T>* m_host;
218 std::chrono::high_resolution_clock::time_point m_deadline;
219 };
220
226 template <class T>
227 class global_progress : public progress<T>
228 {
229 public:
235 global_progress(_In_opt_ progress<T>* host = nullptr) : m_host(host)
236 {}
237
243 void attach(_In_opt_ progress<T>* host)
244 {
245 m_host = host;
246 }
247
253 progress<T>* detach()
254 {
255 progress<T>* k = m_host;
256 m_host = nullptr;
257 return k;
258 }
259
266 void set_global_range(_In_ T start, _In_ T end)
267 {
268 m_global.start = start;
269 m_global.end = end;
270 if (m_host)
271 m_host->set_range(m_global.start, m_global.end);
272 }
273
280 void set_section_range(_In_ T start, _In_ T end)
281 {
282 m_section.start = start;
283 m_section.end = end;
284 }
285
291 virtual void set_text(_In_ const char* msg)
292 {
293 if (m_host)
294 m_host->set_text(msg);
295 }
296
303 virtual void set_range(_In_ T start, _In_ T end)
304 {
305 m_local.start = start;
306 m_local.end = end;
307 }
308
314 virtual void set(_In_ T value)
315 {
316 if (m_host) {
317 T size = m_local.size();
318 if (size != 0) {
319 // TODO: Implement with muldiv.
320 m_host->set(((value - m_local.start) * m_section.size() / size) + m_section.start);
321 }
322 }
323 }
324
330 virtual void show(_In_ bool show = true)
331 {
332 if (m_host)
333 m_host->show(show);
334 }
335
339 virtual bool cancel()
340 {
341 return m_host && m_host->cancel();
342 }
343
344 protected:
345 progress<T>* m_host;
346 interval<T> m_local, m_global, m_section;
347 };
348
354 template <class T>
355 class progress_switcher : public global_progress<T>
356 {
357 public:
358 progress_switcher(progress<T>*& host) :
359 global_progress<T>(host),
360 m_host_ref(host)
361 {
362 m_host_ref = this;
363 }
364
365 ~progress_switcher()
366 {
367 m_host_ref = this->detach();
368 }
369
370 protected:
371 progress<T>*& m_host_ref;
372 };
373
379 template <class T>
380 class aggregate_progress
381 {
382 protected:
386 class worker_progress : public progress<T>
387 {
388 protected:
389 aggregate_progress<T>& m_host;
390 T m_start, m_end, m_value;
391
392 public:
393 worker_progress(_Inout_ aggregate_progress<T>& host) :
394 m_host(host),
395 m_start(0), m_end(0),
396 m_value(0)
397 {}
398
404 virtual void set_text(_In_ const char* msg)
405 {
406 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
407 if (m_host.m_host)
408 m_host.m_host->set_text(msg);
409 }
410
417 virtual void set_range(_In_ T start, _In_ T end)
418 {
419 T
420 combined_start = m_host.m_start += start - m_start,
421 combined_end = m_host.m_end += end - m_end;
422 m_start = start;
423 m_end = end;
424 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
425 if (m_host.m_host)
426 m_host.m_host->set_range(combined_start, combined_end);
427 }
428
434 virtual void set(_In_ T value)
435 {
436 T combined_value = m_host.m_value += value - m_value;
437 m_value = value;
438 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
439 if (m_host.m_host)
440 m_host.m_host->set(combined_value);
441 }
442
448 virtual void show(_In_ bool show = true)
449 {
450 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
451 if (m_host.m_host)
452 m_host.m_host->show(show);
453 }
454
458 virtual bool cancel()
459 {
460 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
461 return m_host.m_host && m_host.m_host->cancel();
462 }
463 };
464
465 progress<T>* m_host;
466 std::atomic<T> m_start, m_end, m_value;
467 std::vector<worker_progress> m_workers;
468 std::shared_mutex m_mutex;
469
470 public:
477 aggregate_progress(_In_ size_t num_workers, _In_opt_ progress<T>* host = nullptr) :
478 m_host(host),
479 m_start(0), m_end(0),
480 m_value(0)
481 {
482 m_workers.reserve(num_workers);
483 for (size_t i = 0; i < num_workers; ++i)
484 m_workers.push_back(std::move(worker_progress(*this)));
485 if (m_host) {
486 m_host->set_range(m_start, m_end);
487 m_host->set(m_value);
488 }
489 }
490
496 void attach(_In_opt_ progress<T>* host)
497 {
498 std::unique_lock<std::shared_mutex> lk(m_mutex);
499 m_host = host;
500 if (m_host) {
501 m_host->set_range(m_start, m_end);
502 m_host->set(m_value);
503 }
504 }
505
511 progress<T>* detach()
512 {
513 std::unique_lock<std::shared_mutex> lk(m_mutex);
514 progress<T>* k = m_host;
515 m_host = nullptr;
516 return k;
517 }
518
526 progress<T>& operator[](_In_ size_t index)
527 {
528 return m_workers[index];
529 }
530 };
531}
stdex::aggregate_progress::worker_progress
Progress indicator for individual worker.
Definition progress.hpp:387
stdex::aggregate_progress::worker_progress::set
virtual void set(T value)
Set local current progress.
Definition progress.hpp:434
stdex::aggregate_progress::worker_progress::cancel
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:458
stdex::aggregate_progress::worker_progress::show
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:448
stdex::aggregate_progress::worker_progress::set_range
virtual void set_range(T start, T end)
Set local extend of the progress indicator.
Definition progress.hpp:417
stdex::aggregate_progress::worker_progress::set_text
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:404
stdex::aggregate_progress
Aggregated progress indicator.
Definition progress.hpp:381
stdex::aggregate_progress::operator[]
progress< T > & operator[](size_t index)
Returns progress indicator for specific worker.
Definition progress.hpp:526
stdex::aggregate_progress::attach
void attach(progress< T > *host)
Attach to a host progress indicator.
Definition progress.hpp:496
stdex::aggregate_progress::detach
progress< T > * detach()
Detach host progress indicator.
Definition progress.hpp:511
stdex::aggregate_progress::aggregate_progress
aggregate_progress(size_t num_workers, progress< T > *host=nullptr)
Constructs a progress indicator.
Definition progress.hpp:477
stdex::global_progress
Global progress indicator.
Definition progress.hpp:228
stdex::global_progress::set_section_range
void set_section_range(T start, T end)
Set section extend of the progress indicator.
Definition progress.hpp:280
stdex::global_progress::show
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:330
stdex::global_progress::cancel
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:339
stdex::global_progress::set
virtual void set(T value)
Set local current progress.
Definition progress.hpp:314
stdex::global_progress::set_text
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:291
stdex::global_progress::detach
progress< T > * detach()
Detach host progress indicator.
Definition progress.hpp:253
stdex::global_progress::set_global_range
void set_global_range(T start, T end)
Set global extend of the progress indicator.
Definition progress.hpp:266
stdex::global_progress::global_progress
global_progress(progress< T > *host=nullptr)
Constructs a progress indicator.
Definition progress.hpp:235
stdex::global_progress::attach
void attach(progress< T > *host)
Attach to a host progress indicator.
Definition progress.hpp:243
stdex::global_progress::set_range
virtual void set_range(T start, T end)
Set local extend of the progress indicator.
Definition progress.hpp:303
stdex::lazy_progress
Lazy progress indicator.
Definition progress.hpp:83
stdex::lazy_progress::lazy_progress
lazy_progress(const std::chrono::nanoseconds &timeout=std::chrono::milliseconds(500))
Constructs a lazy progress indicator.
Definition progress.hpp:90
stdex::lazy_progress::set
virtual void set(T value)
Set current progress.
Definition progress.hpp:114
stdex::lazy_progress::do_set
virtual void do_set()
Called when progress reporting is due. Should override this method to implement actual progress refre...
Definition progress.hpp:134
stdex::lazy_progress::set_range
virtual void set_range(T start, T end)
Set progress range extent.
Definition progress.hpp:103
stdex::progress_switcher
Progress indicator switcher.
Definition progress.hpp:356
stdex::progress
Progress indicator base class.
Definition progress.hpp:22
stdex::progress::cancel
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:70
stdex::progress::set_text
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:31
stdex::progress::show
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:62
stdex::progress::set
virtual void set(T value)
Set current progress.
Definition progress.hpp:52
stdex::progress::set_range
virtual void set_range(T start, T end)
Set progress range extent.
Definition progress.hpp:42
stdex::timeout_progress
Timeout progress indicator.
Definition progress.hpp:149
stdex::timeout_progress::set_range
virtual void set_range(T start, T end)
Set progress range extent.
Definition progress.hpp:178
stdex::timeout_progress::set_text
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:166
stdex::timeout_progress::set
virtual void set(T value)
Set current progress.
Definition progress.hpp:189
stdex::timeout_progress::cancel
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:209
stdex::timeout_progress::timeout_progress
timeout_progress(const std::chrono::nanoseconds &timeout=std::chrono::seconds(60), progress< T > *host=nullptr)
Constructs a timeout progress indicator.
Definition progress.hpp:156
stdex::timeout_progress::show
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:200
stdex::interval
Numerical interval.
Definition interval.hpp:18