ROSE  0.9.10.29
Progress.h
1 #ifndef Rose_Progress_H
2 #define Rose_Progress_H
3 
4 #include <rosePublicConfig.h> // for ROSE_USE_CMAKE
5 #include <boost/chrono.hpp>
6 #include <boost/thread.hpp>
7 #include <rose_isnan.h>
8 #include <Sawyer/SharedPointer.h>
9 #include <Sawyer/Stopwatch.h>
10 #include <Sawyer/Synchronization.h>
11 #include <string>
12 #include <vector>
13 
14 namespace Rose {
15 
165 public:
168 
178  struct Report {
179  std::string name;
180  double completion;
181  double maximum;
185  : completion(0.0), maximum(1.0) {}
186 
188  explicit Report(double completion, double maximum = 1.0)
189  : completion(completion), maximum(maximum) {}
190 
192  Report(const std::string &name, double completion, double maximum = 1.0)
193  : name(name), completion(completion), maximum(maximum) {}
194  };
195 
196 private:
197  static const size_t TERMINATING = (size_t)(-1);
198 
199  // Synchronized data members
200  mutable SAWYER_THREAD_TRAITS::Mutex mutex_; // protects the following data members
201 #if SAWYER_MULTI_THREADED
202  mutable SAWYER_THREAD_TRAITS::ConditionVariable cv_;// for signaling changes to the latestReport_
203 #endif
204  std::vector<Report> reports_; // report stack, one elemet per nested phase
205  size_t reportNumber_; // sequence number of latestReport_, or TERMINATING
206  Sawyer::Stopwatch reportAge_; // time since last report arrived (or since construction)
207 
208 protected:
209  Progress(): reportNumber_(0) {}
210 
211 public:
213  static Ptr instance();
214 
215 public:
238  void update(double completion, double maximum = 1.0);
239  void update(const Report&);
256  Report push();
257  Report push(double completion, double maximum = 1.0);
258  Report push(const Report&);
275  void pop();
276  void pop(double completion, double maximum = 1.0);
277  void pop(const Report&);
300  void finished();
301  void finished(double completion, double maximum = 1.0);
302  void finished(const Report&);
312  bool isFinished() const;
313 
324  std::pair<Report, double /*seconds*/> reportLatest(const std::string &nameSeparator = ".") const;
325 
347  template<class Functor>
348  bool reportRegularly(boost::chrono::milliseconds interval, Functor f, const std::string &nameSeparator = ".") const {
349  // Makes no sense for single threaded. Does not compile when ROSE is built with CMake
350 #if SAWYER_MULTI_THREADED && !defined(ROSE_USE_CMAKE)
351  while (1) {
352  std::pair<Report, double /*seconds*/> rpt = reportLatest(nameSeparator);
353  if (!f(rpt.first, rpt.second))
354  return false;
355  if (isFinished())
356  return true;
357  boost::this_thread::sleep_for(interval);
358  }
359 #else
360  return false;
361 #endif
362  }
363 
384  template<class Functor>
385  bool reportChanges(boost::chrono::milliseconds limit, Functor f, const std::string &nameSeparator = ".") const {
386 #if SAWYER_MULTI_THREADED && !defined(ROSE_USE_CMAKE) // makes no sense for single threaded. Does not compile with cmake
387  Sawyer::Stopwatch timer;
388  size_t seen = TERMINATING - 1;
389  while (1) {
390  SAWYER_THREAD_TRAITS::UniqueLock lock(mutex_);
391  while (reportNumber_ == seen)
392  cv_.wait(lock);
393  ASSERT_forbid(reports_.empty());
394  Report report = reports_.back();
395  report.name = reportNameNS(nameSeparator);
396  seen = reportNumber_;
397  lock.unlock();
398 
399  if (!f(report))
400  return false;
401  if (TERMINATING == seen)
402  return true;
403  boost::this_thread::sleep_for(limit);
404  }
405 #else
406  return false;
407 #endif
408  }
409 
410 private:
411  std::string reportNameNS(const std::string &nameSeparator) const;
412 };
413 
437  Progress::Ptr progress_;
438  Progress::Report after_;
439 
440 public:
442  ProgressTask(const Progress::Ptr &progress, const std::string &name, double afterCompletion = NAN)
443  : progress_(progress) {
444  if (progress_) {
445  after_ = progress_->push(Progress::Report(name, 0.0));
446  if (!rose_isnan(afterCompletion))
447  after_.completion = afterCompletion;
448  }
449  }
450 
452  ProgressTask(const std::string &name, double afterCompletion = NAN)
453  : progress_(Progress::instance()) {
454  after_ = progress_->push(Progress::Report(name, 0.0));
455  if (!rose_isnan(afterCompletion))
456  after_.completion = afterCompletion;
457  }
458 
461  if (progress_)
462  progress_->pop(after_);
463  }
464 
465 public:
473  return progress_;
474  }
475 
480  void cancel() {
481  progress_ = Progress::Ptr();
482  }
483 };
484 
485 } // namespace
486 
487 #endif
Report(const std::string &name, double completion, double maximum=1.0)
Report with name and completion.
Definition: Progress.h:192
A single progress report.
Definition: Progress.h:178
void cancel()
Cancel all cleanup operations.
Definition: Progress.h:480
Report(double completion, double maximum=1.0)
Report completion with default name.
Definition: Progress.h:188
Progress::Ptr progress() const
Progress object being used.
Definition: Progress.h:472
RAII sub-task progress.
Definition: Progress.h:436
ProgressTask(const std::string &name, double afterCompletion=NAN)
Create progress object for subtask.
Definition: Progress.h:452
std::string name
What is being reported.
Definition: Progress.h:179
ProgressTask(const Progress::Ptr &progress, const std::string &name, double afterCompletion=NAN)
Prepare existing progress object for subtask.
Definition: Progress.h:442
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:184
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:348
void pop()
Pop the top progress phase from the stack.
double completion
Estimated degree of completion.
Definition: Progress.h:180
Base class for reference counted objects.
Definition: SharedObject.h:22
A general, thread-safe way to report progress made on some task.
Definition: Progress.h:164
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:385
~ProgressTask()
Clean up subtask progress.
Definition: Progress.h:460
Sawyer::SharedPointer< Progress > Ptr
Progress objects are reference counted.
Definition: Progress.h:167
double maximum
Maximum value for completion.
Definition: Progress.h:181