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