1 #ifndef BENCHMARK_THREAD_TIMER_H
2 #define BENCHMARK_THREAD_TIMER_H
3 
4 #include "check.h"
5 #include "timers.h"
6 
7 namespace benchmark {
8 namespace internal {
9 
10 class ThreadTimer {
ThreadTimer(bool measure_process_cpu_time_)11   explicit ThreadTimer(bool measure_process_cpu_time_)
12       : measure_process_cpu_time(measure_process_cpu_time_) {}
13 
14  public:
Create()15   static ThreadTimer Create() {
16     return ThreadTimer(/*measure_process_cpu_time_=*/false);
17   }
CreateProcessCpuTime()18   static ThreadTimer CreateProcessCpuTime() {
19     return ThreadTimer(/*measure_process_cpu_time_=*/true);
20   }
21 
22   // Called by each thread
StartTimer()23   void StartTimer() {
24     running_ = true;
25     start_real_time_ = ChronoClockNow();
26     start_cpu_time_ = ReadCpuTimerOfChoice();
27   }
28 
29   // Called by each thread
StopTimer()30   void StopTimer() {
31     CHECK(running_);
32     running_ = false;
33     real_time_used_ += ChronoClockNow() - start_real_time_;
34     // Floating point error can result in the subtraction producing a negative
35     // time. Guard against that.
36     cpu_time_used_ +=
37         std::max<double>(ReadCpuTimerOfChoice() - start_cpu_time_, 0);
38   }
39 
40   // Called by each thread
SetIterationTime(double seconds)41   void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
42 
running()43   bool running() const { return running_; }
44 
45   // REQUIRES: timer is not running
real_time_used()46   double real_time_used() {
47     CHECK(!running_);
48     return real_time_used_;
49   }
50 
51   // REQUIRES: timer is not running
cpu_time_used()52   double cpu_time_used() {
53     CHECK(!running_);
54     return cpu_time_used_;
55   }
56 
57   // REQUIRES: timer is not running
manual_time_used()58   double manual_time_used() {
59     CHECK(!running_);
60     return manual_time_used_;
61   }
62 
63  private:
ReadCpuTimerOfChoice()64   double ReadCpuTimerOfChoice() const {
65     if (measure_process_cpu_time) return ProcessCPUUsage();
66     return ThreadCPUUsage();
67   }
68 
69   // should the thread, or the process, time be measured?
70   const bool measure_process_cpu_time;
71 
72   bool running_ = false;        // Is the timer running
73   double start_real_time_ = 0;  // If running_
74   double start_cpu_time_ = 0;   // If running_
75 
76   // Accumulated time so far (does not contain current slice if running_)
77   double real_time_used_ = 0;
78   double cpu_time_used_ = 0;
79   // Manually set iteration time. User sets this with SetIterationTime(seconds).
80   double manual_time_used_ = 0;
81 };
82 
83 }  // namespace internal
84 }  // namespace benchmark
85 
86 #endif  // BENCHMARK_THREAD_TIMER_H
87