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