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::nanoseconds(500000)) :
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 global_progress : public progress<T>
147 {
148 public:
154 global_progress(_In_opt_ progress<T>* host = nullptr) : m_host(host)
155 {}
156
162 void attach(_In_opt_ progress<T>* host)
163 {
164 m_host = host;
165 }
166
173 {
174 progress<T>* k = m_host;
175 m_host = nullptr;
176 return k;
177 }
178
185 void set_global_range(_In_ T start, _In_ T end)
186 {
187 m_global.start = start;
188 m_global.end = end;
189 if (m_host)
190 m_host->set_range(m_global.start, m_global.end);
191 }
192
199 void set_section_range(_In_ T start, _In_ T end)
200 {
201 m_section.start = start;
202 m_section.end = end;
203 }
204
210 virtual void set_text(_In_ const char* msg)
211 {
212 if (m_host)
213 m_host->set_text(msg);
214 }
215
222 virtual void set_range(_In_ T start, _In_ T end)
223 {
224 m_local.start = start;
225 m_local.end = end;
226 }
227
233 virtual void set(_In_ T value)
234 {
235 if (m_host) {
236 T size = m_local.size();
237 if (size != 0) {
238 // TODO: Implement with muldiv.
239 m_host->set(((value - m_local.start) * m_section.size() / size) + m_section.start);
240 }
241 }
242 }
243
249 virtual void show(_In_ bool show = true)
250 {
251 if (m_host)
252 m_host->show(show);
253 }
254
258 virtual bool cancel()
259 {
260 return m_host && m_host->cancel();
261 }
262
263 protected:
264 progress<T>* m_host;
265 interval<T> m_local, m_global, m_section;
266 };
267
273 template <class T>
275 {
276 public:
278 global_progress<T>(host),
279 m_host_ref(host)
280 {
281 m_host_ref = this;
282 }
283
285 {
286 m_host_ref = this->detach();
287 }
288
289 protected:
290 progress<T>*& m_host_ref;
291 };
292
298 template <class T>
300 {
301 protected:
305 class worker_progress : public progress<T>
306 {
307 protected:
308 aggregate_progress<T>& m_host;
309 T m_start, m_end, m_value;
310
311 public:
313 m_host(host),
314 m_start(0), m_end(0),
315 m_value(0)
316 {}
317
323 virtual void set_text(_In_ const char* msg)
324 {
325 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
326 if (m_host.m_host)
327 m_host.m_host->set_text(msg);
328 }
329
336 virtual void set_range(_In_ T start, _In_ T end)
337 {
338 T
339 combined_start = m_host.m_start += start - m_start,
340 combined_end = m_host.m_end += end - m_end;
341 m_start = start;
342 m_end = end;
343 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
344 if (m_host.m_host)
345 m_host.m_host->set_range(combined_start, combined_end);
346 }
347
353 virtual void set(_In_ T value)
354 {
355 T combined_value = m_host.m_value += value - m_value;
356 m_value = value;
357 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
358 if (m_host.m_host)
359 m_host.m_host->set(combined_value);
360 }
361
367 virtual void show(_In_ bool show = true)
368 {
369 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
370 if (m_host.m_host)
371 m_host.m_host->show(show);
372 }
373
377 virtual bool cancel()
378 {
379 std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
380 return m_host.m_host && m_host.m_host->cancel();
381 }
382 };
383
384 progress<T>* m_host;
385 std::atomic<T> m_start, m_end, m_value;
386 std::vector<worker_progress> m_workers;
387 std::shared_mutex m_mutex;
388
389 public:
396 aggregate_progress(_In_ size_t num_workers, _In_opt_ progress<T>* host = nullptr) :
397 m_host(host),
398 m_start(0), m_end(0),
399 m_value(0)
400 {
401 m_workers.reserve(num_workers);
402 for (size_t i = 0; i < num_workers; ++i)
403 m_workers.push_back(std::move(worker_progress(*this)));
404 if (m_host) {
405 m_host->set_range(m_start, m_end);
406 m_host->set(m_value);
407 }
408 }
409
415 void attach(_In_opt_ progress<T>* host)
416 {
417 std::unique_lock<std::shared_mutex> lk(m_mutex);
418 m_host = host;
419 if (m_host) {
420 m_host->set_range(m_start, m_end);
421 m_host->set(m_value);
422 }
423 }
424
431 {
432 std::unique_lock<std::shared_mutex> lk(m_mutex);
433 progress<T>* k = m_host;
434 m_host = nullptr;
435 return k;
436 }
437
445 progress<T>& operator[](_In_ size_t index)
446 {
447 return m_workers[index];
448 }
449 };
450}
Progress indicator for individual worker.
Definition progress.hpp:306
virtual void set(T value)
Set local current progress.
Definition progress.hpp:353
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:377
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:367
virtual void set_range(T start, T end)
Set local extend of the progress indicator.
Definition progress.hpp:336
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:323
Aggregated progress indicator.
Definition progress.hpp:300
progress< T > & operator[](size_t index)
Returns progress indicator for specific worker.
Definition progress.hpp:445
void attach(progress< T > *host)
Attach to a host progress indicator.
Definition progress.hpp:415
progress< T > * detach()
Detach host progress indicator.
Definition progress.hpp:430
aggregate_progress(size_t num_workers, progress< T > *host=nullptr)
Constructs a progress indicator.
Definition progress.hpp:396
Global progress indicator.
Definition progress.hpp:147
void set_section_range(T start, T end)
Set section extend of the progress indicator.
Definition progress.hpp:199
virtual void show(bool show=true)
Show or hide progress.
Definition progress.hpp:249
virtual bool cancel()
Query whether user requested abort.
Definition progress.hpp:258
virtual void set(T value)
Set local current progress.
Definition progress.hpp:233
virtual void set_text(const char *msg)
Set progress indicator text.
Definition progress.hpp:210
progress< T > * detach()
Detach host progress indicator.
Definition progress.hpp:172
void set_global_range(T start, T end)
Set global extend of the progress indicator.
Definition progress.hpp:185
global_progress(progress< T > *host=nullptr)
Constructs a progress indicator.
Definition progress.hpp:154
void attach(progress< T > *host)
Attach to a host progress indicator.
Definition progress.hpp:162
virtual void set_range(T start, T end)
Set local extend of the progress indicator.
Definition progress.hpp:222
Lazy progress indicator.
Definition progress.hpp:81
virtual void set(T value)
Set current progress.
Definition progress.hpp:112
lazy_progress(const std::chrono::nanoseconds &timeout=std::chrono::nanoseconds(500000))
Constructs a lazy progress indicator.
Definition progress.hpp:88
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:275
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
Numerical interval.
Definition interval.hpp:18