1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // 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. 14 // - 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. 23 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). 28 // 29 // Sample RepeatingTimer usage: 30 // 31 // class MyClass { 32 // public: 33 // void StartDoingStuff() { 34 // timer_.Start(FROM_HERE, base::Seconds(1), 35 // this, &MyClass::DoStuff); 36 // // 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)); 40 // } 41 // void StopDoingStuff() { 42 // timer_.Stop(); 43 // } 44 // private: 45 // void DoStuff() { 46 // // This method is called every second to do stuff. 47 // ... 48 // } 49 // base::RepeatingTimer timer_; 50 // }; 51 // 52 // 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 54 // Stop(). Once stopped, it may be destroyed or restarted on another sequence. 55 // 56 // By default, the scheduled tasks will be run on the same sequence that the 57 // 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 59 // modern and preferred approach to mock time is to use TaskEnvironment's 60 // MOCK_TIME mode. 61 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" 71 #include "base/functional/bind.h" 72 #include "base/functional/callback.h" 73 #include "base/functional/callback_helpers.h" 74 #include "base/location.h" 75 #include "base/memory/raw_ptr.h" 76 #include "base/sequence_checker.h" 77 #include "base/task/delayed_task_handle.h" 78 #include "base/task/sequenced_task_runner.h" 79 #include "base/time/time.h" 80 #include "base/types/strong_alias.h" 81 82 namespace base { 83 84 class TickClock; 85 86 namespace internal { 87 88 // This class wraps logic shared by all timers. 89 class BASE_EXPORT TimerBase { 90 public: 91 TimerBase(const TimerBase&) = delete; 92 TimerBase& operator=(const TimerBase&) = delete; 93 94 virtual ~TimerBase(); 95 96 // Returns true if the timer is running (i.e., not stopped). 97 bool IsRunning() const; 98 99 // Sets the task runner on which the delayed task should be scheduled when 100 // this Timer is running. This method can only be called while this Timer 101 // isn't running. If this is used to mock time in tests, the modern and 102 // preferred approach is to use TaskEnvironment::TimeSource::MOCK_TIME. To 103 // avoid racy usage of Timer, |task_runner| must run tasks on the same 104 // sequence which this Timer is bound to (started from). TODO(gab): Migrate 105 // callers using this as a test seam to 106 // TaskEnvironment::TimeSource::MOCK_TIME. 107 virtual void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner); 108 109 // Call this method to stop the timer and cancel all previously scheduled 110 // tasks. It is a no-op if the timer is not running. 111 virtual void Stop(); 112 113 protected: 114 // Constructs a timer. Start must be called later to set task info. 115 explicit TimerBase(const Location& posted_from = Location()); 116 117 virtual void OnStop() = 0; 118 119 // Disables the scheduled task and abandons it so that it no longer refers 120 // back to this object. 121 void AbandonScheduledTask(); 122 123 // Returns the task runner on which the task should be scheduled. If the 124 // corresponding |task_runner_| field is null, the task runner for the current 125 // sequence is returned. 126 scoped_refptr<SequencedTaskRunner> GetTaskRunner(); 127 128 // The task runner on which the task should be scheduled. If it is null, the 129 // task runner for the current sequence will be used. 130 scoped_refptr<SequencedTaskRunner> task_runner_; 131 132 // Timer isn't thread-safe and while it is running, it must only be used on 133 // the same sequence until fully Stop()'ed. Once stopped, it may be destroyed 134 // or restarted on another sequence. 135 SEQUENCE_CHECKER(sequence_checker_); 136 137 // Location in user code. 138 Location posted_from_ GUARDED_BY_CONTEXT(sequence_checker_); 139 140 // The handle to the posted delayed task. 141 DelayedTaskHandle delayed_task_handle_ GUARDED_BY_CONTEXT(sequence_checker_); 142 143 // Callback invoked when the timer is ready. This is saved as a member to 144 // avoid rebinding every time the Timer fires. Lazy initialized the first time 145 // the Timer is started. 146 RepeatingClosure timer_callback_; 147 }; 148 149 //----------------------------------------------------------------------------- 150 // This class wraps logic shared by (Retaining)OneShotTimer and RepeatingTimer. 151 class BASE_EXPORT DelayTimerBase : public TimerBase { 152 public: 153 DelayTimerBase(const DelayTimerBase&) = delete; 154 DelayTimerBase& operator=(const DelayTimerBase&) = delete; 155 156 ~DelayTimerBase() override; 157 158 // Returns the current delay for this timer. 159 TimeDelta GetCurrentDelay() const; 160 161 // Call this method to reset the timer delay. The user task must be set. If 162 // the timer is not running, this will start it by posting a task. 163 virtual void Reset(); 164 165 // DEPRECATED. Call Stop() instead. 166 // TODO(1262205): Remove this method and all callers. 167 void AbandonAndStop(); 168 desired_run_time()169 TimeTicks desired_run_time() const { 170 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 171 return desired_run_time_; 172 } 173 174 protected: 175 // Constructs a timer. Start must be called later to set task info. 176 // If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get 177 // TimeTicks when scheduling tasks. 178 explicit DelayTimerBase(const TickClock* tick_clock = nullptr); 179 180 // Construct a timer with task info. 181 // If |tick_clock| is provided, it is used instead of TimeTicks::Now() to get 182 // TimeTicks when scheduling tasks. 183 DelayTimerBase(const Location& posted_from, 184 TimeDelta delay, 185 const TickClock* tick_clock = nullptr); 186 187 virtual void RunUserTask() = 0; 188 189 // Schedules |OnScheduledTaskInvoked()| to run on the current sequence with 190 // the given |delay|. |desired_run_time_| is reset to Now() + delay. 191 void ScheduleNewTask(TimeDelta delay); 192 193 void StartInternal(const Location& posted_from, TimeDelta delay); 194 195 private: 196 // DCHECKs that the user task is not null. Used to diagnose a recurring bug 197 // where Reset() is called on a OneShotTimer that has already fired. 198 virtual void EnsureNonNullUserTask() = 0; 199 200 // Returns the current tick count. 201 TimeTicks Now() const; 202 203 // Called when the scheduled task is invoked. Will run the |user_task| if the 204 // timer is still running and |desired_run_time_| was reached. 205 void OnScheduledTaskInvoked(); 206 207 // Delay requested by user. 208 TimeDelta delay_ GUARDED_BY_CONTEXT(sequence_checker_); 209 210 // The desired run time of |user_task_|. The user may update this at any time, 211 // even if their previous request has not run yet. This time can be a "zero" 212 // TimeTicks if the task must be run immediately. 213 TimeTicks desired_run_time_ GUARDED_BY_CONTEXT(sequence_checker_); 214 215 // The tick clock used to calculate the run time for scheduled tasks. 216 const raw_ptr<const TickClock> tick_clock_ 217 GUARDED_BY_CONTEXT(sequence_checker_); 218 }; 219 220 } // namespace internal 221 222 //----------------------------------------------------------------------------- 223 // A simple, one-shot timer. See usage notes at the top of the file. 224 class BASE_EXPORT OneShotTimer : public internal::DelayTimerBase { 225 public: 226 OneShotTimer(); 227 explicit OneShotTimer(const TickClock* tick_clock); 228 229 OneShotTimer(const OneShotTimer&) = delete; 230 OneShotTimer& operator=(const OneShotTimer&) = delete; 231 232 ~OneShotTimer() override; 233 234 // Start the timer to run at the given |delay| from now. If the timer is 235 // already running, it will be replaced to call the given |user_task|. 236 virtual void Start(const Location& posted_from, 237 TimeDelta delay, 238 OnceClosure user_task); 239 240 // Start the timer to run at the given |delay| from now. If the timer is 241 // already running, it will be replaced to call a task formed from 242 // |receiver->*method|. 243 template <class Receiver> Start(const Location & posted_from,TimeDelta delay,Receiver * receiver,void (Receiver::* method)())244 void Start(const Location& posted_from, 245 TimeDelta delay, 246 Receiver* receiver, 247 void (Receiver::*method)()) { 248 Start(posted_from, delay, BindOnce(method, Unretained(receiver))); 249 } 250 251 // Run the scheduled task immediately, and stop the timer. The timer needs to 252 // be running. 253 virtual void FireNow(); 254 255 private: 256 void OnStop() final; 257 void RunUserTask() final; 258 void EnsureNonNullUserTask() final; 259 260 OnceClosure user_task_; 261 }; 262 263 //----------------------------------------------------------------------------- 264 // A simple, repeating timer. See usage notes at the top of the file. 265 class BASE_EXPORT RepeatingTimer : public internal::DelayTimerBase { 266 public: 267 RepeatingTimer(); 268 explicit RepeatingTimer(const TickClock* tick_clock); 269 270 RepeatingTimer(const RepeatingTimer&) = delete; 271 RepeatingTimer& operator=(const RepeatingTimer&) = delete; 272 273 ~RepeatingTimer() override; 274 275 RepeatingTimer(const Location& posted_from, 276 TimeDelta delay, 277 RepeatingClosure user_task); 278 RepeatingTimer(const Location& posted_from, 279 TimeDelta delay, 280 RepeatingClosure user_task, 281 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 291 // |receiver->*method|. 292 template <class Receiver> Start(const Location & posted_from,TimeDelta delay,Receiver * receiver,void (Receiver::* method)())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 user_task()300 const RepeatingClosure& user_task() const { return user_task_; } 301 302 private: 303 // Mark this final, so that the destructor can call this safely. 304 void OnStop() final; 305 void RunUserTask() override; 306 void EnsureNonNullUserTask() final; 307 308 RepeatingClosure user_task_; 309 }; 310 311 //----------------------------------------------------------------------------- 312 // A simple, one-shot timer with the retained |user_task| which is reused when 313 // Reset() is invoked. See usage notes at the top of the file. 314 class BASE_EXPORT RetainingOneShotTimer : public internal::DelayTimerBase { 315 public: 316 RetainingOneShotTimer(); 317 explicit RetainingOneShotTimer(const TickClock* tick_clock); 318 319 RetainingOneShotTimer(const RetainingOneShotTimer&) = delete; 320 RetainingOneShotTimer& operator=(const RetainingOneShotTimer&) = delete; 321 322 ~RetainingOneShotTimer() override; 323 324 RetainingOneShotTimer(const Location& posted_from, 325 TimeDelta delay, 326 RepeatingClosure user_task); 327 RetainingOneShotTimer(const Location& posted_from, 328 TimeDelta delay, 329 RepeatingClosure user_task, 330 const TickClock* tick_clock); 331 332 // Start the timer to run at the given |delay| from now. If the timer is 333 // already running, it will be replaced to call the given |user_task|. 334 virtual void Start(const Location& posted_from, 335 TimeDelta delay, 336 RepeatingClosure user_task); 337 338 // Start the timer to run at the given |delay| from now. If the timer is 339 // already running, it will be replaced to call a task formed from 340 // |receiver->*method|. 341 template <class Receiver> Start(const Location & posted_from,TimeDelta delay,Receiver * receiver,void (Receiver::* method)())342 void Start(const Location& posted_from, 343 TimeDelta delay, 344 Receiver* receiver, 345 void (Receiver::*method)()) { 346 Start(posted_from, delay, BindRepeating(method, Unretained(receiver))); 347 } 348 user_task()349 const RepeatingClosure& user_task() const { return user_task_; } 350 351 private: 352 // Mark this final, so that the destructor can call this safely. 353 void OnStop() final; 354 void RunUserTask() override; 355 void EnsureNonNullUserTask() final; 356 357 RepeatingClosure user_task_; 358 }; 359 360 //----------------------------------------------------------------------------- 361 // A Delay timer is like The Button from Lost. Once started, you have to keep 362 // calling Reset otherwise it will call the given method on the sequence it was 363 // initially Reset() from. 364 // 365 // Once created, it is inactive until Reset is called. Once |delay| seconds have 366 // passed since the last call to Reset, the callback is made. Once the callback 367 // has been made, it's inactive until Reset is called again. 368 // 369 // If destroyed, the timeout is canceled and will not occur even if already 370 // inflight. 371 class DelayTimer { 372 public: 373 template <class Receiver> DelayTimer(const Location & posted_from,TimeDelta delay,Receiver * receiver,void (Receiver::* method)())374 DelayTimer(const Location& posted_from, 375 TimeDelta delay, 376 Receiver* receiver, 377 void (Receiver::*method)()) 378 : DelayTimer(posted_from, delay, receiver, method, nullptr) {} 379 380 template <class Receiver> DelayTimer(const Location & posted_from,TimeDelta delay,Receiver * receiver,void (Receiver::* method)(),const TickClock * tick_clock)381 DelayTimer(const Location& posted_from, 382 TimeDelta delay, 383 Receiver* receiver, 384 void (Receiver::*method)(), 385 const TickClock* tick_clock) 386 : timer_(posted_from, 387 delay, 388 BindRepeating(method, Unretained(receiver)), 389 tick_clock) {} 390 391 DelayTimer(const DelayTimer&) = delete; 392 DelayTimer& operator=(const DelayTimer&) = delete; 393 Reset()394 void Reset() { timer_.Reset(); } 395 396 private: 397 RetainingOneShotTimer timer_; 398 }; 399 400 //----------------------------------------------------------------------------- 401 // A one-shot timer that attempts to run |user_task| some time near specified 402 // deadline. See usage notes at the top of the file. 403 class BASE_EXPORT DeadlineTimer : public internal::TimerBase { 404 public: 405 DeadlineTimer(); 406 ~DeadlineTimer() override; 407 408 DeadlineTimer(const DeadlineTimer&) = delete; 409 DeadlineTimer& operator=(const DeadlineTimer&) = delete; 410 411 // Start the timer to run |user_task| near the specified |deadline| following 412 // |delay_policy| If the timer is already running, it will be replaced to call 413 // the given |user_task|. 414 void Start(const Location& posted_from, 415 TimeTicks deadline, 416 OnceClosure user_task, 417 subtle::DelayPolicy delay_policy = 418 subtle::DelayPolicy::kFlexiblePreferEarly); 419 420 // Start the timer to run |user_task| near the specified |deadline|. If the 421 // timer is already running, it will be replaced to call a task formed from 422 // |receiver->*method|. 423 template <class Receiver> 424 void Start(const Location& posted_from, 425 TimeTicks deadline, 426 Receiver* receiver, 427 void (Receiver::*method)(), 428 subtle::DelayPolicy delay_policy = 429 subtle::DelayPolicy::kFlexiblePreferEarly) { 430 Start(posted_from, deadline, BindOnce(method, Unretained(receiver)), 431 delay_policy); 432 } 433 434 protected: 435 void OnStop() override; 436 437 // Schedules |OnScheduledTaskInvoked()| to run on the current sequence at 438 // the given |deadline|. 439 void ScheduleNewTask(TimeTicks deadline, subtle::DelayPolicy delay_policy); 440 441 private: 442 // Called when the scheduled task is invoked to run the |user_task|. 443 void OnScheduledTaskInvoked(); 444 445 OnceClosure user_task_; 446 }; 447 448 //----------------------------------------------------------------------------- 449 // Repeatedly invokes a callback, waiting for a precise delay between the 450 // beginning of each invocation. See usage notes at the top of the file. 451 class BASE_EXPORT MetronomeTimer : public internal::TimerBase { 452 public: 453 MetronomeTimer(); 454 ~MetronomeTimer() override; 455 456 MetronomeTimer(const MetronomeTimer&) = delete; 457 MetronomeTimer& operator=(const MetronomeTimer&) = delete; 458 459 MetronomeTimer(const Location& posted_from, 460 TimeDelta interval, 461 RepeatingClosure user_task, 462 TimeTicks phase = TimeTicks()); 463 464 // Start the timer to repeatedly run |user_task| at the specified |interval|; 465 // If not specified, the phase is up to the scheduler, otherwise each 466 // invocation starts as close as possible to `phase + n * delay` for some 467 // integer n. If the timer is already running, it will be replaced to call the 468 // given |user_task|. 469 void Start(const Location& posted_from, 470 TimeDelta interval, 471 RepeatingClosure user_task, 472 TimeTicks phase = TimeTicks()); 473 474 // Same as the previous overload, except that the user task is specified by 475 // `receiver` and `method`. 476 template <class Receiver> 477 void Start(const Location& posted_from, 478 TimeDelta interval, 479 Receiver* receiver, 480 void (Receiver::*method)(), 481 TimeTicks phase = TimeTicks()) { 482 Start(posted_from, interval, BindRepeating(method, Unretained(receiver)), 483 phase); 484 } 485 486 // Call this method to reset the timer delay. The user task must be set. If 487 // the timer is not running, this will start it by posting a task. 488 void Reset(); 489 490 protected: 491 void OnStop() override; 492 493 // Schedules |OnScheduledTaskInvoked()| to run on the current sequence at 494 // the next tick. 495 void ScheduleNewTask(); 496 497 private: 498 // Called when the scheduled task is invoked to run the |user_task|. 499 void OnScheduledTaskInvoked(); 500 501 TimeDelta interval_; 502 RepeatingClosure user_task_; 503 TimeTicks phase_; 504 }; 505 506 } // namespace base 507 508 #endif // BASE_TIMER_TIMER_H_ 509