1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_BASE_PLATFORM_ELAPSED_TIMER_H_
6 #define V8_BASE_PLATFORM_ELAPSED_TIMER_H_
7 
8 #include "src/base/logging.h"
9 #include "src/base/platform/time.h"
10 
11 namespace v8 {
12 namespace base {
13 
14 class ElapsedTimer final {
15  public:
16 #ifdef DEBUG
ElapsedTimer()17   ElapsedTimer() : started_(false) {}
18 #endif
19 
20   // Starts this timer. Once started a timer can be checked with
21   // |Elapsed()| or |HasExpired()|, and may be restarted using |Restart()|.
22   // This method must not be called on an already started timer.
Start()23   void Start() {
24     DCHECK(!IsStarted());
25     start_ticks_ = Now();
26 #ifdef DEBUG
27     started_ = true;
28 #endif
29     DCHECK(IsStarted());
30   }
31 
32   // Stops this timer. Must not be called on a timer that was not
33   // started before.
Stop()34   void Stop() {
35     DCHECK(IsStarted());
36     start_ticks_ = TimeTicks();
37 #ifdef DEBUG
38     started_ = false;
39 #endif
40     DCHECK(!IsStarted());
41   }
42 
43   // Returns |true| if this timer was started previously.
IsStarted()44   bool IsStarted() const {
45     DCHECK(started_ || start_ticks_.IsNull());
46     DCHECK(!started_ || !start_ticks_.IsNull());
47     return !start_ticks_.IsNull();
48   }
49 
50   // Restarts the timer and returns the time elapsed since the previous start.
51   // This method is equivalent to obtaining the elapsed time with |Elapsed()|
52   // and then starting the timer again, but does so in one single operation,
53   // avoiding the need to obtain the clock value twice. It may only be called
54   // on a previously started timer.
Restart()55   TimeDelta Restart() {
56     DCHECK(IsStarted());
57     TimeTicks ticks = Now();
58     TimeDelta elapsed = ticks - start_ticks_;
59     DCHECK(elapsed.InMicroseconds() >= 0);
60     start_ticks_ = ticks;
61     DCHECK(IsStarted());
62     return elapsed;
63   }
64 
65   // Returns the time elapsed since the previous start. This method may only
66   // be called on a previously started timer.
Elapsed()67   TimeDelta Elapsed() const {
68     DCHECK(IsStarted());
69     TimeDelta elapsed = Now() - start_ticks_;
70     DCHECK(elapsed.InMicroseconds() >= 0);
71     return elapsed;
72   }
73 
74   // Returns |true| if the specified |time_delta| has elapsed since the
75   // previous start, or |false| if not. This method may only be called on
76   // a previously started timer.
HasExpired(TimeDelta time_delta)77   bool HasExpired(TimeDelta time_delta) const {
78     DCHECK(IsStarted());
79     return Elapsed() >= time_delta;
80   }
81 
82  private:
Now()83   static V8_INLINE TimeTicks Now() {
84     TimeTicks now = TimeTicks::HighResolutionNow();
85     DCHECK(!now.IsNull());
86     return now;
87   }
88 
89   TimeTicks start_ticks_;
90 #ifdef DEBUG
91   bool started_;
92 #endif
93 };
94 
95 }  // namespace base
96 }  // namespace v8
97 
98 #endif  // V8_BASE_PLATFORM_ELAPSED_TIMER_H_
99