1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <utility>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/ref_counted.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/task/task_features.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/time/tick_clock.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace base {
22*6777b538SAndroid Build Coastguard Worker namespace internal {
23*6777b538SAndroid Build Coastguard Worker
TimerBase(const Location & posted_from)24*6777b538SAndroid Build Coastguard Worker TimerBase::TimerBase(const Location& posted_from) : posted_from_(posted_from) {
25*6777b538SAndroid Build Coastguard Worker // It is safe for the timer to be created on a different thread/sequence than
26*6777b538SAndroid Build Coastguard Worker // the one from which the timer APIs are called. The first call to the
27*6777b538SAndroid Build Coastguard Worker // checker's CalledOnValidSequence() method will re-bind the checker, and
28*6777b538SAndroid Build Coastguard Worker // later calls will verify that the same task runner is used.
29*6777b538SAndroid Build Coastguard Worker DETACH_FROM_SEQUENCE(sequence_checker_);
30*6777b538SAndroid Build Coastguard Worker }
31*6777b538SAndroid Build Coastguard Worker
~TimerBase()32*6777b538SAndroid Build Coastguard Worker TimerBase::~TimerBase() {
33*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
34*6777b538SAndroid Build Coastguard Worker AbandonScheduledTask();
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
IsRunning() const37*6777b538SAndroid Build Coastguard Worker bool TimerBase::IsRunning() const {
38*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
39*6777b538SAndroid Build Coastguard Worker return delayed_task_handle_.IsValid();
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker
SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner)42*6777b538SAndroid Build Coastguard Worker void TimerBase::SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
43*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
44*6777b538SAndroid Build Coastguard Worker DCHECK(task_runner->RunsTasksInCurrentSequence());
45*6777b538SAndroid Build Coastguard Worker DCHECK(!IsRunning());
46*6777b538SAndroid Build Coastguard Worker task_runner_.swap(task_runner);
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker
GetTaskRunner()49*6777b538SAndroid Build Coastguard Worker scoped_refptr<SequencedTaskRunner> TimerBase::GetTaskRunner() {
50*6777b538SAndroid Build Coastguard Worker return task_runner_ ? task_runner_ : SequencedTaskRunner::GetCurrentDefault();
51*6777b538SAndroid Build Coastguard Worker }
52*6777b538SAndroid Build Coastguard Worker
Stop()53*6777b538SAndroid Build Coastguard Worker void TimerBase::Stop() {
54*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker AbandonScheduledTask();
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker OnStop();
59*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted after Stop() call.
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
AbandonScheduledTask()62*6777b538SAndroid Build Coastguard Worker void TimerBase::AbandonScheduledTask() {
63*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker if (delayed_task_handle_.IsValid())
66*6777b538SAndroid Build Coastguard Worker delayed_task_handle_.CancelTask();
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker // It's safe to destroy or restart Timer on another sequence after the task is
69*6777b538SAndroid Build Coastguard Worker // abandoned.
70*6777b538SAndroid Build Coastguard Worker DETACH_FROM_SEQUENCE(sequence_checker_);
71*6777b538SAndroid Build Coastguard Worker }
72*6777b538SAndroid Build Coastguard Worker
DelayTimerBase(const TickClock * tick_clock)73*6777b538SAndroid Build Coastguard Worker DelayTimerBase::DelayTimerBase(const TickClock* tick_clock)
74*6777b538SAndroid Build Coastguard Worker : tick_clock_(tick_clock) {}
75*6777b538SAndroid Build Coastguard Worker
DelayTimerBase(const Location & posted_from,TimeDelta delay,const TickClock * tick_clock)76*6777b538SAndroid Build Coastguard Worker DelayTimerBase::DelayTimerBase(const Location& posted_from,
77*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
78*6777b538SAndroid Build Coastguard Worker const TickClock* tick_clock)
79*6777b538SAndroid Build Coastguard Worker : TimerBase(posted_from), delay_(delay), tick_clock_(tick_clock) {}
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker DelayTimerBase::~DelayTimerBase() = default;
82*6777b538SAndroid Build Coastguard Worker
GetCurrentDelay() const83*6777b538SAndroid Build Coastguard Worker TimeDelta DelayTimerBase::GetCurrentDelay() const {
84*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
85*6777b538SAndroid Build Coastguard Worker return delay_;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
StartInternal(const Location & posted_from,TimeDelta delay)88*6777b538SAndroid Build Coastguard Worker void DelayTimerBase::StartInternal(const Location& posted_from,
89*6777b538SAndroid Build Coastguard Worker TimeDelta delay) {
90*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker posted_from_ = posted_from;
93*6777b538SAndroid Build Coastguard Worker delay_ = delay;
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker Reset();
96*6777b538SAndroid Build Coastguard Worker }
97*6777b538SAndroid Build Coastguard Worker
AbandonAndStop()98*6777b538SAndroid Build Coastguard Worker void DelayTimerBase::AbandonAndStop() {
99*6777b538SAndroid Build Coastguard Worker Stop();
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
Reset()102*6777b538SAndroid Build Coastguard Worker void DelayTimerBase::Reset() {
103*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker EnsureNonNullUserTask();
106*6777b538SAndroid Build Coastguard Worker
107*6777b538SAndroid Build Coastguard Worker // We can't reuse the |scheduled_task_|, so abandon it and post a new one.
108*6777b538SAndroid Build Coastguard Worker AbandonScheduledTask();
109*6777b538SAndroid Build Coastguard Worker ScheduleNewTask(delay_);
110*6777b538SAndroid Build Coastguard Worker }
111*6777b538SAndroid Build Coastguard Worker
ScheduleNewTask(TimeDelta delay)112*6777b538SAndroid Build Coastguard Worker void DelayTimerBase::ScheduleNewTask(TimeDelta delay) {
113*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
114*6777b538SAndroid Build Coastguard Worker DCHECK(!delayed_task_handle_.IsValid());
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker // Ignore negative deltas.
117*6777b538SAndroid Build Coastguard Worker // TODO(pmonette): Fix callers providing negative deltas and ban passing them.
118*6777b538SAndroid Build Coastguard Worker if (delay < TimeDelta())
119*6777b538SAndroid Build Coastguard Worker delay = TimeDelta();
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker if (!timer_callback_) {
122*6777b538SAndroid Build Coastguard Worker timer_callback_ = BindRepeating(&DelayTimerBase::OnScheduledTaskInvoked,
123*6777b538SAndroid Build Coastguard Worker Unretained(this));
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker delayed_task_handle_ = GetTaskRunner()->PostCancelableDelayedTask(
126*6777b538SAndroid Build Coastguard Worker base::subtle::PostDelayedTaskPassKey(), posted_from_, timer_callback_,
127*6777b538SAndroid Build Coastguard Worker delay);
128*6777b538SAndroid Build Coastguard Worker desired_run_time_ = Now() + delay;
129*6777b538SAndroid Build Coastguard Worker }
130*6777b538SAndroid Build Coastguard Worker
Now() const131*6777b538SAndroid Build Coastguard Worker TimeTicks DelayTimerBase::Now() const {
132*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
133*6777b538SAndroid Build Coastguard Worker return tick_clock_ ? tick_clock_->NowTicks() : TimeTicks::Now();
134*6777b538SAndroid Build Coastguard Worker }
135*6777b538SAndroid Build Coastguard Worker
OnScheduledTaskInvoked()136*6777b538SAndroid Build Coastguard Worker void DelayTimerBase::OnScheduledTaskInvoked() {
137*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
138*6777b538SAndroid Build Coastguard Worker DCHECK(!delayed_task_handle_.IsValid()) << posted_from_.ToString();
139*6777b538SAndroid Build Coastguard Worker
140*6777b538SAndroid Build Coastguard Worker RunUserTask();
141*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted at this point.
142*6777b538SAndroid Build Coastguard Worker }
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker } // namespace internal
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker OneShotTimer::OneShotTimer() = default;
OneShotTimer(const TickClock * tick_clock)147*6777b538SAndroid Build Coastguard Worker OneShotTimer::OneShotTimer(const TickClock* tick_clock)
148*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(tick_clock) {}
149*6777b538SAndroid Build Coastguard Worker OneShotTimer::~OneShotTimer() = default;
150*6777b538SAndroid Build Coastguard Worker
Start(const Location & posted_from,TimeDelta delay,OnceClosure user_task)151*6777b538SAndroid Build Coastguard Worker void OneShotTimer::Start(const Location& posted_from,
152*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
153*6777b538SAndroid Build Coastguard Worker OnceClosure user_task) {
154*6777b538SAndroid Build Coastguard Worker user_task_ = std::move(user_task);
155*6777b538SAndroid Build Coastguard Worker StartInternal(posted_from, delay);
156*6777b538SAndroid Build Coastguard Worker }
157*6777b538SAndroid Build Coastguard Worker
FireNow()158*6777b538SAndroid Build Coastguard Worker void OneShotTimer::FireNow() {
159*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
160*6777b538SAndroid Build Coastguard Worker DCHECK(!task_runner_) << "FireNow() is incompatible with SetTaskRunner()";
161*6777b538SAndroid Build Coastguard Worker DCHECK(IsRunning());
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker RunUserTask();
164*6777b538SAndroid Build Coastguard Worker }
165*6777b538SAndroid Build Coastguard Worker
OnStop()166*6777b538SAndroid Build Coastguard Worker void OneShotTimer::OnStop() {
167*6777b538SAndroid Build Coastguard Worker user_task_.Reset();
168*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted after freeing
169*6777b538SAndroid Build Coastguard Worker // |user_task_|.
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker
RunUserTask()172*6777b538SAndroid Build Coastguard Worker void OneShotTimer::RunUserTask() {
173*6777b538SAndroid Build Coastguard Worker // Make a local copy of the task to run. The Stop method will reset the
174*6777b538SAndroid Build Coastguard Worker // |user_task_| member.
175*6777b538SAndroid Build Coastguard Worker OnceClosure task = std::move(user_task_);
176*6777b538SAndroid Build Coastguard Worker Stop();
177*6777b538SAndroid Build Coastguard Worker DCHECK(task);
178*6777b538SAndroid Build Coastguard Worker std::move(task).Run();
179*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted at this point.
180*6777b538SAndroid Build Coastguard Worker }
181*6777b538SAndroid Build Coastguard Worker
EnsureNonNullUserTask()182*6777b538SAndroid Build Coastguard Worker void OneShotTimer::EnsureNonNullUserTask() {
183*6777b538SAndroid Build Coastguard Worker DCHECK(user_task_);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker RepeatingTimer::RepeatingTimer() = default;
RepeatingTimer(const TickClock * tick_clock)187*6777b538SAndroid Build Coastguard Worker RepeatingTimer::RepeatingTimer(const TickClock* tick_clock)
188*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(tick_clock) {}
189*6777b538SAndroid Build Coastguard Worker RepeatingTimer::~RepeatingTimer() = default;
190*6777b538SAndroid Build Coastguard Worker
RepeatingTimer(const Location & posted_from,TimeDelta delay,RepeatingClosure user_task)191*6777b538SAndroid Build Coastguard Worker RepeatingTimer::RepeatingTimer(const Location& posted_from,
192*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
193*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task)
194*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(posted_from, delay),
195*6777b538SAndroid Build Coastguard Worker user_task_(std::move(user_task)) {}
RepeatingTimer(const Location & posted_from,TimeDelta delay,RepeatingClosure user_task,const TickClock * tick_clock)196*6777b538SAndroid Build Coastguard Worker RepeatingTimer::RepeatingTimer(const Location& posted_from,
197*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
198*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task,
199*6777b538SAndroid Build Coastguard Worker const TickClock* tick_clock)
200*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(posted_from, delay, tick_clock),
201*6777b538SAndroid Build Coastguard Worker user_task_(std::move(user_task)) {}
202*6777b538SAndroid Build Coastguard Worker
Start(const Location & posted_from,TimeDelta delay,RepeatingClosure user_task)203*6777b538SAndroid Build Coastguard Worker void RepeatingTimer::Start(const Location& posted_from,
204*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
205*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task) {
206*6777b538SAndroid Build Coastguard Worker user_task_ = std::move(user_task);
207*6777b538SAndroid Build Coastguard Worker StartInternal(posted_from, delay);
208*6777b538SAndroid Build Coastguard Worker }
209*6777b538SAndroid Build Coastguard Worker
OnStop()210*6777b538SAndroid Build Coastguard Worker void RepeatingTimer::OnStop() {}
211*6777b538SAndroid Build Coastguard Worker
RunUserTask()212*6777b538SAndroid Build Coastguard Worker void RepeatingTimer::RunUserTask() {
213*6777b538SAndroid Build Coastguard Worker // Make a local copy of the task to run in case the task destroy the timer
214*6777b538SAndroid Build Coastguard Worker // instance.
215*6777b538SAndroid Build Coastguard Worker RepeatingClosure task = user_task_;
216*6777b538SAndroid Build Coastguard Worker ScheduleNewTask(GetCurrentDelay());
217*6777b538SAndroid Build Coastguard Worker task.Run();
218*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted at this point.
219*6777b538SAndroid Build Coastguard Worker }
220*6777b538SAndroid Build Coastguard Worker
EnsureNonNullUserTask()221*6777b538SAndroid Build Coastguard Worker void RepeatingTimer::EnsureNonNullUserTask() {
222*6777b538SAndroid Build Coastguard Worker DCHECK(user_task_);
223*6777b538SAndroid Build Coastguard Worker }
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker RetainingOneShotTimer::RetainingOneShotTimer() = default;
RetainingOneShotTimer(const TickClock * tick_clock)226*6777b538SAndroid Build Coastguard Worker RetainingOneShotTimer::RetainingOneShotTimer(const TickClock* tick_clock)
227*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(tick_clock) {}
228*6777b538SAndroid Build Coastguard Worker RetainingOneShotTimer::~RetainingOneShotTimer() = default;
229*6777b538SAndroid Build Coastguard Worker
RetainingOneShotTimer(const Location & posted_from,TimeDelta delay,RepeatingClosure user_task)230*6777b538SAndroid Build Coastguard Worker RetainingOneShotTimer::RetainingOneShotTimer(const Location& posted_from,
231*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
232*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task)
233*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(posted_from, delay),
234*6777b538SAndroid Build Coastguard Worker user_task_(std::move(user_task)) {}
RetainingOneShotTimer(const Location & posted_from,TimeDelta delay,RepeatingClosure user_task,const TickClock * tick_clock)235*6777b538SAndroid Build Coastguard Worker RetainingOneShotTimer::RetainingOneShotTimer(const Location& posted_from,
236*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
237*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task,
238*6777b538SAndroid Build Coastguard Worker const TickClock* tick_clock)
239*6777b538SAndroid Build Coastguard Worker : internal::DelayTimerBase(posted_from, delay, tick_clock),
240*6777b538SAndroid Build Coastguard Worker user_task_(std::move(user_task)) {}
241*6777b538SAndroid Build Coastguard Worker
Start(const Location & posted_from,TimeDelta delay,RepeatingClosure user_task)242*6777b538SAndroid Build Coastguard Worker void RetainingOneShotTimer::Start(const Location& posted_from,
243*6777b538SAndroid Build Coastguard Worker TimeDelta delay,
244*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task) {
245*6777b538SAndroid Build Coastguard Worker user_task_ = std::move(user_task);
246*6777b538SAndroid Build Coastguard Worker StartInternal(posted_from, delay);
247*6777b538SAndroid Build Coastguard Worker }
248*6777b538SAndroid Build Coastguard Worker
OnStop()249*6777b538SAndroid Build Coastguard Worker void RetainingOneShotTimer::OnStop() {}
250*6777b538SAndroid Build Coastguard Worker
RunUserTask()251*6777b538SAndroid Build Coastguard Worker void RetainingOneShotTimer::RunUserTask() {
252*6777b538SAndroid Build Coastguard Worker // Make a local copy of the task to run in case the task destroys the timer
253*6777b538SAndroid Build Coastguard Worker // instance.
254*6777b538SAndroid Build Coastguard Worker RepeatingClosure task = user_task_;
255*6777b538SAndroid Build Coastguard Worker Stop();
256*6777b538SAndroid Build Coastguard Worker task.Run();
257*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted at this point.
258*6777b538SAndroid Build Coastguard Worker }
259*6777b538SAndroid Build Coastguard Worker
EnsureNonNullUserTask()260*6777b538SAndroid Build Coastguard Worker void RetainingOneShotTimer::EnsureNonNullUserTask() {
261*6777b538SAndroid Build Coastguard Worker DCHECK(user_task_);
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker DeadlineTimer::DeadlineTimer() = default;
265*6777b538SAndroid Build Coastguard Worker DeadlineTimer::~DeadlineTimer() = default;
266*6777b538SAndroid Build Coastguard Worker
Start(const Location & posted_from,TimeTicks deadline,OnceClosure user_task,subtle::DelayPolicy delay_policy)267*6777b538SAndroid Build Coastguard Worker void DeadlineTimer::Start(const Location& posted_from,
268*6777b538SAndroid Build Coastguard Worker TimeTicks deadline,
269*6777b538SAndroid Build Coastguard Worker OnceClosure user_task,
270*6777b538SAndroid Build Coastguard Worker subtle::DelayPolicy delay_policy) {
271*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
272*6777b538SAndroid Build Coastguard Worker AbandonScheduledTask();
273*6777b538SAndroid Build Coastguard Worker user_task_ = std::move(user_task);
274*6777b538SAndroid Build Coastguard Worker posted_from_ = posted_from;
275*6777b538SAndroid Build Coastguard Worker ScheduleNewTask(deadline, delay_policy);
276*6777b538SAndroid Build Coastguard Worker }
277*6777b538SAndroid Build Coastguard Worker
OnStop()278*6777b538SAndroid Build Coastguard Worker void DeadlineTimer::OnStop() {
279*6777b538SAndroid Build Coastguard Worker user_task_.Reset();
280*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted after freeing
281*6777b538SAndroid Build Coastguard Worker // |user_task_|.
282*6777b538SAndroid Build Coastguard Worker }
283*6777b538SAndroid Build Coastguard Worker
ScheduleNewTask(TimeTicks deadline,subtle::DelayPolicy delay_policy)284*6777b538SAndroid Build Coastguard Worker void DeadlineTimer::ScheduleNewTask(TimeTicks deadline,
285*6777b538SAndroid Build Coastguard Worker subtle::DelayPolicy delay_policy) {
286*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
287*6777b538SAndroid Build Coastguard Worker
288*6777b538SAndroid Build Coastguard Worker if (!timer_callback_) {
289*6777b538SAndroid Build Coastguard Worker timer_callback_ =
290*6777b538SAndroid Build Coastguard Worker BindRepeating(&DeadlineTimer::OnScheduledTaskInvoked, Unretained(this));
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker delayed_task_handle_ = GetTaskRunner()->PostCancelableDelayedTaskAt(
293*6777b538SAndroid Build Coastguard Worker base::subtle::PostDelayedTaskPassKey(), posted_from_, timer_callback_,
294*6777b538SAndroid Build Coastguard Worker deadline, delay_policy);
295*6777b538SAndroid Build Coastguard Worker }
296*6777b538SAndroid Build Coastguard Worker
OnScheduledTaskInvoked()297*6777b538SAndroid Build Coastguard Worker void DeadlineTimer::OnScheduledTaskInvoked() {
298*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
299*6777b538SAndroid Build Coastguard Worker DCHECK(!delayed_task_handle_.IsValid());
300*6777b538SAndroid Build Coastguard Worker
301*6777b538SAndroid Build Coastguard Worker // Make a local copy of the task to run. The Stop method will reset the
302*6777b538SAndroid Build Coastguard Worker // |user_task_| member.
303*6777b538SAndroid Build Coastguard Worker OnceClosure task = std::move(user_task_);
304*6777b538SAndroid Build Coastguard Worker Stop();
305*6777b538SAndroid Build Coastguard Worker std::move(task).Run();
306*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted at this point.
307*6777b538SAndroid Build Coastguard Worker }
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker MetronomeTimer::MetronomeTimer() = default;
310*6777b538SAndroid Build Coastguard Worker MetronomeTimer::~MetronomeTimer() = default;
311*6777b538SAndroid Build Coastguard Worker
MetronomeTimer(const Location & posted_from,TimeDelta interval,RepeatingClosure user_task,TimeTicks phase)312*6777b538SAndroid Build Coastguard Worker MetronomeTimer::MetronomeTimer(const Location& posted_from,
313*6777b538SAndroid Build Coastguard Worker TimeDelta interval,
314*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task,
315*6777b538SAndroid Build Coastguard Worker TimeTicks phase)
316*6777b538SAndroid Build Coastguard Worker : TimerBase(posted_from),
317*6777b538SAndroid Build Coastguard Worker interval_(interval),
318*6777b538SAndroid Build Coastguard Worker user_task_(user_task),
319*6777b538SAndroid Build Coastguard Worker phase_(phase) {}
320*6777b538SAndroid Build Coastguard Worker
Start(const Location & posted_from,TimeDelta interval,RepeatingClosure user_task,TimeTicks phase)321*6777b538SAndroid Build Coastguard Worker void MetronomeTimer::Start(const Location& posted_from,
322*6777b538SAndroid Build Coastguard Worker TimeDelta interval,
323*6777b538SAndroid Build Coastguard Worker RepeatingClosure user_task,
324*6777b538SAndroid Build Coastguard Worker TimeTicks phase) {
325*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
326*6777b538SAndroid Build Coastguard Worker user_task_ = std::move(user_task);
327*6777b538SAndroid Build Coastguard Worker posted_from_ = posted_from;
328*6777b538SAndroid Build Coastguard Worker interval_ = interval;
329*6777b538SAndroid Build Coastguard Worker phase_ = phase;
330*6777b538SAndroid Build Coastguard Worker
331*6777b538SAndroid Build Coastguard Worker Reset();
332*6777b538SAndroid Build Coastguard Worker }
333*6777b538SAndroid Build Coastguard Worker
OnStop()334*6777b538SAndroid Build Coastguard Worker void MetronomeTimer::OnStop() {
335*6777b538SAndroid Build Coastguard Worker user_task_.Reset();
336*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted after freeing
337*6777b538SAndroid Build Coastguard Worker // |user_task_|.
338*6777b538SAndroid Build Coastguard Worker }
339*6777b538SAndroid Build Coastguard Worker
Reset()340*6777b538SAndroid Build Coastguard Worker void MetronomeTimer::Reset() {
341*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
342*6777b538SAndroid Build Coastguard Worker DCHECK(user_task_);
343*6777b538SAndroid Build Coastguard Worker // We can't reuse the |scheduled_task_|, so abandon it and post a new one.
344*6777b538SAndroid Build Coastguard Worker AbandonScheduledTask();
345*6777b538SAndroid Build Coastguard Worker ScheduleNewTask();
346*6777b538SAndroid Build Coastguard Worker }
347*6777b538SAndroid Build Coastguard Worker
ScheduleNewTask()348*6777b538SAndroid Build Coastguard Worker void MetronomeTimer::ScheduleNewTask() {
349*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
350*6777b538SAndroid Build Coastguard Worker
351*6777b538SAndroid Build Coastguard Worker // The next wake up is scheduled at the next aligned time which is at least
352*6777b538SAndroid Build Coastguard Worker // `interval_ / 2` after now. `interval_ / 2` is added to avoid playing
353*6777b538SAndroid Build Coastguard Worker // "catch-up" if wake ups are late.
354*6777b538SAndroid Build Coastguard Worker TimeTicks deadline =
355*6777b538SAndroid Build Coastguard Worker (TimeTicks::Now() + interval_ / 2).SnappedToNextTick(phase_, interval_);
356*6777b538SAndroid Build Coastguard Worker
357*6777b538SAndroid Build Coastguard Worker if (!timer_callback_) {
358*6777b538SAndroid Build Coastguard Worker timer_callback_ = BindRepeating(&MetronomeTimer::OnScheduledTaskInvoked,
359*6777b538SAndroid Build Coastguard Worker Unretained(this));
360*6777b538SAndroid Build Coastguard Worker }
361*6777b538SAndroid Build Coastguard Worker delayed_task_handle_ = GetTaskRunner()->PostCancelableDelayedTaskAt(
362*6777b538SAndroid Build Coastguard Worker base::subtle::PostDelayedTaskPassKey(), posted_from_, timer_callback_,
363*6777b538SAndroid Build Coastguard Worker deadline, subtle::DelayPolicy::kPrecise);
364*6777b538SAndroid Build Coastguard Worker }
365*6777b538SAndroid Build Coastguard Worker
OnScheduledTaskInvoked()366*6777b538SAndroid Build Coastguard Worker void MetronomeTimer::OnScheduledTaskInvoked() {
367*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
368*6777b538SAndroid Build Coastguard Worker DCHECK(!delayed_task_handle_.IsValid());
369*6777b538SAndroid Build Coastguard Worker
370*6777b538SAndroid Build Coastguard Worker // Make a local copy of the task to run in case the task destroy the timer
371*6777b538SAndroid Build Coastguard Worker // instance.
372*6777b538SAndroid Build Coastguard Worker RepeatingClosure task = user_task_;
373*6777b538SAndroid Build Coastguard Worker ScheduleNewTask();
374*6777b538SAndroid Build Coastguard Worker std::move(task).Run();
375*6777b538SAndroid Build Coastguard Worker // No more member accesses here: |this| could be deleted at this point.
376*6777b538SAndroid Build Coastguard Worker }
377*6777b538SAndroid Build Coastguard Worker
378*6777b538SAndroid Build Coastguard Worker } // namespace base
379