progress: add aggregate_progress
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
f3e117afcc
commit
848979950c
@ -7,7 +7,10 @@
|
||||
|
||||
#include "compat.hpp"
|
||||
#include "interval.hpp"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <shared_mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace stdex
|
||||
{
|
||||
@ -69,7 +72,7 @@ namespace stdex
|
||||
};
|
||||
|
||||
///
|
||||
/// Lazy progress indicator base class
|
||||
/// Lazy progress indicator
|
||||
///
|
||||
/// Use with expensive progress reporting to suppress progress indication for a period of time.
|
||||
///
|
||||
@ -135,7 +138,7 @@ namespace stdex
|
||||
};
|
||||
|
||||
///
|
||||
/// Global progress indicator base class
|
||||
/// Global progress indicator
|
||||
///
|
||||
/// Use to report progress of a phase or section as a part of a whole progress.
|
||||
///
|
||||
@ -148,7 +151,7 @@ namespace stdex
|
||||
///
|
||||
/// \param[in] host Host progress indicator
|
||||
///
|
||||
global_progress(_In_opt_ progress<T>* host = NULL) : m_host(host)
|
||||
global_progress(_In_opt_ progress<T>* host = nullptr) : m_host(host)
|
||||
{}
|
||||
|
||||
///
|
||||
@ -169,7 +172,7 @@ namespace stdex
|
||||
progress<T>* detach()
|
||||
{
|
||||
progress<T>* k = m_host;
|
||||
m_host = NULL;
|
||||
m_host = nullptr;
|
||||
return k;
|
||||
}
|
||||
|
||||
@ -267,7 +270,6 @@ namespace stdex
|
||||
///
|
||||
/// Use to inject global_progress indicator inplace of another progress indicator.
|
||||
///
|
||||
|
||||
template <class T>
|
||||
class progress_switcher : public global_progress<T>
|
||||
{
|
||||
@ -287,4 +289,162 @@ namespace stdex
|
||||
protected:
|
||||
progress<T>*& m_host_ref;
|
||||
};
|
||||
|
||||
///
|
||||
/// Aggregated progress indicator
|
||||
///
|
||||
/// Use to report combined progress from multiple workers.
|
||||
///
|
||||
template <class T>
|
||||
class aggregate_progress
|
||||
{
|
||||
protected:
|
||||
///
|
||||
/// Progress indicator for individual worker
|
||||
///
|
||||
class worker_progress : public progress<T>
|
||||
{
|
||||
protected:
|
||||
aggregate_progress<T>& m_host;
|
||||
T m_start, m_end, m_value;
|
||||
|
||||
public:
|
||||
worker_progress(_Inout_ aggregate_progress<T>& host) :
|
||||
m_host(host),
|
||||
m_start(0), m_end(0),
|
||||
m_value(0)
|
||||
{}
|
||||
|
||||
///
|
||||
/// Set progress indicator text
|
||||
///
|
||||
/// \param[in] msg Text to display
|
||||
///
|
||||
virtual void set_text(_In_ const char* msg)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
|
||||
if (m_host.m_host)
|
||||
m_host.m_host->set_text(msg);
|
||||
}
|
||||
|
||||
///
|
||||
/// Set local extend of the progress indicator
|
||||
///
|
||||
/// \param[in] start Minimum value of the progress
|
||||
/// \param[in] end Maximum value of the progress
|
||||
///
|
||||
virtual void set_range(_In_ T start, _In_ T end)
|
||||
{
|
||||
T
|
||||
combined_start = m_host.m_start += start - m_start,
|
||||
combined_end = m_host.m_end += end - m_end;
|
||||
m_start = start;
|
||||
m_end = end;
|
||||
std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
|
||||
if (m_host.m_host)
|
||||
m_host.m_host->set_range(combined_start, combined_end);
|
||||
}
|
||||
|
||||
///
|
||||
/// Set local current progress
|
||||
///
|
||||
/// \param[in] value Current value of the progress. Must be between start and end parameters provided in set_range() call.
|
||||
///
|
||||
virtual void set(_In_ T value)
|
||||
{
|
||||
T combined_value = m_host.m_value += value - m_value;
|
||||
m_value = value;
|
||||
std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
|
||||
if (m_host.m_host)
|
||||
m_host.m_host->set(combined_value);
|
||||
}
|
||||
|
||||
///
|
||||
/// Show or hide progress
|
||||
///
|
||||
/// \param[in] show Shows or hides progress indicator
|
||||
///
|
||||
virtual void show(_In_ bool show = true)
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
|
||||
if (m_host.m_host)
|
||||
m_host.m_host->show(show);
|
||||
}
|
||||
|
||||
///
|
||||
/// Query whether user requested abort
|
||||
///
|
||||
virtual bool cancel()
|
||||
{
|
||||
std::shared_lock<std::shared_mutex> lk(m_host.m_mutex);
|
||||
return m_host.m_host && m_host.m_host->cancel();
|
||||
}
|
||||
};
|
||||
|
||||
progress<T>* m_host;
|
||||
std::atomic<T> m_start, m_end, m_value;
|
||||
std::vector<worker_progress> m_workers;
|
||||
std::shared_mutex m_mutex;
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructs a progress indicator
|
||||
///
|
||||
/// \param[in] num_workers Total number of workers
|
||||
/// \param[in] host Host progress indicator
|
||||
///
|
||||
aggregate_progress(_In_ size_t num_workers, _In_opt_ progress<T>* host = nullptr) :
|
||||
m_host(host),
|
||||
m_start(0), m_end(0),
|
||||
m_value(0)
|
||||
{
|
||||
m_workers.reserve(num_workers);
|
||||
for (size_t i = 0; i < num_workers; ++i)
|
||||
m_workers.push_back(std::move(worker_progress(*this)));
|
||||
if (m_host) {
|
||||
m_host->set_range(m_start, m_end);
|
||||
m_host->set(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Attach to a host progress indicator
|
||||
///
|
||||
/// \param[in] host Host progress indicator
|
||||
///
|
||||
void attach(_In_opt_ progress<T>* host)
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lk(m_mutex);
|
||||
m_host = host;
|
||||
if (m_host) {
|
||||
m_host->set_range(m_start, m_end);
|
||||
m_host->set(m_value);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Detach host progress indicator
|
||||
///
|
||||
/// \returns Old host progress indicator
|
||||
///
|
||||
progress<T>* detach()
|
||||
{
|
||||
std::unique_lock<std::shared_mutex> lk(m_mutex);
|
||||
progress<T>* k = m_host;
|
||||
m_host = nullptr;
|
||||
return k;
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns progress indicator for specific worker
|
||||
///
|
||||
/// \param[in] index Index of worker
|
||||
///
|
||||
/// \returns Reference to specific worker progress indicator
|
||||
///
|
||||
progress<T>& operator[](_In_ size_t index)
|
||||
{
|
||||
return m_workers[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user