[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 1 | // 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 | |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 5 | // OneShotTimer, RepeatingTimer and RetainingOneShotTimer provide a simple timer |
| 6 | // API. As the names suggest, OneShotTimer calls you back once after a time |
| 7 | // delay expires. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 8 | // RepeatingTimer on the other hand calls you back periodically with the |
| 9 | // prescribed time interval. |
Owen Min | 9bbee7d3 | 2019-04-29 15:31:40 | [diff] [blame] | 10 | // RetainingOneShotTimer doesn't repeat the task itself like RepeatingTimer, but |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 11 | // retains the given task after the time out. You can restart it with Reset |
| 12 | // again without giving new task to Start. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 13 | // |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 14 | // All of OneShotTimer, RepeatingTimer and RetainingOneShotTimer cancel the |
| 15 | // timer when they go out of scope, which makes it easy to ensure that you do |
| 16 | // not get called when your object has gone out of scope. Just instantiate a |
| 17 | // timer as a member variable of the class for which you wish to receive timer |
| 18 | // events. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 19 | // |
| 20 | // Sample RepeatingTimer usage: |
| 21 | // |
| 22 | // class MyClass { |
| 23 | // public: |
| 24 | // void StartDoingStuff() { |
Peter Kasting | 53fd6ee | 2021-10-05 20:40:48 | [diff] [blame] | 25 | // timer_.Start(FROM_HERE, Seconds(1), |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 26 | // this, &MyClass::DoStuff); |
| 27 | // } |
| 28 | // void StopDoingStuff() { |
| 29 | // timer_.Stop(); |
| 30 | // } |
| 31 | // private: |
| 32 | // void DoStuff() { |
| 33 | // // This method is called every second to do stuff. |
| 34 | // ... |
| 35 | // } |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 36 | // base::RepeatingTimer timer_; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 37 | // }; |
| 38 | // |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 39 | // Timers also support a Reset method, which allows you to easily defer the |
| 40 | // timer event until the timer delay passes once again. So, in the above |
| 41 | // example, if 0.5 seconds have already passed, calling Reset on |timer_| |
| 42 | // would postpone DoStuff by another 1 second. In other words, Reset is |
| 43 | // shorthand for calling Stop and then Start again with the same arguments. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 44 | // |
Gabriel Charette | e92ccc0 | 2019-01-19 14:13:05 | [diff] [blame] | 45 | // These APIs are not thread safe. When a method is called (except the |
| 46 | // constructor), all further method calls must be on the same sequence until |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 47 | // Stop(). Once stopped, it may be destroyed or restarted on another sequence. |
ossu | 87340af | 2017-07-06 09:02:15 | [diff] [blame] | 48 | // |
| 49 | // By default, the scheduled tasks will be run on the same sequence that the |
Gabriel Charette | e92ccc0 | 2019-01-19 14:13:05 | [diff] [blame] | 50 | // Timer was *started on*. To mock time in unit tests, some old tests used |
| 51 | // SetTaskRunner() to schedule the delay on a test-controlled TaskRunner. The |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame] | 52 | // modern and preferred approach to mock time is to use TaskEnvironment's |
Gabriel Charette | e92ccc0 | 2019-01-19 14:13:05 | [diff] [blame] | 53 | // MOCK_TIME mode. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 54 | |
| 55 | #ifndef BASE_TIMER_TIMER_H_ |
| 56 | #define BASE_TIMER_TIMER_H_ |
| 57 | |
| 58 | // IMPORTANT: If you change timer code, make sure that all tests (including |
| 59 | // disabled ones) from timer_unittests.cc pass locally. Some are disabled |
| 60 | // because they're flaky on the buildbot, but when you run them locally you |
| 61 | // should be able to tell the difference. |
| 62 | |
| 63 | #include "base/base_export.h" |
| 64 | #include "base/bind.h" |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 65 | #include "base/callback.h" |
danakj | db9ae794 | 2020-11-11 16:01:35 | [diff] [blame] | 66 | #include "base/callback_helpers.h" |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 67 | #include "base/location.h" |
avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 68 | #include "base/macros.h" |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 69 | #include "base/sequence_checker.h" |
Patrick Monette | 643cdf6 | 2021-10-15 19:13:42 | [diff] [blame^] | 70 | #include "base/task/sequenced_task_runner.h" |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 71 | #include "base/time/time.h" |
| 72 | |
| 73 | namespace base { |
| 74 | |
jameswest | 6e0c8d2 | 2016-11-15 05:19:54 | [diff] [blame] | 75 | class TickClock; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 76 | |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 77 | namespace internal { |
| 78 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 79 | class TaskDestructionDetector; |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 80 | |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 81 | //----------------------------------------------------------------------------- |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 82 | // This class wraps TaskRunner::PostDelayedTask to manage delayed and repeating |
| 83 | // tasks. See meta comment above for thread-safety requirements. |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 84 | // Do not use this class directly. Use one of OneShotTimer, RepeatingTimer or |
| 85 | // RetainingOneShotTimer. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 86 | // |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 87 | class BASE_EXPORT TimerBase { |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 88 | public: |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 89 | // Constructs a timer. Start must be called later to set task info. |
| 90 | // If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get |
| 91 | // TimeTicks when scheduling tasks. |
| 92 | TimerBase(); |
| 93 | explicit TimerBase(const TickClock* tick_clock); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 94 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 95 | // Construct a timer with task info. |
| 96 | // If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get |
| 97 | // TimeTicks when scheduling tasks. |
| 98 | TimerBase(const Location& posted_from, TimeDelta delay); |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 99 | TimerBase(const Location& posted_from, |
| 100 | TimeDelta delay, |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 101 | const TickClock* tick_clock); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 102 | |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 103 | TimerBase(const TimerBase&) = delete; |
| 104 | TimerBase& operator=(const TimerBase&) = delete; |
| 105 | |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 106 | virtual ~TimerBase(); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 107 | |
| 108 | // Returns true if the timer is running (i.e., not stopped). |
tzik | 84db891 | 2018-06-19 06:08:54 | [diff] [blame] | 109 | bool IsRunning() const; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 110 | |
| 111 | // Returns the current delay for this timer. |
tzik | 84db891 | 2018-06-19 06:08:54 | [diff] [blame] | 112 | TimeDelta GetCurrentDelay() const; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 113 | |
Gabriel Charette | e92ccc0 | 2019-01-19 14:13:05 | [diff] [blame] | 114 | // Sets the task runner on which the delayed task should be scheduled when |
| 115 | // this Timer is running. This method can only be called while this Timer |
| 116 | // isn't running. This is an alternative (old) approach to mock time in tests. |
| 117 | // The modern and preferred approach is to use |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame] | 118 | // TaskEnvironment::TimeSource::MOCK_TIME. To avoid racy usage of Timer, |
Gabriel Charette | e92ccc0 | 2019-01-19 14:13:05 | [diff] [blame] | 119 | // |task_runner| must run tasks on the same sequence which this Timer is bound |
Gabriel Charette | c9a37f0 | 2019-07-15 22:32:02 | [diff] [blame] | 120 | // to (started from). TODO(gab): Migrate all callers to |
Gabriel Charette | 694c3c33 | 2019-08-19 14:53:05 | [diff] [blame] | 121 | // TaskEnvironment::TimeSource::MOCK_TIME. |
tzik | 84db891 | 2018-06-19 06:08:54 | [diff] [blame] | 122 | virtual void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner); |
petrcermak | 7652da6d | 2014-11-06 02:17:57 | [diff] [blame] | 123 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 124 | // Call this method to stop and cancel the timer. It is a no-op if the timer |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 125 | // is not running. |
[email protected] | 9df013b | 2014-03-13 22:04:39 | [diff] [blame] | 126 | virtual void Stop(); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 127 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 128 | // Abandons the scheduled task (if any) and stops the timer (if running). |
ossu | 87340af | 2017-07-06 09:02:15 | [diff] [blame] | 129 | void AbandonAndStop() { |
| 130 | AbandonScheduledTask(); |
| 131 | |
| 132 | Stop(); |
| 133 | // No more member accesses here: |this| could be deleted at this point. |
| 134 | } |
| 135 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 136 | // Call this method to reset the timer delay. The user task must be set. If |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 137 | // the timer is not running, this will start it by posting a task. |
[email protected] | 9df013b | 2014-03-13 22:04:39 | [diff] [blame] | 138 | virtual void Reset(); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 139 | |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 140 | const TimeTicks& desired_run_time() const { return desired_run_time_; } |
| 141 | |
| 142 | protected: |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 143 | virtual void OnStop() = 0; |
| 144 | virtual void RunUserTask() = 0; |
| 145 | |
tzik | f550a61 | 2018-07-12 02:25:34 | [diff] [blame] | 146 | // The task runner on which the task should be scheduled. If it is null, the |
| 147 | // task runner for the current sequence will be used. |
| 148 | scoped_refptr<SequencedTaskRunner> task_runner_; |
| 149 | |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 150 | // Timer isn't thread-safe and while it is running, it must only be used on |
| 151 | // the same sequence until fully Stop()'ed. Once stopped, it may be destroyed |
| 152 | // or restarted on another sequence. |
| 153 | SEQUENCE_CHECKER(sequence_checker_); |
tzik | f550a61 | 2018-07-12 02:25:34 | [diff] [blame] | 154 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 155 | // Schedules |OnScheduledTaskInvoked()| to run on the current sequence with |
| 156 | // the given |delay|. |scheduled_run_time_| and |desired_run_time_| are reset |
| 157 | // to Now() + delay. |
| 158 | void ScheduleNewTask(TimeDelta delay); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 159 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 160 | void StartInternal(const Location& posted_from, TimeDelta delay); |
| 161 | |
| 162 | private: |
| 163 | friend class BaseTimerTaskInternal; |
| 164 | |
jsbell | 763cd40 | 2015-12-17 00:38:27 | [diff] [blame] | 165 | // Returns the task runner on which the task should be scheduled. If the |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 166 | // corresponding |task_runner_| field is null, the task runner for the current |
| 167 | // sequence is returned. |
| 168 | scoped_refptr<SequencedTaskRunner> GetTaskRunner(); |
petrcermak | 7652da6d | 2014-11-06 02:17:57 | [diff] [blame] | 169 | |
Patrick Monette | 400b0514 | 2021-04-21 22:28:35 | [diff] [blame] | 170 | // Returns the current tick count. |
| 171 | TimeTicks Now() const; |
| 172 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 173 | // Disables the scheduled task and abandon it so that it no longer refers back |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 174 | // to this object. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 175 | void AbandonScheduledTask(); |
| 176 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 177 | // Called when the scheduled task is invoked. Will run the |user_task| if the |
| 178 | // timer is still running and |desired_run_time_| was reached. |
| 179 | // |task_destruction_detector| is owned by the callback to detect when the |
| 180 | // scheduled task is deleted before being executed. |
| 181 | void OnScheduledTaskInvoked( |
| 182 | std::unique_ptr<TaskDestructionDetector> task_destruction_detector); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 183 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 184 | // Detects when the scheduled task is deleted before being executed. Null when |
| 185 | // there is no scheduled task. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 186 | TaskDestructionDetector* task_destruction_detector_ |
| 187 | GUARDED_BY_CONTEXT(sequence_checker_); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 188 | |
| 189 | // Location in user code. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 190 | Location posted_from_ GUARDED_BY_CONTEXT(sequence_checker_); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 191 | // Delay requested by user. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 192 | TimeDelta delay_ GUARDED_BY_CONTEXT(sequence_checker_); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 193 | |
Patrick Monette | 57d1c18d | 2021-04-22 00:50:44 | [diff] [blame] | 194 | // The time at which the scheduled task is expected to fire. This time can be |
| 195 | // null if the task must be run immediately. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 196 | TimeTicks scheduled_run_time_ GUARDED_BY_CONTEXT(sequence_checker_); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 197 | |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 198 | // The desired run time of |user_task_|. The user may update this at any time, |
| 199 | // even if their previous request has not run yet. If |desired_run_time_| is |
| 200 | // greater than |scheduled_run_time_|, a continuation task will be posted to |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 201 | // wait for the remaining time. This allows us to reuse the pending task so as |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 202 | // not to flood the delayed queues with orphaned tasks when the user code |
[email protected] | d0451935 | 2013-12-04 20:05:45 | [diff] [blame] | 203 | // excessively Stops and Starts the timer. This time can be a "zero" TimeTicks |
| 204 | // if the task must be run immediately. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 205 | TimeTicks desired_run_time_ GUARDED_BY_CONTEXT(sequence_checker_); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 206 | |
jameswest | 6e0c8d2 | 2016-11-15 05:19:54 | [diff] [blame] | 207 | // The tick clock used to calculate the run time for scheduled tasks. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 208 | const TickClock* const tick_clock_ GUARDED_BY_CONTEXT(sequence_checker_); |
jameswest | 6e0c8d2 | 2016-11-15 05:19:54 | [diff] [blame] | 209 | |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 210 | // If true, |user_task_| is scheduled to run sometime in the future. |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 211 | bool is_running_ GUARDED_BY_CONTEXT(sequence_checker_); |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 212 | |
Patrick Monette | c4d306d | 2021-06-23 19:15:25 | [diff] [blame] | 213 | WeakPtrFactory<TimerBase> weak_ptr_factory_ |
| 214 | GUARDED_BY_CONTEXT(sequence_checker_){this}; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 215 | }; |
| 216 | |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 217 | } // namespace internal |
| 218 | |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 219 | //----------------------------------------------------------------------------- |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 220 | // A simple, one-shot timer. See usage notes at the top of the file. |
tzik | d93bb086 | 2018-07-19 11:54:14 | [diff] [blame] | 221 | class BASE_EXPORT OneShotTimer : public internal::TimerBase { |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 222 | public: |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 223 | OneShotTimer(); |
| 224 | explicit OneShotTimer(const TickClock* tick_clock); |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 225 | |
| 226 | OneShotTimer(const OneShotTimer&) = delete; |
| 227 | OneShotTimer& operator=(const OneShotTimer&) = delete; |
| 228 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 229 | ~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 Lin | 1b43b40 | 2020-02-27 17:53:39 | [diff] [blame] | 239 | // |receiver->*method|. |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 240 | template <class Receiver> |
| 241 | void Start(const Location& posted_from, |
| 242 | TimeDelta delay, |
| 243 | Receiver* receiver, |
| 244 | void (Receiver::*method)()) { |
| 245 | Start(posted_from, delay, BindOnce(method, Unretained(receiver))); |
| 246 | } |
tzik | f550a61 | 2018-07-12 02:25:34 | [diff] [blame] | 247 | |
| 248 | // Run the scheduled task immediately, and stop the timer. The timer needs to |
| 249 | // be running. |
| 250 | void FireNow(); |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 251 | |
| 252 | private: |
| 253 | void OnStop() final; |
| 254 | void RunUserTask() final; |
| 255 | |
| 256 | OnceClosure user_task_; |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 257 | }; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 258 | |
| 259 | //----------------------------------------------------------------------------- |
| 260 | // A simple, repeating timer. See usage notes at the top of the file. |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 261 | class BASE_EXPORT RepeatingTimer : public internal::TimerBase { |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 262 | public: |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 263 | RepeatingTimer(); |
| 264 | explicit RepeatingTimer(const TickClock* tick_clock); |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 265 | |
| 266 | RepeatingTimer(const RepeatingTimer&) = delete; |
| 267 | RepeatingTimer& operator=(const RepeatingTimer&) = delete; |
| 268 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 269 | ~RepeatingTimer() override; |
tzik | 524daae9 | 2018-07-05 02:52:02 | [diff] [blame] | 270 | |
| 271 | RepeatingTimer(const Location& posted_from, |
| 272 | TimeDelta delay, |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 273 | RepeatingClosure user_task); |
tzik | 524daae9 | 2018-07-05 02:52:02 | [diff] [blame] | 274 | RepeatingTimer(const Location& posted_from, |
| 275 | TimeDelta delay, |
| 276 | RepeatingClosure user_task, |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 277 | const TickClock* tick_clock); |
| 278 | |
| 279 | // Start the timer to run at the given |delay| from now. If the timer is |
| 280 | // already running, it will be replaced to call the given |user_task|. |
| 281 | virtual void Start(const Location& posted_from, |
| 282 | TimeDelta delay, |
| 283 | RepeatingClosure user_task); |
| 284 | |
| 285 | // Start the timer to run at the given |delay| from now. If the timer is |
| 286 | // already running, it will be replaced to call a task formed from |
Ming-Chuan Lin | 1b43b40 | 2020-02-27 17:53:39 | [diff] [blame] | 287 | // |receiver->*method|. |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 288 | template <class Receiver> |
| 289 | void Start(const Location& posted_from, |
| 290 | TimeDelta delay, |
| 291 | Receiver* receiver, |
| 292 | void (Receiver::*method)()) { |
| 293 | Start(posted_from, delay, BindRepeating(method, Unretained(receiver))); |
| 294 | } |
| 295 | |
| 296 | const RepeatingClosure& user_task() const { return user_task_; } |
| 297 | |
| 298 | private: |
| 299 | // Mark this final, so that the destructor can call this safely. |
| 300 | void OnStop() final; |
| 301 | |
| 302 | void RunUserTask() override; |
| 303 | |
| 304 | RepeatingClosure user_task_; |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 305 | }; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 306 | |
| 307 | //----------------------------------------------------------------------------- |
danakj | 8c1f3bf | 2019-12-11 22:21:02 | [diff] [blame] | 308 | // A simple, one-shot timer with the retained user_task which is reused for |
| 309 | // multiple invocations of Start(). See usage notes at the top of the file. |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 310 | class BASE_EXPORT RetainingOneShotTimer : public internal::TimerBase { |
tzik | 57c66e3 | 2018-07-02 08:02:57 | [diff] [blame] | 311 | public: |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 312 | RetainingOneShotTimer(); |
| 313 | explicit RetainingOneShotTimer(const TickClock* tick_clock); |
Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 314 | |
| 315 | RetainingOneShotTimer(const RetainingOneShotTimer&) = delete; |
| 316 | RetainingOneShotTimer& operator=(const RetainingOneShotTimer&) = delete; |
| 317 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 318 | ~RetainingOneShotTimer() override; |
tzik | 524daae9 | 2018-07-05 02:52:02 | [diff] [blame] | 319 | |
| 320 | RetainingOneShotTimer(const Location& posted_from, |
| 321 | TimeDelta delay, |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 322 | RepeatingClosure user_task); |
tzik | 524daae9 | 2018-07-05 02:52:02 | [diff] [blame] | 323 | RetainingOneShotTimer(const Location& posted_from, |
| 324 | TimeDelta delay, |
| 325 | RepeatingClosure user_task, |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 326 | const TickClock* tick_clock); |
| 327 | |
| 328 | // Start the timer to run at the given |delay| from now. If the timer is |
| 329 | // already running, it will be replaced to call the given |user_task|. |
| 330 | virtual void Start(const Location& posted_from, |
| 331 | TimeDelta delay, |
| 332 | RepeatingClosure user_task); |
| 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 a task formed from |
Ming-Chuan Lin | 1b43b40 | 2020-02-27 17:53:39 | [diff] [blame] | 336 | // |receiver->*method|. |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 337 | template <class Receiver> |
| 338 | void Start(const Location& posted_from, |
| 339 | TimeDelta delay, |
| 340 | Receiver* receiver, |
| 341 | void (Receiver::*method)()) { |
| 342 | Start(posted_from, delay, BindRepeating(method, Unretained(receiver))); |
| 343 | } |
| 344 | |
| 345 | const RepeatingClosure& user_task() const { return user_task_; } |
| 346 | |
tzik | f3336c9 | 2018-07-25 03:15:50 | [diff] [blame] | 347 | private: |
| 348 | // Mark this final, so that the destructor can call this safely. |
| 349 | void OnStop() final; |
| 350 | |
| 351 | void RunUserTask() override; |
| 352 | |
| 353 | RepeatingClosure user_task_; |
tzik | 57c66e3 | 2018-07-02 08:02:57 | [diff] [blame] | 354 | }; |
| 355 | |
| 356 | //----------------------------------------------------------------------------- |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 357 | // A Delay timer is like The Button from Lost. Once started, you have to keep |
gab | 4e844bb | 2017-06-01 16:23:36 | [diff] [blame] | 358 | // calling Reset otherwise it will call the given method on the sequence it was |
| 359 | // initially Reset() from. |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 360 | // |
| 361 | // Once created, it is inactive until Reset is called. Once |delay| seconds have |
| 362 | // passed since the last call to Reset, the callback is made. Once the callback |
| 363 | // has been made, it's inactive until Reset is called again. |
| 364 | // |
| 365 | // If destroyed, the timeout is canceled and will not occur even if already |
| 366 | // inflight. |
tzik | 32c3bcd | 2018-07-09 04:39:38 | [diff] [blame] | 367 | class DelayTimer { |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 368 | public: |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 369 | template <class Receiver> |
Brett Wilson | 8e88b31 | 2017-09-12 05:22:16 | [diff] [blame] | 370 | DelayTimer(const Location& posted_from, |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 371 | TimeDelta delay, |
| 372 | Receiver* receiver, |
danakj | 8c3eb80 | 2015-09-24 07:53:00 | [diff] [blame] | 373 | void (Receiver::*method)()) |
jameswest | 6e0c8d2 | 2016-11-15 05:19:54 | [diff] [blame] | 374 | : DelayTimer(posted_from, delay, receiver, method, nullptr) {} |
| 375 | |
| 376 | template <class Receiver> |
Brett Wilson | 8e88b31 | 2017-09-12 05:22:16 | [diff] [blame] | 377 | DelayTimer(const Location& posted_from, |
jameswest | 6e0c8d2 | 2016-11-15 05:19:54 | [diff] [blame] | 378 | TimeDelta delay, |
| 379 | Receiver* receiver, |
| 380 | void (Receiver::*method)(), |
Greg Thompson | aa48ce8d | 2018-04-03 06:11:43 | [diff] [blame] | 381 | const TickClock* tick_clock) |
tzik | 32c3bcd | 2018-07-09 04:39:38 | [diff] [blame] | 382 | : timer_(posted_from, |
| 383 | delay, |
| 384 | BindRepeating(method, Unretained(receiver)), |
| 385 | tick_clock) {} |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 386 | |
Peter Boström | 75cd3c0 | 2021-09-28 15:23:18 | [diff] [blame] | 387 | DelayTimer(const DelayTimer&) = delete; |
| 388 | DelayTimer& operator=(const DelayTimer&) = delete; |
| 389 | |
tzik | 32c3bcd | 2018-07-09 04:39:38 | [diff] [blame] | 390 | void Reset() { timer_.Reset(); } |
| 391 | |
| 392 | private: |
| 393 | RetainingOneShotTimer timer_; |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 394 | }; |
| 395 | |
[email protected] | 89bf27e | 2013-06-27 18:04:56 | [diff] [blame] | 396 | } // namespace base |
| 397 | |
| 398 | #endif // BASE_TIMER_TIMER_H_ |