Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: base/timer.h

Issue 7812036: Update base/timer.h code to pass through Location from call sites. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/system_monitor/system_monitor.cc ('k') | base/timer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // OneShotTimer and RepeatingTimer provide a simple timer API. As the names 5 // OneShotTimer and RepeatingTimer provide a simple timer API. As the names
6 // suggest, OneShotTimer calls you back once after a time delay expires. 6 // suggest, OneShotTimer calls you back once after a time delay expires.
7 // RepeatingTimer on the other hand calls you back periodically with the 7 // RepeatingTimer on the other hand calls you back periodically with the
8 // prescribed time interval. 8 // prescribed time interval.
9 // 9 //
10 // OneShotTimer and RepeatingTimer both cancel the timer when they go out of 10 // OneShotTimer and RepeatingTimer both cancel the timer when they go out of
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 DCHECK(IsRunning()); 80 DCHECK(IsRunning());
81 return delayed_task_->delay_; 81 return delayed_task_->delay_;
82 } 82 }
83 83
84 protected: 84 protected:
85 BaseTimer_Helper() : delayed_task_(NULL) {} 85 BaseTimer_Helper() : delayed_task_(NULL) {}
86 86
87 // We have access to the timer_ member so we can orphan this task. 87 // We have access to the timer_ member so we can orphan this task.
88 class TimerTask : public Task { 88 class TimerTask : public Task {
89 public: 89 public:
90 explicit TimerTask(TimeDelta delay) : timer_(NULL), delay_(delay) { 90 explicit TimerTask(TimeDelta delay,
91 const tracked_objects::Location& posted_from)
92 : timer_(NULL),
93 delay_(delay),
94 posted_from_(posted_from) {
91 } 95 }
92 virtual ~TimerTask() {} 96 virtual ~TimerTask() {}
93 BaseTimer_Helper* timer_; 97 BaseTimer_Helper* timer_;
94 TimeDelta delay_; 98 TimeDelta delay_;
99 tracked_objects::Location posted_from_;
95 }; 100 };
96 101
97 // Used to orphan delayed_task_ so that when it runs it does nothing. 102 // Used to orphan delayed_task_ so that when it runs it does nothing.
98 void OrphanDelayedTask(); 103 void OrphanDelayedTask();
99 104
100 // Used to initiated a new delayed task. This has the side-effect of 105 // Used to initiated a new delayed task. This has the side-effect of
101 // orphaning delayed_task_ if it is non-null. 106 // orphaning delayed_task_ if it is non-null.
102 void InitiateDelayedTask(TimerTask* timer_task); 107 void InitiateDelayedTask(TimerTask* timer_task);
103 108
104 TimerTask* delayed_task_; 109 TimerTask* delayed_task_;
105 110
106 DISALLOW_COPY_AND_ASSIGN(BaseTimer_Helper); 111 DISALLOW_COPY_AND_ASSIGN(BaseTimer_Helper);
107 }; 112 };
108 113
109 //----------------------------------------------------------------------------- 114 //-----------------------------------------------------------------------------
110 // This class is an implementation detail of OneShotTimer and RepeatingTimer. 115 // This class is an implementation detail of OneShotTimer and RepeatingTimer.
111 // Please do not use this class directly. 116 // Please do not use this class directly.
112 template <class Receiver, bool kIsRepeating> 117 template <class Receiver, bool kIsRepeating>
113 class BaseTimer : public BaseTimer_Helper { 118 class BaseTimer : public BaseTimer_Helper {
114 public: 119 public:
115 typedef void (Receiver::*ReceiverMethod)(); 120 typedef void (Receiver::*ReceiverMethod)();
116 121
117 // Call this method to start the timer. It is an error to call this method 122 // Call this method to start the timer. It is an error to call this method
118 // while the timer is already running. 123 // while the timer is already running.
119 void Start(TimeDelta delay, Receiver* receiver, ReceiverMethod method) { 124 void Start(TimeDelta delay,
darin (slow to review) 2011/08/31 21:27:38 consistency nit: it'd be nice to place the Locati
jbates 2011/08/31 23:01:59 Done.
125 Receiver* receiver,
126 ReceiverMethod method,
127 const tracked_objects::Location& posted_from) {
120 DCHECK(!IsRunning()); 128 DCHECK(!IsRunning());
121 InitiateDelayedTask(new TimerTask(delay, receiver, method)); 129 InitiateDelayedTask(new TimerTask(delay, receiver, method, posted_from));
122 } 130 }
123 131
124 // Call this method to stop the timer. It is a no-op if the timer is not 132 // Call this method to stop the timer. It is a no-op if the timer is not
125 // running. 133 // running.
126 void Stop() { 134 void Stop() {
127 OrphanDelayedTask(); 135 OrphanDelayedTask();
128 } 136 }
129 137
130 // Call this method to reset the timer delay of an already running timer. 138 // Call this method to reset the timer delay of an already running timer.
131 void Reset() { 139 void Reset() {
132 DCHECK(IsRunning()); 140 DCHECK(IsRunning());
133 InitiateDelayedTask(static_cast<TimerTask*>(delayed_task_)->Clone()); 141 InitiateDelayedTask(static_cast<TimerTask*>(delayed_task_)->Clone());
134 } 142 }
135 143
136 private: 144 private:
137 typedef BaseTimer<Receiver, kIsRepeating> SelfType; 145 typedef BaseTimer<Receiver, kIsRepeating> SelfType;
138 146
139 class TimerTask : public BaseTimer_Helper::TimerTask { 147 class TimerTask : public BaseTimer_Helper::TimerTask {
140 public: 148 public:
141 TimerTask(TimeDelta delay, Receiver* receiver, ReceiverMethod method) 149 TimerTask(TimeDelta delay,
142 : BaseTimer_Helper::TimerTask(delay), 150 Receiver* receiver,
151 ReceiverMethod method,
152 const tracked_objects::Location& posted_from)
153 : BaseTimer_Helper::TimerTask(delay, posted_from),
143 receiver_(receiver), 154 receiver_(receiver),
144 method_(method) { 155 method_(method) {
145 } 156 }
146 157
147 virtual ~TimerTask() { 158 virtual ~TimerTask() {
148 // This task may be getting cleared because the MessageLoop has been 159 // This task may be getting cleared because the MessageLoop has been
149 // destructed. If so, don't leave the Timer with a dangling pointer 160 // destructed. If so, don't leave the Timer with a dangling pointer
150 // to this now-defunct task. 161 // to this now-defunct task.
151 ClearBaseTimer(); 162 ClearBaseTimer();
152 } 163 }
153 164
154 virtual void Run() { 165 virtual void Run() {
155 if (!timer_) // timer_ is null if we were orphaned. 166 if (!timer_) // timer_ is null if we were orphaned.
156 return; 167 return;
157 if (kIsRepeating) 168 if (kIsRepeating)
158 ResetBaseTimer(); 169 ResetBaseTimer();
159 else 170 else
160 ClearBaseTimer(); 171 ClearBaseTimer();
161 DispatchToMethod(receiver_, method_, Tuple0()); 172 DispatchToMethod(receiver_, method_, Tuple0());
162 } 173 }
163 174
164 TimerTask* Clone() const { 175 TimerTask* Clone() const {
165 return new TimerTask(delay_, receiver_, method_); 176 return new TimerTask(delay_, receiver_, method_, posted_from_);
166 } 177 }
167 178
168 private: 179 private:
169 // Inform the Base that the timer is no longer active. 180 // Inform the Base that the timer is no longer active.
170 void ClearBaseTimer() { 181 void ClearBaseTimer() {
171 if (timer_) { 182 if (timer_) {
172 SelfType* self = static_cast<SelfType*>(timer_); 183 SelfType* self = static_cast<SelfType*>(timer_);
173 // It is possible that the Timer has already been reset, and that this 184 // It is possible that the Timer has already been reset, and that this
174 // Task is old. So, if the Timer points to a different task, assume 185 // Task is old. So, if the Timer points to a different task, assume
175 // that the Timer has already taken care of properly setting the task. 186 // that the Timer has already taken care of properly setting the task.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 // passed since the last call to Reset, the callback is made. Once the callback 225 // passed since the last call to Reset, the callback is made. Once the callback
215 // has been made, it's inactive until Reset is called again. 226 // has been made, it's inactive until Reset is called again.
216 // 227 //
217 // If destroyed, the timeout is canceled and will not occur even if already 228 // If destroyed, the timeout is canceled and will not occur even if already
218 // inflight. 229 // inflight.
219 template <class Receiver> 230 template <class Receiver>
220 class DelayTimer { 231 class DelayTimer {
221 public: 232 public:
222 typedef void (Receiver::*ReceiverMethod)(); 233 typedef void (Receiver::*ReceiverMethod)();
223 234
224 DelayTimer(TimeDelta delay, Receiver* receiver, ReceiverMethod method) 235 DelayTimer(TimeDelta delay,
236 Receiver* receiver,
237 ReceiverMethod method,
238 const tracked_objects::Location& posted_from)
225 : receiver_(receiver), 239 : receiver_(receiver),
226 method_(method), 240 method_(method),
227 delay_(delay) { 241 delay_(delay),
242 posted_from_(posted_from) {
228 } 243 }
229 244
230 void Reset() { 245 void Reset() {
231 DelayFor(delay_); 246 DelayFor(delay_);
232 } 247 }
233 248
234 private: 249 private:
235 void DelayFor(TimeDelta delay) { 250 void DelayFor(TimeDelta delay) {
236 trigger_time_ = TimeTicks::Now() + delay; 251 trigger_time_ = TimeTicks::Now() + delay;
237 252
238 // If we already have a timer that will expire at or before the given delay, 253 // If we already have a timer that will expire at or before the given delay,
239 // then we have nothing more to do now. 254 // then we have nothing more to do now.
240 if (timer_.IsRunning() && timer_.GetCurrentDelay() <= delay) 255 if (timer_.IsRunning() && timer_.GetCurrentDelay() <= delay)
241 return; 256 return;
242 257
243 // The timer isn't running, or will expire too late, so restart it. 258 // The timer isn't running, or will expire too late, so restart it.
244 timer_.Stop(); 259 timer_.Stop();
245 timer_.Start(delay, this, &DelayTimer<Receiver>::Check); 260 timer_.Start(delay, this, &DelayTimer<Receiver>::Check, posted_from_);
246 } 261 }
247 262
248 void Check() { 263 void Check() {
249 if (trigger_time_.is_null()) 264 if (trigger_time_.is_null())
250 return; 265 return;
251 266
252 // If we have not waited long enough, then wait some more. 267 // If we have not waited long enough, then wait some more.
253 const TimeTicks now = TimeTicks::Now(); 268 const TimeTicks now = TimeTicks::Now();
254 if (now < trigger_time_) { 269 if (now < trigger_time_) {
255 DelayFor(trigger_time_ - now); 270 DelayFor(trigger_time_ - now);
256 return; 271 return;
257 } 272 }
258 273
259 (receiver_->*method_)(); 274 (receiver_->*method_)();
260 } 275 }
261 276
262 Receiver *const receiver_; 277 Receiver *const receiver_;
263 const ReceiverMethod method_; 278 const ReceiverMethod method_;
264 const TimeDelta delay_; 279 const TimeDelta delay_;
280 tracked_objects::Location posted_from_;
265 281
266 OneShotTimer<DelayTimer<Receiver> > timer_; 282 OneShotTimer<DelayTimer<Receiver> > timer_;
267 TimeTicks trigger_time_; 283 TimeTicks trigger_time_;
268 }; 284 };
269 285
270 } // namespace base 286 } // namespace base
271 287
272 #endif // BASE_TIMER_H_ 288 #endif // BASE_TIMER_H_
OLDNEW
« no previous file with comments | « base/system_monitor/system_monitor.cc ('k') | base/timer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698