File: low_precision_timer.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (115 lines) | stat: -rw-r--r-- 4,863 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_LOW_PRECISION_TIMER_H_
#define THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_LOW_PRECISION_TIMER_H_

#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "base/time/time.h"
#include "third_party/webrtc/rtc_base/system/rtc_export.h"

namespace blink {

// Implements a low precision timer, expect it to fire up to ~16 ms late (plus
// any OS or workload related delays).
//
// This timer only fires on metronome ticks as specified by
// MetronomeSource::TimeSnappedToNextTick(). This allows running numerous timers
// without increasing the Idle Wake Ups frequency beyond the metronome tick
// frequency, i.e. when each tick is already scheduled adding a
// LowPrecisionTimer should not add any Idle Wake Ups.
//
// TODO(https://crbug.com/1267874): Can this timer be moved to base/ or replaced
// by a low precision base/ timer without causing excessive Idle Wake Up
// frequencies (e.g. WebRTC use case with 50 incoming videos)?
class RTC_EXPORT LowPrecisionTimer final {
 public:
  LowPrecisionTimer(scoped_refptr<base::SequencedTaskRunner> task_runner,
                    base::RepeatingCallback<void()> callback);
  ~LowPrecisionTimer();
  // Must be called prior to destruction. Unregisters from the metronome
  // provider.
  void Shutdown();

  // Schedules to invoke the callback |delay| time from now.
  void StartOneShot(base::TimeDelta delay);
  // Scheduldes to repeat unconditionally until the timer is stopped. This has
  // the same behavior as calling StartOneShot(delay) inside each callback.
  void StartRepeating(base::TimeDelta delay);
  // True if there is currently activity scheduled.
  bool IsActive();
  // Cancels any scheduled callbacks.
  void Stop();

  // Change which task runner to fire callbacks on. Seamlessy re-schedules
  // pending callbacks. Must not be called from inside the callback.
  void MoveToNewTaskRunner(
      scoped_refptr<base::SequencedTaskRunner> task_runner);

 private:
  // Handles the scheduling and cancellation of a repeating callback.
  // The callback can be re-scheduled after it has fired, but all other settings
  // are "const". To change settings the SchedulableCallback has to be
  // inactivated and replaced by a new SchedulableCallback instance.
  class SchedulableCallback
      : public base::RefCountedThreadSafe<SchedulableCallback> {
   public:
    SchedulableCallback(scoped_refptr<base::SequencedTaskRunner> task_runner,
                        base::RepeatingCallback<void()> callback,
                        base::TimeDelta repeated_delay);
    ~SchedulableCallback();

    // The task can be re-scheduled after each run.
    void Schedule(base::TimeTicks scheduled_time);
    bool IsScheduled();
    // Inactivate the callback. Returns the cancelled scheduled time, or
    // base::TimeTicks::Max() if nothing was scheduled when cancelled.
    base::TimeTicks Inactivate();

   private:
    void MaybeRun();
    void RemoveMetronomeListener();

    const scoped_refptr<base::SequencedTaskRunner> task_runner_;
    const base::RepeatingCallback<void()> callback_;

    // Only accessed on |task_runner_|.
    bool is_currently_running_ = false;
    base::Lock active_lock_;
    // Guarded by |active_lock_|, but to avoid deadlock we do not acquire the
    // lock when Inactivate() is being called from inside the callback. In this
    // case the lock is already being held by MaybeRun().
    bool is_active_ = true;
    base::TimeDelta repeated_delay_;

    base::Lock scheduled_time_lock_;
    base::TimeTicks scheduled_time_ GUARDED_BY(scheduled_time_lock_) =
        base::TimeTicks::Max();  // Max represents forever, i.e. not scheduled.
  };

  // Lazy-constructs |schedulable_callback_| and schedules the callback on the
  // specified time.
  void ScheduleCallback(base::TimeTicks scheduled_time)
      EXCLUSIVE_LOCKS_REQUIRED(lock_);
  // Inactivates in-flight callbacks and re-schedulels the callback using the
  // latest settings. Used e.g. when we start or stop using the metronome.
  void RescheduleCallback() EXCLUSIVE_LOCKS_REQUIRED(lock_);

  const base::RepeatingCallback<void()> callback_;
  base::Lock lock_;
  bool is_shutdown_ GUARDED_BY(lock_) = false;
  scoped_refptr<base::SequencedTaskRunner> task_runner_ GUARDED_BY(lock_);
  scoped_refptr<SchedulableCallback> schedulable_callback_ GUARDED_BY(lock_);
  // If not repeating this is zero.
  base::TimeDelta repeated_delay_ GUARDED_BY(lock_);
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_WEBRTC_OVERRIDES_LOW_PRECISION_TIMER_H_