xref: /aosp_15_r20/external/webrtc/rtc_base/task_utils/repeating_task.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "rtc_base/task_utils/repeating_task.h"
12 
13 #include "absl/functional/any_invocable.h"
14 #include "api/task_queue/pending_task_safety_flag.h"
15 #include "rtc_base/logging.h"
16 
17 namespace webrtc {
18 namespace {
19 
20 class RepeatingTask {
21  public:
22   RepeatingTask(TaskQueueBase* task_queue,
23                 TaskQueueBase::DelayPrecision precision,
24                 TimeDelta first_delay,
25                 absl::AnyInvocable<TimeDelta()> task,
26                 Clock* clock,
27                 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag);
28   RepeatingTask(RepeatingTask&&) = default;
29   RepeatingTask& operator=(RepeatingTask&&) = delete;
30   ~RepeatingTask() = default;
31 
32   void operator()() &&;
33 
34  private:
35   TaskQueueBase* const task_queue_;
36   const TaskQueueBase::DelayPrecision precision_;
37   Clock* const clock_;
38   absl::AnyInvocable<TimeDelta()> task_;
39   // This is always finite.
40   Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
41   rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag_
42       RTC_GUARDED_BY(task_queue_);
43 };
44 
RepeatingTask(TaskQueueBase * task_queue,TaskQueueBase::DelayPrecision precision,TimeDelta first_delay,absl::AnyInvocable<TimeDelta ()> task,Clock * clock,rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)45 RepeatingTask::RepeatingTask(
46     TaskQueueBase* task_queue,
47     TaskQueueBase::DelayPrecision precision,
48     TimeDelta first_delay,
49     absl::AnyInvocable<TimeDelta()> task,
50     Clock* clock,
51     rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
52     : task_queue_(task_queue),
53       precision_(precision),
54       clock_(clock),
55       task_(std::move(task)),
56       next_run_time_(clock_->CurrentTime() + first_delay),
57       alive_flag_(std::move(alive_flag)) {}
58 
operator ()()59 void RepeatingTask::operator()() && {
60   RTC_DCHECK_RUN_ON(task_queue_);
61   if (!alive_flag_->alive())
62     return;
63 
64   webrtc_repeating_task_impl::RepeatingTaskImplDTraceProbeRun();
65   TimeDelta delay = task_();
66   RTC_DCHECK_GE(delay, TimeDelta::Zero());
67 
68   // A delay of +infinity means that the task should not be run again.
69   // Alternatively, the closure might have stopped this task.
70   if (delay.IsPlusInfinity() || !alive_flag_->alive())
71     return;
72 
73   TimeDelta lost_time = clock_->CurrentTime() - next_run_time_;
74   next_run_time_ += delay;
75   delay -= lost_time;
76   delay = std::max(delay, TimeDelta::Zero());
77 
78   task_queue_->PostDelayedTaskWithPrecision(precision_, std::move(*this),
79                                             delay);
80 }
81 
82 }  // namespace
83 
Start(TaskQueueBase * task_queue,absl::AnyInvocable<TimeDelta ()> closure,TaskQueueBase::DelayPrecision precision,Clock * clock)84 RepeatingTaskHandle RepeatingTaskHandle::Start(
85     TaskQueueBase* task_queue,
86     absl::AnyInvocable<TimeDelta()> closure,
87     TaskQueueBase::DelayPrecision precision,
88     Clock* clock) {
89   auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
90   webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeStart();
91   task_queue->PostTask(RepeatingTask(task_queue, precision, TimeDelta::Zero(),
92                                      std::move(closure), clock, alive_flag));
93   return RepeatingTaskHandle(std::move(alive_flag));
94 }
95 
96 // DelayedStart is equivalent to Start except that the first invocation of the
97 // closure will be delayed by the given amount.
DelayedStart(TaskQueueBase * task_queue,TimeDelta first_delay,absl::AnyInvocable<TimeDelta ()> closure,TaskQueueBase::DelayPrecision precision,Clock * clock)98 RepeatingTaskHandle RepeatingTaskHandle::DelayedStart(
99     TaskQueueBase* task_queue,
100     TimeDelta first_delay,
101     absl::AnyInvocable<TimeDelta()> closure,
102     TaskQueueBase::DelayPrecision precision,
103     Clock* clock) {
104   auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
105   webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeDelayedStart();
106   task_queue->PostDelayedTaskWithPrecision(
107       precision,
108       RepeatingTask(task_queue, precision, first_delay, std::move(closure),
109                     clock, alive_flag),
110       first_delay);
111   return RepeatingTaskHandle(std::move(alive_flag));
112 }
113 
Stop()114 void RepeatingTaskHandle::Stop() {
115   if (repeating_task_) {
116     repeating_task_->SetNotAlive();
117     repeating_task_ = nullptr;
118   }
119 }
120 
Running() const121 bool RepeatingTaskHandle::Running() const {
122   return repeating_task_ != nullptr;
123 }
124 
125 namespace webrtc_repeating_task_impl {
126 // These methods are empty, but can be externally equipped with actions using
127 // dtrace.
RepeatingTaskHandleDTraceProbeStart()128 void RepeatingTaskHandleDTraceProbeStart() {}
RepeatingTaskHandleDTraceProbeDelayedStart()129 void RepeatingTaskHandleDTraceProbeDelayedStart() {}
RepeatingTaskImplDTraceProbeRun()130 void RepeatingTaskImplDTraceProbeRun() {}
131 }  // namespace webrtc_repeating_task_impl
132 }  // namespace webrtc
133