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: ElapsedTimer()16 ElapsedTimer() : start_ticks_() {} 17 18 // Starts this timer. Once started a timer can be checked with 19 // |Elapsed()| or |HasExpired()|, and may be restarted using |Restart()|. 20 // This method must not be called on an already started timer. Start()21 void Start() { Start(Now()); } 22 Start(TimeTicks now)23 void Start(TimeTicks now) { 24 DCHECK(!now.IsNull()); 25 DCHECK(!IsStarted()); 26 set_start_ticks(now); 27 #ifdef DEBUG 28 started_ = true; 29 #endif 30 DCHECK(IsStarted()); 31 } 32 33 // Stops this timer. Must not be called on a timer that was not 34 // started before. Stop()35 void Stop() { 36 DCHECK(IsStarted()); 37 set_start_ticks(TimeTicks()); 38 #ifdef DEBUG 39 started_ = false; 40 #endif 41 DCHECK(!IsStarted()); 42 } 43 44 // Returns |true| if this timer was started previously. IsStarted()45 bool IsStarted() const { 46 DCHECK(!paused_); 47 DCHECK_NE(started_, start_ticks_.IsNull()); 48 return !start_ticks_.IsNull(); 49 } 50 51 #if DEBUG IsPaused()52 bool IsPaused() const { return paused_; } 53 #endif 54 55 // Restarts the timer and returns the time elapsed since the previous start. 56 // This method is equivalent to obtaining the elapsed time with |Elapsed()| 57 // and then starting the timer again, but does so in one single operation, 58 // avoiding the need to obtain the clock value twice. It may only be called 59 // on a previously started timer. Restart()60 TimeDelta Restart() { return Restart(Now()); } 61 Restart(TimeTicks now)62 TimeDelta Restart(TimeTicks now) { 63 DCHECK(!now.IsNull()); 64 DCHECK(IsStarted()); 65 TimeDelta elapsed = now - start_ticks_; 66 DCHECK_GE(elapsed.InMicroseconds(), 0); 67 set_start_ticks(now); 68 DCHECK(IsStarted()); 69 return elapsed; 70 } 71 Pause()72 void Pause() { Pause(Now()); } 73 Pause(TimeTicks now)74 void Pause(TimeTicks now) { 75 TimeDelta elapsed = Elapsed(now); 76 DCHECK(IsStarted()); 77 #ifdef DEBUG 78 paused_ = true; 79 #endif 80 set_paused_elapsed(elapsed); 81 } 82 Resume()83 void Resume() { Resume(Now()); } 84 Resume(TimeTicks now)85 void Resume(TimeTicks now) { 86 DCHECK(!now.IsNull()); 87 DCHECK(started_); 88 DCHECK(paused_); 89 TimeDelta elapsed = paused_elapsed(); 90 #ifdef DEBUG 91 paused_ = false; 92 #endif 93 set_start_ticks(now - elapsed); 94 DCHECK(IsStarted()); 95 } 96 97 // Returns the time elapsed since the previous start. This method may only 98 // be called on a previously started timer. Elapsed()99 TimeDelta Elapsed() const { return Elapsed(Now()); } 100 Elapsed(TimeTicks now)101 TimeDelta Elapsed(TimeTicks now) const { 102 DCHECK(!now.IsNull()); 103 DCHECK(IsStarted()); 104 TimeDelta elapsed = now - start_ticks(); 105 DCHECK_GE(elapsed.InMicroseconds(), 0); 106 return elapsed; 107 } 108 109 // Returns |true| if the specified |time_delta| has elapsed since the 110 // previous start, or |false| if not. This method may only be called on 111 // a previously started timer. HasExpired(TimeDelta time_delta)112 bool HasExpired(TimeDelta time_delta) const { 113 DCHECK(IsStarted()); 114 return Elapsed() >= time_delta; 115 } 116 117 private: Now()118 static V8_INLINE TimeTicks Now() { 119 TimeTicks now = TimeTicks::Now(); 120 DCHECK(!now.IsNull()); 121 return now; 122 } 123 paused_elapsed()124 TimeDelta paused_elapsed() { 125 // Only used started_ since paused_elapsed_ can be 0. 126 DCHECK(paused_); 127 DCHECK(started_); 128 return paused_elapsed_; 129 } 130 set_paused_elapsed(TimeDelta delta)131 void set_paused_elapsed(TimeDelta delta) { 132 DCHECK(paused_); 133 DCHECK(started_); 134 paused_elapsed_ = delta; 135 } 136 start_ticks()137 TimeTicks start_ticks() const { 138 DCHECK(!paused_); 139 return start_ticks_; 140 } set_start_ticks(TimeTicks start_ticks)141 void set_start_ticks(TimeTicks start_ticks) { 142 DCHECK(!paused_); 143 start_ticks_ = start_ticks; 144 } 145 146 union { 147 TimeTicks start_ticks_; 148 TimeDelta paused_elapsed_; 149 }; 150 #ifdef DEBUG 151 bool started_ = false; 152 bool paused_ = false; 153 #endif 154 }; 155 156 } // namespace base 157 } // namespace v8 158 159 #endif // V8_BASE_PLATFORM_ELAPSED_TIMER_H_ 160