ROSE  0.11.145.0
Progress.h
1 #ifndef ROSE_Progress_H
2 #define ROSE_Progress_H
3 
4 #include <Rose/BasicTypes.h>
5 
6 #include <Rose/Constants.h>
7 
8 #include <boost/chrono.hpp>
9 #include <boost/thread.hpp>
10 #include <rose_isnan.h>
11 #include <Sawyer/Stopwatch.h>
12 #include <Sawyer/Synchronization.h>
13 #include <string>
14 #include <vector>
15 
16 namespace Rose {
17 
167 public:
169  using Ptr = ProgressPtr;
170 
180  struct Report {
181  std::string name;
182  double completion;
183  double maximum;
187  : completion(0.0), maximum(1.0) {}
188 
190  explicit Report(double completion, double maximum = 1.0)
191  : completion(completion), maximum(maximum) {}
192 
194  Report(const std::string &name, double completion, double maximum = 1.0)
195  : name(name), completion(completion), maximum(maximum) {}
196  };
197 
198 private:
199  static const size_t TERMINATING = INVALID_INDEX;
200 
201  // Synchronized data members
202  mutable SAWYER_THREAD_TRAITS::Mutex mutex_; // protects the following data members
203 #if SAWYER_MULTI_THREADED
204  mutable SAWYER_THREAD_TRAITS::ConditionVariable cv_;// for signaling changes to the latestReport_
205 #endif
206  std::vector<Report> reports_; // report stack, one elemet per nested phase
207  size_t reportNumber_; // sequence number of latestReport_, or TERMINATING
208  Sawyer::Stopwatch reportAge_; // time since last report arrived (or since construction)
209 
210 protected:
211  Progress(): reportNumber_(0) {}
212 
213 public:
215  static Ptr instance();
216 
217 public:
240  void update(double completion, double maximum = 1.0);
241  void update(const Report&);
258  Report push();
259  Report push(double completion, double maximum = 1.0);
260  Report push(const Report&);
277  void pop();
278  void pop(double completion, double maximum = 1.0);
279  void pop(const Report&);
302  void finished();
303  void finished(double completion, double maximum = 1.0);
304  void finished(const Report&);
314  bool isFinished() const;
315 
326  std::pair<Report, double /*seconds*/> reportLatest(const std::string &nameSeparator = ".") const;
327 
349  template<class Functor>
350  bool reportRegularly(boost::chrono::milliseconds interval, Functor f, const std::string &nameSeparator = ".") const {
351  // Makes no sense for single threaded. Does not compile when ROSE is built with CMake
352 #if SAWYER_MULTI_THREADED && !defined(ROSE_USE_CMAKE)
353  while (1) {
354  std::pair<Report, double /*seconds*/> rpt = reportLatest(nameSeparator);
355  if (!f(rpt.first, rpt.second))
356  return false;
357  if (isFinished())
358  return true;
359  boost::this_thread::sleep_for(interval);
360  }
361 #else
362  return false;
363 #endif
364  }
365 
386  template<class Functor>
387  bool reportChanges(boost::chrono::milliseconds limit, Functor f, const std::string &nameSeparator = ".") const {
388 #if SAWYER_MULTI_THREADED && !defined(ROSE_USE_CMAKE) // makes no sense for single threaded. Does not compile with cmake
389  Sawyer::Stopwatch timer;
390  size_t seen = TERMINATING - 1;
391  while (1) {
392  SAWYER_THREAD_TRAITS::UniqueLock lock(mutex_);
393  while (reportNumber_ == seen)
394  cv_.wait(lock);
395  ASSERT_forbid(reports_.empty());
396  Report report = reports_.back();
397  report.name = reportNameNS(nameSeparator);
398  seen = reportNumber_;
399  lock.unlock();
400 
401  if (!f(report))
402  return false;
403  if (TERMINATING == seen)
404  return true;
405  boost::this_thread::sleep_for(limit);
406  }
407 #else
408  return false;
409 #endif
410  }
411 
412 private:
413  std::string reportNameNS(const std::string &nameSeparator) const;
414 };
415 
439  Progress::Ptr progress_;
440  Progress::Report after_;
441 
442 public:
444  ProgressTask(const Progress::Ptr &progress, const std::string &name, double afterCompletion = NAN)
445  : progress_(progress) {
446  if (progress_) {
447  after_ = progress_->push(Progress::Report(name, 0.0));
448  if (!rose_isnan(afterCompletion))
449  after_.completion = afterCompletion;
450  }
451  }
452 
454  ProgressTask(const std::string &name, double afterCompletion = NAN)
455  : progress_(Progress::instance()) {
456  after_ = progress_->push(Progress::Report(name, 0.0));
457  if (!rose_isnan(afterCompletion))
458  after_.completion = afterCompletion;
459  }
460 
463  if (progress_)
464  progress_->pop(after_);
465  }
466 
467 public:
475  return progress_;
476  }
477 
482  void cancel() {
483  progress_ = Progress::Ptr();
484  }
485 };
486 
487 } // namespace
488 
489 #endif
Report(const std::string &name, double completion, double maximum=1.0)
Report with name and completion.
Definition: Progress.h:194
A single progress report.
Definition: Progress.h:180
void cancel()
Cancel all cleanup operations.
Definition: Progress.h:482
Report(double completion, double maximum=1.0)
Report completion with default name.
Definition: Progress.h:190
Progress::Ptr progress() const
Progress object being used.
Definition: Progress.h:474
RAII sub-task progress.
Definition: Progress.h:438
ProgressTask(const std::string &name, double afterCompletion=NAN)
Create progress object for subtask.
Definition: Progress.h:454
std::string name
What is being reported.
Definition: Progress.h:181
ProgressTask(const Progress::Ptr &progress, const std::string &name, double afterCompletion=NAN)
Prepare existing progress object for subtask.
Definition: Progress.h:444
Main namespace for the ROSE library.
void update(double completion, double maximum=1.0)
Make a progress report.
static Ptr instance()
Factory to create a new instance of this class.
std::pair< Report, double > reportLatest(const std::string &nameSeparator=".") const
Latest report and its age in seconds.
bool isFinished() const
Predicate indicating whether the task is finished.
Simple elapsed time.
Definition: Stopwatch.h:41
void finished()
Indicate that the task is complete.
Report()
Initial progress report.
Definition: Progress.h:186
Report push()
Push a new progress phase onto the stack.
bool reportRegularly(boost::chrono::milliseconds interval, Functor f, const std::string &nameSeparator=".") const
Invoke the specified function at regular intervals.
Definition: Progress.h:350
void pop()
Pop the top progress phase from the stack.
double completion
Estimated degree of completion.
Definition: Progress.h:182
Base class for reference counted objects.
Definition: SharedObject.h:64
A general, thread-safe way to report progress made on some task.
Definition: Progress.h:166
bool reportChanges(boost::chrono::milliseconds limit, Functor f, const std::string &nameSeparator=".") const
Invoke the specified function each time the progress changes.
Definition: Progress.h:387
~ProgressTask()
Clean up subtask progress.
Definition: Progress.h:462
const size_t INVALID_INDEX(static_cast< size_t >(-1))
Invalid array index.
ProgressPtr Ptr
Progress objects are reference counted.
Definition: Progress.h:169
double maximum
Maximum value for completion.
Definition: Progress.h:183