xref: /aosp_15_r20/external/webrtc/test/time_controller/external_time_controller.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 #include "test/time_controller/external_time_controller.h"
11 
12 #include <algorithm>
13 #include <map>
14 #include <memory>
15 #include <utility>
16 
17 #include "absl/functional/any_invocable.h"
18 #include "api/task_queue/task_queue_base.h"
19 #include "api/task_queue/task_queue_factory.h"
20 #include "api/units/time_delta.h"
21 #include "api/units/timestamp.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/synchronization/yield_policy.h"
24 #include "test/time_controller/simulated_time_controller.h"
25 
26 namespace webrtc {
27 
28 // Wraps a TaskQueue so that it can reschedule the time controller whenever
29 // an external call schedules a new task.
30 class ExternalTimeController::TaskQueueWrapper : public TaskQueueBase {
31  public:
TaskQueueWrapper(ExternalTimeController * parent,std::unique_ptr<TaskQueueBase,TaskQueueDeleter> base)32   TaskQueueWrapper(ExternalTimeController* parent,
33                    std::unique_ptr<TaskQueueBase, TaskQueueDeleter> base)
34       : parent_(parent), base_(std::move(base)) {}
35 
PostTask(absl::AnyInvocable<void ()&&> task)36   void PostTask(absl::AnyInvocable<void() &&> task) override {
37     parent_->UpdateTime();
38     base_->PostTask(TaskWrapper(std::move(task)));
39     parent_->ScheduleNext();
40   }
41 
PostDelayedTask(absl::AnyInvocable<void ()&&> task,TimeDelta delay)42   void PostDelayedTask(absl::AnyInvocable<void() &&> task,
43                        TimeDelta delay) override {
44     parent_->UpdateTime();
45     base_->PostDelayedTask(TaskWrapper(std::move(task)), delay);
46     parent_->ScheduleNext();
47   }
48 
PostDelayedHighPrecisionTask(absl::AnyInvocable<void ()&&> task,TimeDelta delay)49   void PostDelayedHighPrecisionTask(absl::AnyInvocable<void() &&> task,
50                                     TimeDelta delay) override {
51     parent_->UpdateTime();
52     base_->PostDelayedHighPrecisionTask(TaskWrapper(std::move(task)), delay);
53     parent_->ScheduleNext();
54   }
55 
Delete()56   void Delete() override { delete this; }
57 
58  private:
TaskWrapper(absl::AnyInvocable<void ()&&> task)59   absl::AnyInvocable<void() &&> TaskWrapper(
60       absl::AnyInvocable<void() &&> task) {
61     return [task = std::move(task), this]() mutable {
62       CurrentTaskQueueSetter current(this);
63       std::move(task)();
64     };
65   }
66 
67   ExternalTimeController* const parent_;
68   std::unique_ptr<TaskQueueBase, TaskQueueDeleter> base_;
69 };
70 
ExternalTimeController(ControlledAlarmClock * alarm)71 ExternalTimeController::ExternalTimeController(ControlledAlarmClock* alarm)
72     : alarm_(alarm),
73       impl_(alarm_->GetClock()->CurrentTime()),
74       yield_policy_(&impl_) {
75   global_clock_.SetTime(alarm_->GetClock()->CurrentTime());
76   alarm_->SetCallback([this] { Run(); });
77 }
78 
GetClock()79 Clock* ExternalTimeController::GetClock() {
80   return alarm_->GetClock();
81 }
82 
GetTaskQueueFactory()83 TaskQueueFactory* ExternalTimeController::GetTaskQueueFactory() {
84   return this;
85 }
86 
AdvanceTime(TimeDelta duration)87 void ExternalTimeController::AdvanceTime(TimeDelta duration) {
88   alarm_->Sleep(duration);
89 }
90 
CreateThread(const std::string & name,std::unique_ptr<rtc::SocketServer> socket_server)91 std::unique_ptr<rtc::Thread> ExternalTimeController::CreateThread(
92     const std::string& name,
93     std::unique_ptr<rtc::SocketServer> socket_server) {
94   RTC_DCHECK_NOTREACHED();
95   return nullptr;
96 }
97 
GetMainThread()98 rtc::Thread* ExternalTimeController::GetMainThread() {
99   RTC_DCHECK_NOTREACHED();
100   return nullptr;
101 }
102 
103 std::unique_ptr<TaskQueueBase, TaskQueueDeleter>
CreateTaskQueue(absl::string_view name,TaskQueueFactory::Priority priority) const104 ExternalTimeController::CreateTaskQueue(
105     absl::string_view name,
106     TaskQueueFactory::Priority priority) const {
107   return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
108       new TaskQueueWrapper(const_cast<ExternalTimeController*>(this),
109                            impl_.CreateTaskQueue(name, priority)));
110 }
111 
Run()112 void ExternalTimeController::Run() {
113   rtc::ScopedYieldPolicy yield_policy(&impl_);
114   UpdateTime();
115   impl_.RunReadyRunners();
116   ScheduleNext();
117 }
118 
UpdateTime()119 void ExternalTimeController::UpdateTime() {
120   Timestamp now = alarm_->GetClock()->CurrentTime();
121   impl_.AdvanceTime(now);
122   global_clock_.SetTime(now);
123 }
124 
ScheduleNext()125 void ExternalTimeController::ScheduleNext() {
126   RTC_DCHECK_EQ(impl_.CurrentTime(), alarm_->GetClock()->CurrentTime());
127   TimeDelta delay =
128       std::max(impl_.NextRunTime() - impl_.CurrentTime(), TimeDelta::Zero());
129   if (delay.IsFinite()) {
130     alarm_->ScheduleAlarmAt(alarm_->GetClock()->CurrentTime() + delay);
131   }
132 }
133 
134 }  // namespace webrtc
135