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