#include <ProgressMonitor.h>
Classes | |
struct | CurrentTaskInfo |
class | Updater |
Public Types | |
using | ChangedCallbackType = Execution::Function< void(const ProgressMonitor &progressMonitor)> |
Public Member Functions | |
ProgressMonitor () | |
nonvirtual void | AddOnProgressCallback (const ChangedCallbackType &progressChangedCallback) |
nonvirtual ProgressRangeType | GetProgress () const |
nonvirtual void | Cancel () |
nonvirtual | operator Updater () |
nonvirtual CurrentTaskInfo | GetCurrentTaskInfo () const |
ProgressMonitor is the basic interface used for progress tracking. Progress tracking both measures progress, and supports the notion of canceling. The reason progress and cancelability are tied together is that its only for 'long lived' tasks one might want to measure the progress of, that one might want to allow canceling.
A progress Monitor owns a list of ChangedCallbackType that can be associated with the ProgressMonitor. These callbacks are each called whenever the progress is known to have changed. Note - this callback uses std::function<>, and the callback runs on an arbitrary thread, not necessarily the one used by the creator of the ProgressMonitor.
A ProgressMonitor also has associated with it an arbitrary number of Updater objects. These are the things that one hands to processes (not OS processes, but long lived procedures or threads) which they then callback to to notify of their progress.
An updater is retrieved from the root ProgressMonitor, and it has 'scope' of 0..1. You can construct sub-updaters by passing a base Updater to the Updater constructor along with a subrange (inside 0..1). That way - if you have sub-procedures, they can report on their progress (0..1) and that is mapped to a subrange of the overall progress.
Note - in order to help debug the progress values, ProgressMonitor strictly enforces some rules. Progress starts at zero, and successive values are non-degreasing. This means the progress bar grows monotonically (though not necessarily smoothly). In order to avoid common floating point bugs with rounding errors, ProgressMonitor employs Math::PinToSpecialPoint ().
Users of ProgressMonitor can call "Cancel" on the ProgressMonitor at any point. This records a cancelation in the Updater object, so that when it calls Updater::SetProgress () - and perhaps in other situations (see thread support below) - the progress will terminate immediately.
ProgressMonitor supports having the underlying long-lived-task happen EITHER in the current thread, or in another thread (the ProgressMonitor and related code is fully threadsafe).
If ProgressMonitor is constructed with an argument Thread (optional) - then attempts to Cancel the ProgressMonitor will also send an Abort() command to the associated thread. This can accelerate - depending less on co-operative checking - to cancel the long-lived progress-monitored process.
Definition at line 105 of file ProgressMonitor.h.
using Stroika::Foundation::Execution::ProgressMonitor::ChangedCallbackType = Execution::Function<void (const ProgressMonitor& progressMonitor)> |
This is for consumers of progress information. Consumers MAY either poll the ProgressMonitor, or may register a callback to be notified of progress.
Callback should be short lived, not hold any locks (because that could make it long lived and create a deadlock).
Also don't throw exceptions in these callbacks. Just record the info needed, and schedule further work in a GUI or whatever (queue it maybe).
\todo revisit 'noexcept' in C++23 - see https://stackoverflow.com/questions/41293025/stdfunction-with-noexcept-in-c17 but for now, cannot declare teh function as noexcept Execution::Function<void (const ProgressMonitor& progressMonitor) noexcept>; \note - though un-enforced by the language, callers should still treat these callbacks as noexcept
Definition at line 128 of file ProgressMonitor.h.
ProgressMonitor::ProgressMonitor | ( | ) |
If work thread is specified (optional) - then thread cancelation will work more efficiently. But this is not required.
Definition at line 16 of file ProgressMonitor.cpp.
void ProgressMonitor::AddOnProgressCallback | ( | const ChangedCallbackType & | progressChangedCallback | ) |
This doesn't need to be used. You can use ProgressMonitor progress monitor just periodically calling GetProgress(). But you may use AddCallback () to receive notifications of progress changes.
Also note, these callbacks may be mutable, and the same instance will be re-used on each progress callback (but it maybe a copy of what is originally passed in ).
Definition at line 41 of file ProgressMonitor.cpp.
ProgressMonitor::ProgressRangeType Stroika::Foundation::Execution::ProgressMonitor::GetProgress | ( | ) | const |
Return the progress value (between 0..1). This values starts at zero, and increases monotonically to 1.0
Definition at line 54 of file ProgressMonitor.inl.
void ProgressMonitor::Cancel | ( | ) |
Cancelability. Anyone can call Cancel () on this progress object. If the progress object is handed to some long-lived task, that task may (at its discretion) - check the progress callback, and cancel its operation by throwing a UserCanceledException.
It is safe to call multiple times (and just may have no additional effect).
If a work thread is associated with the ProgressMonitor, it will be automatically aborted.
Definition at line 47 of file ProgressMonitor.cpp.
Stroika::Foundation::Execution::ProgressMonitor::operator Updater | ( | ) |
Progress isn't updated directly through the ProgressMonitor object. Instead, get an Updater, and call methods on it to update the progress.
Definition at line 65 of file ProgressMonitor.inl.
ProgressMonitor::CurrentTaskInfo Stroika::Foundation::Execution::ProgressMonitor::GetCurrentTaskInfo | ( | ) | const |
Often in displaying progress, its useful to have a notion of what the system is doing, and that is usually displayed far away from where the notion of progress stage resides. This API is usually called by the bit of code performing actions (to set the current task) and by the calling GUI to Get the current task description.
Note also - for reasons of localization - its often helpful to pass back specific information about the task in progress (like file 1 of 4).
Use the 'fExtraData' field of the CurrentTaskInfo.
Definition at line 60 of file ProgressMonitor.inl.