blob: 88958d4ad65a3abef8976483d758014e097b8b82 [file] [log] [blame]
[email protected]89bf27e2013-06-27 18:04:561// Copyright (c) 2012 The Chromium 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// OneShotTimer and RepeatingTimer provide a simple timer API. As the names
6// suggest, OneShotTimer calls you back once after a time delay expires.
7// RepeatingTimer on the other hand calls you back periodically with the
8// prescribed time interval.
9//
10// OneShotTimer and RepeatingTimer both cancel the timer when they go out of
11// scope, which makes it easy to ensure that you do not get called when your
12// object has gone out of scope. Just instantiate a OneShotTimer or
13// RepeatingTimer as a member variable of the class for which you wish to
14// receive timer events.
15//
16// Sample RepeatingTimer usage:
17//
18// class MyClass {
19// public:
20// void StartDoingStuff() {
21// timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1),
22// this, &MyClass::DoStuff);
23// }
24// void StopDoingStuff() {
25// timer_.Stop();
26// }
27// private:
28// void DoStuff() {
29// // This method is called every second to do stuff.
30// ...
31// }
danakj8c3eb802015-09-24 07:53:0032// base::RepeatingTimer timer_;
[email protected]89bf27e2013-06-27 18:04:5633// };
34//
35// Both OneShotTimer and RepeatingTimer also support a Reset method, which
36// allows you to easily defer the timer event until the timer delay passes once
37// again. So, in the above example, if 0.5 seconds have already passed,
gab4e844bb2017-06-01 16:23:3638// calling Reset on |timer_| would postpone DoStuff by another 1 second. In
[email protected]89bf27e2013-06-27 18:04:5639// other words, Reset is shorthand for calling Stop and then Start again with
40// the same arguments.
41//
gab4e844bb2017-06-01 16:23:3642// These APIs are not thread safe. All methods must be called from the same
43// sequence (not necessarily the construction sequence), except for the
44// destructor and SetTaskRunner() which may be called from any sequence when the
45// timer is not running (i.e. when Start() has never been called or Stop() has
46// been called since the last Start()). By default, the scheduled tasks will be
47// run on the same sequence that the Timer was *started on*, but this can be
48// changed *prior* to Start() via SetTaskRunner().
[email protected]89bf27e2013-06-27 18:04:5649
50#ifndef BASE_TIMER_TIMER_H_
51#define BASE_TIMER_TIMER_H_
52
53// IMPORTANT: If you change timer code, make sure that all tests (including
54// disabled ones) from timer_unittests.cc pass locally. Some are disabled
55// because they're flaky on the buildbot, but when you run them locally you
56// should be able to tell the difference.
57
jameswest6e0c8d22016-11-15 05:19:5458#include <memory>
59
[email protected]89bf27e2013-06-27 18:04:5660#include "base/base_export.h"
61#include "base/bind.h"
62#include "base/bind_helpers.h"
63#include "base/callback.h"
64#include "base/location.h"
avi9b6f42932015-12-26 22:15:1465#include "base/macros.h"
gab4e844bb2017-06-01 16:23:3666#include "base/sequence_checker_impl.h"
67#include "base/sequenced_task_runner.h"
[email protected]89bf27e2013-06-27 18:04:5668#include "base/time/time.h"
69
70namespace base {
71
72class BaseTimerTaskInternal;
jameswest6e0c8d22016-11-15 05:19:5473class TickClock;
[email protected]89bf27e2013-06-27 18:04:5674
gab4e844bb2017-06-01 16:23:3675// TODO(gab): Removing this fwd-decl causes IWYU failures in other headers,
76// remove it in a follow- up CL.
77class SingleThreadTaskRunner;
78
[email protected]89bf27e2013-06-27 18:04:5679//-----------------------------------------------------------------------------
gab4e844bb2017-06-01 16:23:3680// This class wraps TaskRunner::PostDelayedTask to manage delayed and repeating
81// tasks. See meta comment above for thread-safety requirements.
[email protected]89bf27e2013-06-27 18:04:5682//
83class BASE_EXPORT Timer {
84 public:
gab4e844bb2017-06-01 16:23:3685 // Construct a timer in repeating or one-shot mode. Start must be called later
86 // to set task info. |retain_user_task| determines whether the user_task is
87 // retained or reset when it runs or stops. If |tick_clock| is provided, it is
88 // used instead of TimeTicks::Now() to get TimeTicks when scheduling tasks.
[email protected]89bf27e2013-06-27 18:04:5689 Timer(bool retain_user_task, bool is_repeating);
jameswest6e0c8d22016-11-15 05:19:5490 Timer(bool retain_user_task, bool is_repeating, TickClock* tick_clock);
[email protected]89bf27e2013-06-27 18:04:5691
jameswest6e0c8d22016-11-15 05:19:5492 // Construct a timer with retained task info. If |tick_clock| is provided, it
93 // is used instead of TimeTicks::Now() to get TimeTicks when scheduling tasks.
[email protected]89bf27e2013-06-27 18:04:5694 Timer(const tracked_objects::Location& posted_from,
95 TimeDelta delay,
96 const base::Closure& user_task,
97 bool is_repeating);
jameswest6e0c8d22016-11-15 05:19:5498 Timer(const tracked_objects::Location& posted_from,
99 TimeDelta delay,
100 const base::Closure& user_task,
101 bool is_repeating,
102 TickClock* tick_clock);
[email protected]89bf27e2013-06-27 18:04:56103
104 virtual ~Timer();
105
106 // Returns true if the timer is running (i.e., not stopped).
[email protected]9df013b2014-03-13 22:04:39107 virtual bool IsRunning() const;
[email protected]89bf27e2013-06-27 18:04:56108
109 // Returns the current delay for this timer.
[email protected]9df013b2014-03-13 22:04:39110 virtual TimeDelta GetCurrentDelay() const;
[email protected]89bf27e2013-06-27 18:04:56111
petrcermak7652da6d2014-11-06 02:17:57112 // Set the task runner on which the task should be scheduled. This method can
gab4e844bb2017-06-01 16:23:36113 // only be called before any tasks have been scheduled. If |task_runner| runs
114 // tasks on a different sequence than the sequence owning this Timer,
115 // |user_task_| will be posted to it when the Timer fires (note that this
116 // means |user_task_| can run after ~Timer() and should support that).
117 void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner);
petrcermak7652da6d2014-11-06 02:17:57118
[email protected]89bf27e2013-06-27 18:04:56119 // Start the timer to run at the given |delay| from now. If the timer is
120 // already running, it will be replaced to call the given |user_task|.
[email protected]9df013b2014-03-13 22:04:39121 virtual void Start(const tracked_objects::Location& posted_from,
[email protected]d76fad62014-05-23 21:09:20122 TimeDelta delay,
123 const base::Closure& user_task);
[email protected]89bf27e2013-06-27 18:04:56124
125 // Call this method to stop and cancel the timer. It is a no-op if the timer
126 // is not running.
[email protected]9df013b2014-03-13 22:04:39127 virtual void Stop();
[email protected]89bf27e2013-06-27 18:04:56128
gab4e844bb2017-06-01 16:23:36129 // Call this method to reset the timer delay. The |user_task_| must be set. If
[email protected]89bf27e2013-06-27 18:04:56130 // the timer is not running, this will start it by posting a task.
[email protected]9df013b2014-03-13 22:04:39131 virtual void Reset();
[email protected]89bf27e2013-06-27 18:04:56132
133 const base::Closure& user_task() const { return user_task_; }
134 const TimeTicks& desired_run_time() const { return desired_run_time_; }
135
136 protected:
jameswest6e0c8d22016-11-15 05:19:54137 // Returns the current tick count.
138 TimeTicks Now() const;
139
chirantan26436e402014-10-24 19:44:42140 void set_user_task(const Closure& task) { user_task_ = task; }
141 void set_desired_run_time(TimeTicks desired) { desired_run_time_ = desired; }
142 void set_is_running(bool running) { is_running_ = running; }
143
144 const tracked_objects::Location& posted_from() const { return posted_from_; }
[email protected]9df013b2014-03-13 22:04:39145 bool retain_user_task() const { return retain_user_task_; }
146 bool is_repeating() const { return is_repeating_; }
chirantan26436e402014-10-24 19:44:42147 bool is_running() const { return is_running_; }
[email protected]9df013b2014-03-13 22:04:39148
[email protected]89bf27e2013-06-27 18:04:56149 private:
150 friend class BaseTimerTaskInternal;
151
gab4e844bb2017-06-01 16:23:36152 // Allocates a new |scheduled_task_| and posts it on the current sequence with
153 // the given |delay|. |scheduled_task_| must be null. |scheduled_run_time_|
154 // and |desired_run_time_| are reset to Now() + delay.
[email protected]89bf27e2013-06-27 18:04:56155 void PostNewScheduledTask(TimeDelta delay);
156
jsbell763cd402015-12-17 00:38:27157 // Returns the task runner on which the task should be scheduled. If the
gab4e844bb2017-06-01 16:23:36158 // corresponding |task_runner_| field is null, the task runner for the current
159 // sequence is returned.
160 scoped_refptr<SequencedTaskRunner> GetTaskRunner();
petrcermak7652da6d2014-11-06 02:17:57161
gab4e844bb2017-06-01 16:23:36162 // Disable |scheduled_task_| and abandon it so that it no longer refers back
163 // to this object.
[email protected]89bf27e2013-06-27 18:04:56164 void AbandonScheduledTask();
165
gab4e844bb2017-06-01 16:23:36166 // Called by BaseTimerTaskInternal when the delayed task fires.
[email protected]89bf27e2013-06-27 18:04:56167 void RunScheduledTask();
168
169 // Stop running task (if any) and abandon scheduled task (if any).
gab4e844bb2017-06-01 16:23:36170 void AbandonAndStop() {
[email protected]89bf27e2013-06-27 18:04:56171 AbandonScheduledTask();
pkotwicz4a286ed2017-01-17 20:45:26172
173 Stop();
174 // No more member accesses here: |this| could be deleted at this point.
[email protected]89bf27e2013-06-27 18:04:56175 }
176
gab4e844bb2017-06-01 16:23:36177 // When non-null, the |scheduled_task_| was posted to call RunScheduledTask()
178 // at |scheduled_run_time_|.
[email protected]89bf27e2013-06-27 18:04:56179 BaseTimerTaskInternal* scheduled_task_;
180
petrcermak7652da6d2014-11-06 02:17:57181 // The task runner on which the task should be scheduled. If it is null, the
gab4e844bb2017-06-01 16:23:36182 // task runner for the current sequence will be used.
183 scoped_refptr<SequencedTaskRunner> task_runner_;
petrcermak7652da6d2014-11-06 02:17:57184
[email protected]89bf27e2013-06-27 18:04:56185 // Location in user code.
186 tracked_objects::Location posted_from_;
187 // Delay requested by user.
188 TimeDelta delay_;
gab4e844bb2017-06-01 16:23:36189 // |user_task_| is what the user wants to be run at |desired_run_time_|.
[email protected]89bf27e2013-06-27 18:04:56190 base::Closure user_task_;
191
gab4e844bb2017-06-01 16:23:36192 // The time at which |scheduled_task_| is expected to fire. This time can be a
193 // "zero" TimeTicks if the task must be run immediately.
[email protected]89bf27e2013-06-27 18:04:56194 TimeTicks scheduled_run_time_;
195
gab4e844bb2017-06-01 16:23:36196 // The desired run time of |user_task_|. The user may update this at any time,
197 // even if their previous request has not run yet. If |desired_run_time_| is
198 // greater than |scheduled_run_time_|, a continuation task will be posted to
[email protected]89bf27e2013-06-27 18:04:56199 // wait for the remaining time. This allows us to reuse the pending task so as
gab4e844bb2017-06-01 16:23:36200 // not to flood the delayed queues with orphaned tasks when the user code
[email protected]d04519352013-12-04 20:05:45201 // excessively Stops and Starts the timer. This time can be a "zero" TimeTicks
202 // if the task must be run immediately.
[email protected]89bf27e2013-06-27 18:04:56203 TimeTicks desired_run_time_;
204
gab4e844bb2017-06-01 16:23:36205 // Timer isn't thread-safe and must only be used on its origin sequence
206 // (sequence on which it was started).
207 SequenceChecker origin_sequence_checker_;
[email protected]89bf27e2013-06-27 18:04:56208
209 // Repeating timers automatically post the task again before calling the task
210 // callback.
211 const bool is_repeating_;
212
gab4e844bb2017-06-01 16:23:36213 // If true, hold on to the |user_task_| closure object for reuse.
[email protected]89bf27e2013-06-27 18:04:56214 const bool retain_user_task_;
215
jameswest6e0c8d22016-11-15 05:19:54216 // The tick clock used to calculate the run time for scheduled tasks.
217 TickClock* const tick_clock_;
218
gab4e844bb2017-06-01 16:23:36219 // If true, |user_task_| is scheduled to run sometime in the future.
[email protected]89bf27e2013-06-27 18:04:56220 bool is_running_;
221
222 DISALLOW_COPY_AND_ASSIGN(Timer);
223};
224
225//-----------------------------------------------------------------------------
226// This class is an implementation detail of OneShotTimer and RepeatingTimer.
227// Please do not use this class directly.
[email protected]89bf27e2013-06-27 18:04:56228class BaseTimerMethodPointer : public Timer {
229 public:
[email protected]89bf27e2013-06-27 18:04:56230 // This is here to work around the fact that Timer::Start is "hidden" by the
231 // Start definition below, rather than being overloaded.
232 // TODO(tim): We should remove uses of BaseTimerMethodPointer::Start below
233 // and convert callers to use the base::Closure version in Timer::Start,
234 // see bug 148832.
235 using Timer::Start;
236
danakj8c3eb802015-09-24 07:53:00237 enum RepeatMode { ONE_SHOT, REPEATING };
jameswest6e0c8d22016-11-15 05:19:54238 BaseTimerMethodPointer(RepeatMode mode, TickClock* tick_clock)
239 : Timer(mode == REPEATING, mode == REPEATING, tick_clock) {}
[email protected]89bf27e2013-06-27 18:04:56240
241 // Start the timer to run at the given |delay| from now. If the timer is
242 // already running, it will be replaced to call a task formed from
243 // |reviewer->*method|.
danakj8c3eb802015-09-24 07:53:00244 template <class Receiver>
245 void Start(const tracked_objects::Location& posted_from,
246 TimeDelta delay,
247 Receiver* receiver,
248 void (Receiver::*method)()) {
[email protected]89bf27e2013-06-27 18:04:56249 Timer::Start(posted_from, delay,
250 base::Bind(method, base::Unretained(receiver)));
251 }
252};
253
254//-----------------------------------------------------------------------------
255// A simple, one-shot timer. See usage notes at the top of the file.
danakj8c3eb802015-09-24 07:53:00256class OneShotTimer : public BaseTimerMethodPointer {
257 public:
jameswest6e0c8d22016-11-15 05:19:54258 OneShotTimer() : OneShotTimer(nullptr) {}
259 explicit OneShotTimer(TickClock* tick_clock)
260 : BaseTimerMethodPointer(ONE_SHOT, tick_clock) {}
danakj8c3eb802015-09-24 07:53:00261};
[email protected]89bf27e2013-06-27 18:04:56262
263//-----------------------------------------------------------------------------
264// A simple, repeating timer. See usage notes at the top of the file.
danakj8c3eb802015-09-24 07:53:00265class RepeatingTimer : public BaseTimerMethodPointer {
266 public:
jameswest6e0c8d22016-11-15 05:19:54267 RepeatingTimer() : RepeatingTimer(nullptr) {}
268 explicit RepeatingTimer(TickClock* tick_clock)
269 : BaseTimerMethodPointer(REPEATING, tick_clock) {}
danakj8c3eb802015-09-24 07:53:00270};
[email protected]89bf27e2013-06-27 18:04:56271
272//-----------------------------------------------------------------------------
273// A Delay timer is like The Button from Lost. Once started, you have to keep
gab4e844bb2017-06-01 16:23:36274// calling Reset otherwise it will call the given method on the sequence it was
275// initially Reset() from.
[email protected]89bf27e2013-06-27 18:04:56276//
277// Once created, it is inactive until Reset is called. Once |delay| seconds have
278// passed since the last call to Reset, the callback is made. Once the callback
279// has been made, it's inactive until Reset is called again.
280//
281// If destroyed, the timeout is canceled and will not occur even if already
282// inflight.
[email protected]89bf27e2013-06-27 18:04:56283class DelayTimer : protected Timer {
284 public:
danakj8c3eb802015-09-24 07:53:00285 template <class Receiver>
[email protected]89bf27e2013-06-27 18:04:56286 DelayTimer(const tracked_objects::Location& posted_from,
287 TimeDelta delay,
288 Receiver* receiver,
danakj8c3eb802015-09-24 07:53:00289 void (Receiver::*method)())
jameswest6e0c8d22016-11-15 05:19:54290 : DelayTimer(posted_from, delay, receiver, method, nullptr) {}
291
292 template <class Receiver>
293 DelayTimer(const tracked_objects::Location& posted_from,
294 TimeDelta delay,
295 Receiver* receiver,
296 void (Receiver::*method)(),
297 TickClock* tick_clock)
danakj8c3eb802015-09-24 07:53:00298 : Timer(posted_from,
299 delay,
[email protected]89bf27e2013-06-27 18:04:56300 base::Bind(method, base::Unretained(receiver)),
jameswest6e0c8d22016-11-15 05:19:54301 false,
302 tick_clock) {}
[email protected]89bf27e2013-06-27 18:04:56303
danakj8c3eb802015-09-24 07:53:00304 void Reset() override;
[email protected]89bf27e2013-06-27 18:04:56305};
306
danakj8c3eb802015-09-24 07:53:00307// This class has a templated method so it can not be exported without failing
308// to link in MSVC. But clang-plugin does not allow inline definitions of
309// virtual methods, so the inline definition lives in the header file here
310// to satisfy both.
311inline void DelayTimer::Reset() {
312 Timer::Reset();
313}
314
[email protected]89bf27e2013-06-27 18:04:56315} // namespace base
316
317#endif // BASE_TIMER_TIMER_H_