blob: 2a1fbc4675ad7ddb931323582f8ccfe1e41c2faf [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]89bf27e2013-06-27 18:04:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Etienne Pierre-doray1a0edc72022-01-14 15:11:445// A "timer" takes care of invoking a callback in the future, once or
6// repeatedly. The callback is invoked:
7// - OneShotTimer: Once after a `TimeDelta` delay has elapsed.
8// - RetainingOneShotTimer: Same as OneShotTimer, but the callback is retained
9// after being executed, allowing another invocation to be scheduled with
10// Reset() without specifying the callback again.
11// - DeadlineTimer: Once at the specified `TimeTicks` time.
12// - RepeatingTimer: Repeatedly, with a specified `TimeDelta` delay before the
13// first invocation and between invocations.
Etienne Pierre-dorayc7654612022-06-08 22:23:3214// - MetronomeTimer: Repeatedly, with a specified `TimeDelta` delay between the
15// beginning of each invocations such that a constant phase is respected.
16// (Retaining)OneShotTimer and RepeatingTimer automatically apply some leeway to
17// the delay whereas DeadlineTimer and MetronomeTimer allow more control over
18// the requested time. As a result, the former are generally more
19// power-efficient.
20// Prefer using (Retaining)OneShotTimer and RepeatingTimer because they
21// automatically apply some leeway to the delay which enables power-efficient
22// scheduling.
Etienne Pierre-doray1a0edc72022-01-14 15:11:4423
24// Scheduled invocations can be cancelled with Stop() or by deleting the
25// Timer. The latter makes it easy to ensure that an object is not accessed by a
26// Timer after it has been deleted: just make the Timer a member of the object
27// which receives Timer events (see example below).
[email protected]89bf27e2013-06-27 18:04:5628//
29// Sample RepeatingTimer usage:
30//
31// class MyClass {
32// public:
33// void StartDoingStuff() {
Hong Xua6f51122022-04-20 20:10:2234// timer_.Start(FROM_HERE, base::Seconds(1),
[email protected]89bf27e2013-06-27 18:04:5635// this, &MyClass::DoStuff);
Hong Xua6f51122022-04-20 20:10:2236// // Alternative form if the callback is not bound to `this` or
37// // requires arguments:
38// // timer_.Start(FROM_HERE, base::Seconds(1),
39// // base::BindRepeating(&MyFunction, 42));
[email protected]89bf27e2013-06-27 18:04:5640// }
41// void StopDoingStuff() {
42// timer_.Stop();
43// }
44// private:
45// void DoStuff() {
46// // This method is called every second to do stuff.
47// ...
48// }
danakj8c3eb802015-09-24 07:53:0049// base::RepeatingTimer timer_;
[email protected]89bf27e2013-06-27 18:04:5650// };
51//
Gabriel Charettee92ccc02019-01-19 14:13:0552// These APIs are not thread safe. When a method is called (except the
53// constructor), all further method calls must be on the same sequence until
Patrick Monettec4d306d2021-06-23 19:15:2554// Stop(). Once stopped, it may be destroyed or restarted on another sequence.
ossu87340af2017-07-06 09:02:1555//
56// By default, the scheduled tasks will be run on the same sequence that the
Gabriel Charettee92ccc02019-01-19 14:13:0557// Timer was *started on*. To mock time in unit tests, some old tests used
58// SetTaskRunner() to schedule the delay on a test-controlled TaskRunner. The
Gabriel Charette694c3c332019-08-19 14:53:0559// modern and preferred approach to mock time is to use TaskEnvironment's
Gabriel Charettee92ccc02019-01-19 14:13:0560// MOCK_TIME mode.
[email protected]89bf27e2013-06-27 18:04:5661
62#ifndef BASE_TIMER_TIMER_H_
63#define BASE_TIMER_TIMER_H_
64
65// IMPORTANT: If you change timer code, make sure that all tests (including
66// disabled ones) from timer_unittests.cc pass locally. Some are disabled
67// because they're flaky on the buildbot, but when you run them locally you
68// should be able to tell the difference.
69
70#include "base/base_export.h"
Tom Sepez04e98bf2024-10-25 18:19:3171#include "base/compiler_specific.h"
Avi Drissman63e1f992023-01-13 18:54:4372#include "base/functional/bind.h"
73#include "base/functional/callback.h"
74#include "base/functional/callback_helpers.h"
[email protected]89bf27e2013-06-27 18:04:5675#include "base/location.h"
Keishi Hattori0e45c022021-11-27 09:25:5276#include "base/memory/raw_ptr.h"
Patrick Monettec4d306d2021-06-23 19:15:2577#include "base/sequence_checker.h"
Patrick Monette6994b91f2021-11-01 19:19:0478#include "base/task/delayed_task_handle.h"
Patrick Monette643cdf62021-10-15 19:13:4279#include "base/task/sequenced_task_runner.h"
[email protected]89bf27e2013-06-27 18:04:5680#include "base/time/time.h"
Etienne Pierre-doray1a0edc72022-01-14 15:11:4481#include "base/types/strong_alias.h"
[email protected]89bf27e2013-06-27 18:04:5682
83namespace base {
84
jameswest6e0c8d22016-11-15 05:19:5485class TickClock;
[email protected]89bf27e2013-06-27 18:04:5686
tzikd93bb0862018-07-19 11:54:1487namespace internal {
88
Etienne Pierre-doray1a0edc72022-01-14 15:11:4489// This class wraps logic shared by all timers.
tzikd93bb0862018-07-19 11:54:1490class BASE_EXPORT TimerBase {
[email protected]89bf27e2013-06-27 18:04:5691 public:
Peter Boström7319bbd2021-09-15 22:59:3892 TimerBase(const TimerBase&) = delete;
93 TimerBase& operator=(const TimerBase&) = delete;
94
tzikd93bb0862018-07-19 11:54:1495 virtual ~TimerBase();
[email protected]89bf27e2013-06-27 18:04:5696
97 // Returns true if the timer is running (i.e., not stopped).
tzik84db8912018-06-19 06:08:5498 bool IsRunning() const;
[email protected]89bf27e2013-06-27 18:04:5699
Gabriel Charettee92ccc02019-01-19 14:13:05100 // Sets the task runner on which the delayed task should be scheduled when
101 // this Timer is running. This method can only be called while this Timer
Etienne Pierre-doray5321eb02021-12-09 18:05:49102 // isn't running. If this is used to mock time in tests, the modern and
103 // preferred approach is to use TaskEnvironment::TimeSource::MOCK_TIME. To
104 // avoid racy usage of Timer, |task_runner| must run tasks on the same
105 // sequence which this Timer is bound to (started from). TODO(gab): Migrate
106 // callers using this as a test seam to
Gabriel Charette694c3c332019-08-19 14:53:05107 // TaskEnvironment::TimeSource::MOCK_TIME.
tzik84db8912018-06-19 06:08:54108 virtual void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner);
petrcermak7652da6d2014-11-06 02:17:57109
Hong Xu4b105812022-08-09 14:49:42110 // Call this method to stop the timer and cancel all previously scheduled
111 // tasks. It is a no-op if the timer is not running.
[email protected]9df013b2014-03-13 22:04:39112 virtual void Stop();
[email protected]89bf27e2013-06-27 18:04:56113
[email protected]89bf27e2013-06-27 18:04:56114 protected:
Etienne Pierre-doray1a0edc72022-01-14 15:11:44115 // Constructs a timer. Start must be called later to set task info.
116 explicit TimerBase(const Location& posted_from = Location());
117
Etienne Pierre-doray1a0edc72022-01-14 15:11:44118 virtual void OnStop() = 0;
119
Etienne Pierre-doray9c3d17d82022-05-12 22:05:29120 // Disables the scheduled task and abandons it so that it no longer refers
121 // back to this object.
Etienne Pierre-doray1a0edc72022-01-14 15:11:44122 void AbandonScheduledTask();
123
124 // Returns the task runner on which the task should be scheduled. If the
125 // corresponding |task_runner_| field is null, the task runner for the current
126 // sequence is returned.
127 scoped_refptr<SequencedTaskRunner> GetTaskRunner();
tzikf3336c92018-07-25 03:15:50128
tzikf550a612018-07-12 02:25:34129 // The task runner on which the task should be scheduled. If it is null, the
130 // task runner for the current sequence will be used.
131 scoped_refptr<SequencedTaskRunner> task_runner_;
132
Patrick Monettec4d306d2021-06-23 19:15:25133 // Timer isn't thread-safe and while it is running, it must only be used on
134 // the same sequence until fully Stop()'ed. Once stopped, it may be destroyed
135 // or restarted on another sequence.
136 SEQUENCE_CHECKER(sequence_checker_);
tzikf550a612018-07-12 02:25:34137
Etienne Pierre-doray1a0edc72022-01-14 15:11:44138 // Location in user code.
139 Location posted_from_ GUARDED_BY_CONTEXT(sequence_checker_);
140
Etienne Pierre-doray1a0edc72022-01-14 15:11:44141 // The handle to the posted delayed task.
142 DelayedTaskHandle delayed_task_handle_ GUARDED_BY_CONTEXT(sequence_checker_);
Etienne Pierre-dorayf16856862022-06-10 18:49:02143
144 // Callback invoked when the timer is ready. This is saved as a member to
145 // avoid rebinding every time the Timer fires. Lazy initialized the first time
146 // the Timer is started.
147 RepeatingClosure timer_callback_;
Etienne Pierre-doray1a0edc72022-01-14 15:11:44148};
149
150//-----------------------------------------------------------------------------
151// This class wraps logic shared by (Retaining)OneShotTimer and RepeatingTimer.
152class BASE_EXPORT DelayTimerBase : public TimerBase {
153 public:
154 DelayTimerBase(const DelayTimerBase&) = delete;
155 DelayTimerBase& operator=(const DelayTimerBase&) = delete;
156
157 ~DelayTimerBase() override;
158
159 // Returns the current delay for this timer.
160 TimeDelta GetCurrentDelay() const;
161
162 // Call this method to reset the timer delay. The user task must be set. If
163 // the timer is not running, this will start it by posting a task.
164 virtual void Reset();
165
Etienne Pierre-doray1a0edc72022-01-14 15:11:44166 TimeTicks desired_run_time() const {
167 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
168 return desired_run_time_;
169 }
170
171 protected:
172 // Constructs a timer. Start must be called later to set task info.
173 // If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get
174 // TimeTicks when scheduling tasks.
175 explicit DelayTimerBase(const TickClock* tick_clock = nullptr);
176
177 // Construct a timer with task info.
178 // If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get
179 // TimeTicks when scheduling tasks.
180 DelayTimerBase(const Location& posted_from,
181 TimeDelta delay,
182 const TickClock* tick_clock = nullptr);
183
Etienne Pierre-doray9c3d17d82022-05-12 22:05:29184 virtual void RunUserTask() = 0;
185
Patrick Monette57d1c18d2021-04-22 00:50:44186 // Schedules |OnScheduledTaskInvoked()| to run on the current sequence with
Etienne Pierre-doray8c6860d2023-03-22 20:18:49187 // the given |delay|. |desired_run_time_| is reset to Now() + delay.
Patrick Monette57d1c18d2021-04-22 00:50:44188 void ScheduleNewTask(TimeDelta delay);
[email protected]89bf27e2013-06-27 18:04:56189
tzikf3336c92018-07-25 03:15:50190 void StartInternal(const Location& posted_from, TimeDelta delay);
191
192 private:
Patrick Monette478af572022-01-20 20:34:15193 // DCHECKs that the user task is not null. Used to diagnose a recurring bug
194 // where Reset() is called on a OneShotTimer that has already fired.
195 virtual void EnsureNonNullUserTask() = 0;
196
Patrick Monette400b05142021-04-21 22:28:35197 // Returns the current tick count.
198 TimeTicks Now() const;
199
Patrick Monette57d1c18d2021-04-22 00:50:44200 // Called when the scheduled task is invoked. Will run the |user_task| if the
201 // timer is still running and |desired_run_time_| was reached.
Etienne Pierre-doray9c3d17d82022-05-12 22:05:29202 void OnScheduledTaskInvoked();
[email protected]89bf27e2013-06-27 18:04:56203
[email protected]89bf27e2013-06-27 18:04:56204 // Delay requested by user.
Patrick Monettec4d306d2021-06-23 19:15:25205 TimeDelta delay_ GUARDED_BY_CONTEXT(sequence_checker_);
[email protected]89bf27e2013-06-27 18:04:56206
gab4e844bb2017-06-01 16:23:36207 // The desired run time of |user_task_|. The user may update this at any time,
Etienne Pierre-doray8c6860d2023-03-22 20:18:49208 // even if their previous request has not run yet. This time can be a "zero"
209 // TimeTicks if the task must be run immediately.
Patrick Monettec4d306d2021-06-23 19:15:25210 TimeTicks desired_run_time_ GUARDED_BY_CONTEXT(sequence_checker_);
[email protected]89bf27e2013-06-27 18:04:56211
jameswest6e0c8d22016-11-15 05:19:54212 // The tick clock used to calculate the run time for scheduled tasks.
Keishi Hattori0e45c022021-11-27 09:25:52213 const raw_ptr<const TickClock> tick_clock_
214 GUARDED_BY_CONTEXT(sequence_checker_);
[email protected]89bf27e2013-06-27 18:04:56215};
216
tzikd93bb0862018-07-19 11:54:14217} // namespace internal
218
[email protected]89bf27e2013-06-27 18:04:56219//-----------------------------------------------------------------------------
[email protected]89bf27e2013-06-27 18:04:56220// A simple, one-shot timer. See usage notes at the top of the file.
Etienne Pierre-doray1a0edc72022-01-14 15:11:44221class BASE_EXPORT OneShotTimer : public internal::DelayTimerBase {
danakj8c3eb802015-09-24 07:53:00222 public:
tzikf3336c92018-07-25 03:15:50223 OneShotTimer();
224 explicit OneShotTimer(const TickClock* tick_clock);
Peter Boström7319bbd2021-09-15 22:59:38225
226 OneShotTimer(const OneShotTimer&) = delete;
227 OneShotTimer& operator=(const OneShotTimer&) = delete;
228
tzikf3336c92018-07-25 03:15:50229 ~OneShotTimer() override;
230
231 // Start the timer to run at the given |delay| from now. If the timer is
232 // already running, it will be replaced to call the given |user_task|.
233 virtual void Start(const Location& posted_from,
234 TimeDelta delay,
235 OnceClosure user_task);
236
237 // Start the timer to run at the given |delay| from now. If the timer is
238 // already running, it will be replaced to call a task formed from
Ming-Chuan Lin1b43b402020-02-27 17:53:39239 // |receiver->*method|.
tzikf3336c92018-07-25 03:15:50240 template <class Receiver>
241 void Start(const Location& posted_from,
242 TimeDelta delay,
243 Receiver* receiver,
244 void (Receiver::*method)()) {
Peter Kastinga253f752025-01-31 18:57:26245 // Explicitly qualify calls, in case this is used inside Blink (which has
246 // similar methods in WTF).
247 Start(posted_from, delay,
248 ::base::BindOnce(method, ::base::Unretained(receiver)));
tzikf3336c92018-07-25 03:15:50249 }
tzikf550a612018-07-12 02:25:34250
251 // Run the scheduled task immediately, and stop the timer. The timer needs to
252 // be running.
Shintaro Kawamuraccefc5a2023-05-08 16:46:18253 virtual void FireNow();
tzikf3336c92018-07-25 03:15:50254
255 private:
256 void OnStop() final;
257 void RunUserTask() final;
Patrick Monette478af572022-01-20 20:34:15258 void EnsureNonNullUserTask() final;
tzikf3336c92018-07-25 03:15:50259
260 OnceClosure user_task_;
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.
Etienne Pierre-doray1a0edc72022-01-14 15:11:44265class BASE_EXPORT RepeatingTimer : public internal::DelayTimerBase {
danakj8c3eb802015-09-24 07:53:00266 public:
tzikf3336c92018-07-25 03:15:50267 RepeatingTimer();
268 explicit RepeatingTimer(const TickClock* tick_clock);
Peter Boström7319bbd2021-09-15 22:59:38269
270 RepeatingTimer(const RepeatingTimer&) = delete;
271 RepeatingTimer& operator=(const RepeatingTimer&) = delete;
272
tzikf3336c92018-07-25 03:15:50273 ~RepeatingTimer() override;
tzik524daae92018-07-05 02:52:02274
275 RepeatingTimer(const Location& posted_from,
276 TimeDelta delay,
tzikf3336c92018-07-25 03:15:50277 RepeatingClosure user_task);
tzik524daae92018-07-05 02:52:02278 RepeatingTimer(const Location& posted_from,
279 TimeDelta delay,
280 RepeatingClosure user_task,
tzikf3336c92018-07-25 03:15:50281 const TickClock* tick_clock);
282
283 // Start the timer to run at the given |delay| from now. If the timer is
284 // already running, it will be replaced to call the given |user_task|.
285 virtual void Start(const Location& posted_from,
286 TimeDelta delay,
287 RepeatingClosure user_task);
288
289 // Start the timer to run at the given |delay| from now. If the timer is
290 // already running, it will be replaced to call a task formed from
Ming-Chuan Lin1b43b402020-02-27 17:53:39291 // |receiver->*method|.
tzikf3336c92018-07-25 03:15:50292 template <class Receiver>
293 void Start(const Location& posted_from,
294 TimeDelta delay,
295 Receiver* receiver,
296 void (Receiver::*method)()) {
297 Start(posted_from, delay, BindRepeating(method, Unretained(receiver)));
298 }
299
Tom Sepez04e98bf2024-10-25 18:19:31300 const RepeatingClosure& user_task() const LIFETIME_BOUND {
301 return user_task_;
302 }
tzikf3336c92018-07-25 03:15:50303
304 private:
305 // Mark this final, so that the destructor can call this safely.
306 void OnStop() final;
tzikf3336c92018-07-25 03:15:50307 void RunUserTask() override;
Patrick Monette478af572022-01-20 20:34:15308 void EnsureNonNullUserTask() final;
tzikf3336c92018-07-25 03:15:50309
310 RepeatingClosure user_task_;
danakj8c3eb802015-09-24 07:53:00311};
[email protected]89bf27e2013-06-27 18:04:56312
313//-----------------------------------------------------------------------------
Etienne Pierre-doray1a0edc72022-01-14 15:11:44314// A simple, one-shot timer with the retained |user_task| which is reused when
315// Reset() is invoked. See usage notes at the top of the file.
316class BASE_EXPORT RetainingOneShotTimer : public internal::DelayTimerBase {
tzik57c66e32018-07-02 08:02:57317 public:
tzikf3336c92018-07-25 03:15:50318 RetainingOneShotTimer();
319 explicit RetainingOneShotTimer(const TickClock* tick_clock);
Peter Boström7319bbd2021-09-15 22:59:38320
321 RetainingOneShotTimer(const RetainingOneShotTimer&) = delete;
322 RetainingOneShotTimer& operator=(const RetainingOneShotTimer&) = delete;
323
tzikf3336c92018-07-25 03:15:50324 ~RetainingOneShotTimer() override;
tzik524daae92018-07-05 02:52:02325
326 RetainingOneShotTimer(const Location& posted_from,
327 TimeDelta delay,
tzikf3336c92018-07-25 03:15:50328 RepeatingClosure user_task);
tzik524daae92018-07-05 02:52:02329 RetainingOneShotTimer(const Location& posted_from,
330 TimeDelta delay,
331 RepeatingClosure user_task,
tzikf3336c92018-07-25 03:15:50332 const TickClock* tick_clock);
333
334 // Start the timer to run at the given |delay| from now. If the timer is
335 // already running, it will be replaced to call the given |user_task|.
336 virtual void Start(const Location& posted_from,
337 TimeDelta delay,
338 RepeatingClosure user_task);
339
340 // Start the timer to run at the given |delay| from now. If the timer is
341 // already running, it will be replaced to call a task formed from
Ming-Chuan Lin1b43b402020-02-27 17:53:39342 // |receiver->*method|.
tzikf3336c92018-07-25 03:15:50343 template <class Receiver>
344 void Start(const Location& posted_from,
345 TimeDelta delay,
346 Receiver* receiver,
347 void (Receiver::*method)()) {
348 Start(posted_from, delay, BindRepeating(method, Unretained(receiver)));
349 }
350
Tom Sepez04e98bf2024-10-25 18:19:31351 const RepeatingClosure& user_task() const LIFETIME_BOUND {
352 return user_task_;
353 }
tzikf3336c92018-07-25 03:15:50354
tzikf3336c92018-07-25 03:15:50355 private:
356 // Mark this final, so that the destructor can call this safely.
357 void OnStop() final;
tzikf3336c92018-07-25 03:15:50358 void RunUserTask() override;
Patrick Monette478af572022-01-20 20:34:15359 void EnsureNonNullUserTask() final;
tzikf3336c92018-07-25 03:15:50360
361 RepeatingClosure user_task_;
tzik57c66e32018-07-02 08:02:57362};
363
364//-----------------------------------------------------------------------------
[email protected]89bf27e2013-06-27 18:04:56365// A Delay timer is like The Button from Lost. Once started, you have to keep
gab4e844bb2017-06-01 16:23:36366// calling Reset otherwise it will call the given method on the sequence it was
367// initially Reset() from.
[email protected]89bf27e2013-06-27 18:04:56368//
369// Once created, it is inactive until Reset is called. Once |delay| seconds have
370// passed since the last call to Reset, the callback is made. Once the callback
371// has been made, it's inactive until Reset is called again.
372//
373// If destroyed, the timeout is canceled and will not occur even if already
374// inflight.
tzik32c3bcd2018-07-09 04:39:38375class DelayTimer {
[email protected]89bf27e2013-06-27 18:04:56376 public:
danakj8c3eb802015-09-24 07:53:00377 template <class Receiver>
Brett Wilson8e88b312017-09-12 05:22:16378 DelayTimer(const Location& posted_from,
[email protected]89bf27e2013-06-27 18:04:56379 TimeDelta delay,
380 Receiver* receiver,
danakj8c3eb802015-09-24 07:53:00381 void (Receiver::*method)())
jameswest6e0c8d22016-11-15 05:19:54382 : DelayTimer(posted_from, delay, receiver, method, nullptr) {}
383
384 template <class Receiver>
Brett Wilson8e88b312017-09-12 05:22:16385 DelayTimer(const Location& posted_from,
jameswest6e0c8d22016-11-15 05:19:54386 TimeDelta delay,
387 Receiver* receiver,
388 void (Receiver::*method)(),
Greg Thompsonaa48ce8d2018-04-03 06:11:43389 const TickClock* tick_clock)
tzik32c3bcd2018-07-09 04:39:38390 : timer_(posted_from,
391 delay,
392 BindRepeating(method, Unretained(receiver)),
393 tick_clock) {}
[email protected]89bf27e2013-06-27 18:04:56394
Peter Boström75cd3c02021-09-28 15:23:18395 DelayTimer(const DelayTimer&) = delete;
396 DelayTimer& operator=(const DelayTimer&) = delete;
397
tzik32c3bcd2018-07-09 04:39:38398 void Reset() { timer_.Reset(); }
399
400 private:
401 RetainingOneShotTimer timer_;
[email protected]89bf27e2013-06-27 18:04:56402};
403
Etienne Pierre-doray1a0edc72022-01-14 15:11:44404//-----------------------------------------------------------------------------
405// A one-shot timer that attempts to run |user_task| some time near specified
406// deadline. See usage notes at the top of the file.
407class BASE_EXPORT DeadlineTimer : public internal::TimerBase {
408 public:
409 DeadlineTimer();
410 ~DeadlineTimer() override;
411
412 DeadlineTimer(const DeadlineTimer&) = delete;
413 DeadlineTimer& operator=(const DeadlineTimer&) = delete;
414
Etienne Pierre-doraya3f38272022-12-08 22:10:51415 // Start the timer to run |user_task| near the specified |deadline| following
416 // |delay_policy| If the timer is already running, it will be replaced to call
417 // the given |user_task|.
Etienne Pierre-doray1a0edc72022-01-14 15:11:44418 void Start(const Location& posted_from,
419 TimeTicks deadline,
420 OnceClosure user_task,
Etienne Pierre-doraya3f38272022-12-08 22:10:51421 subtle::DelayPolicy delay_policy =
422 subtle::DelayPolicy::kFlexiblePreferEarly);
Etienne Pierre-doray1a0edc72022-01-14 15:11:44423
424 // Start the timer to run |user_task| near the specified |deadline|. If the
425 // timer is already running, it will be replaced to call a task formed from
426 // |receiver->*method|.
427 template <class Receiver>
428 void Start(const Location& posted_from,
429 TimeTicks deadline,
430 Receiver* receiver,
431 void (Receiver::*method)(),
Etienne Pierre-doraya3f38272022-12-08 22:10:51432 subtle::DelayPolicy delay_policy =
433 subtle::DelayPolicy::kFlexiblePreferEarly) {
434 Start(posted_from, deadline, BindOnce(method, Unretained(receiver)),
435 delay_policy);
Etienne Pierre-doray1a0edc72022-01-14 15:11:44436 }
437
438 protected:
439 void OnStop() override;
Etienne Pierre-doray1a0edc72022-01-14 15:11:44440
441 // Schedules |OnScheduledTaskInvoked()| to run on the current sequence at
442 // the given |deadline|.
443 void ScheduleNewTask(TimeTicks deadline, subtle::DelayPolicy delay_policy);
444
445 private:
446 // Called when the scheduled task is invoked to run the |user_task|.
Etienne Pierre-doray9c3d17d82022-05-12 22:05:29447 void OnScheduledTaskInvoked();
Etienne Pierre-doray1a0edc72022-01-14 15:11:44448
449 OnceClosure user_task_;
450};
451
Etienne Pierre-dorayc7654612022-06-08 22:23:32452//-----------------------------------------------------------------------------
453// Repeatedly invokes a callback, waiting for a precise delay between the
454// beginning of each invocation. See usage notes at the top of the file.
455class BASE_EXPORT MetronomeTimer : public internal::TimerBase {
456 public:
457 MetronomeTimer();
458 ~MetronomeTimer() override;
459
460 MetronomeTimer(const MetronomeTimer&) = delete;
461 MetronomeTimer& operator=(const MetronomeTimer&) = delete;
462
463 MetronomeTimer(const Location& posted_from,
464 TimeDelta interval,
465 RepeatingClosure user_task,
466 TimeTicks phase = TimeTicks());
467
468 // Start the timer to repeatedly run |user_task| at the specified |interval|;
469 // If not specified, the phase is up to the scheduler, otherwise each
470 // invocation starts as close as possible to `phase + n * delay` for some
471 // integer n. If the timer is already running, it will be replaced to call the
472 // given |user_task|.
473 void Start(const Location& posted_from,
474 TimeDelta interval,
475 RepeatingClosure user_task,
476 TimeTicks phase = TimeTicks());
477
478 // Same as the previous overload, except that the user task is specified by
479 // `receiver` and `method`.
480 template <class Receiver>
481 void Start(const Location& posted_from,
482 TimeDelta interval,
483 Receiver* receiver,
484 void (Receiver::*method)(),
485 TimeTicks phase = TimeTicks()) {
Francois Dorayf8b6e45a2023-02-17 17:32:17486 Start(posted_from, interval, BindRepeating(method, Unretained(receiver)),
487 phase);
Etienne Pierre-dorayc7654612022-06-08 22:23:32488 }
489
490 // Call this method to reset the timer delay. The user task must be set. If
491 // the timer is not running, this will start it by posting a task.
492 void Reset();
493
494 protected:
495 void OnStop() override;
496
497 // Schedules |OnScheduledTaskInvoked()| to run on the current sequence at
498 // the next tick.
499 void ScheduleNewTask();
500
501 private:
502 // Called when the scheduled task is invoked to run the |user_task|.
503 void OnScheduledTaskInvoked();
504
505 TimeDelta interval_;
506 RepeatingClosure user_task_;
507 TimeTicks phase_;
508};
509
[email protected]89bf27e2013-06-27 18:04:56510} // namespace base
511
512#endif // BASE_TIMER_TIMER_H_