blob: f652eb686cd2cc3ffbb1bda1bc3ce75182e45e1a [file] [log] [blame]
Bjorn A Mellemc4f86542019-11-21 10:37:18 -08001/*
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
Danil Chapovalov9c125c62022-07-07 20:29:30 +020017#include "absl/functional/any_invocable.h"
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080018#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"
Sebastian Janssonfc8279d2020-01-16 11:45:59 +010022#include "rtc_base/checks.h"
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080023#include "rtc_base/synchronization/yield_policy.h"
24#include "test/time_controller/simulated_time_controller.h"
25
26namespace webrtc {
27
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080028// Wraps a TaskQueue so that it can reschedule the time controller whenever
29// an external call schedules a new task.
30class ExternalTimeController::TaskQueueWrapper : public TaskQueueBase {
31 public:
32 TaskQueueWrapper(ExternalTimeController* parent,
33 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> base)
34 : parent_(parent), base_(std::move(base)) {}
35
Danil Chapovalov9c125c62022-07-07 20:29:30 +020036 void PostTask(absl::AnyInvocable<void() &&> task) override {
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080037 parent_->UpdateTime();
Danil Chapovalov9c125c62022-07-07 20:29:30 +020038 base_->PostTask(TaskWrapper(std::move(task)));
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080039 parent_->ScheduleNext();
40 }
41
Danil Chapovalov9c125c62022-07-07 20:29:30 +020042 void PostDelayedTask(absl::AnyInvocable<void() &&> task,
43 TimeDelta delay) override {
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080044 parent_->UpdateTime();
Danil Chapovalov9c125c62022-07-07 20:29:30 +020045 base_->PostDelayedTask(TaskWrapper(std::move(task)), delay);
46 parent_->ScheduleNext();
47 }
48
49 void PostDelayedHighPrecisionTask(absl::AnyInvocable<void() &&> task,
50 TimeDelta delay) override {
51 parent_->UpdateTime();
52 base_->PostDelayedHighPrecisionTask(TaskWrapper(std::move(task)), delay);
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080053 parent_->ScheduleNext();
54 }
55
56 void Delete() override { delete this; }
57
58 private:
Danil Chapovalov9c125c62022-07-07 20:29:30 +020059 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 }
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080066
67 ExternalTimeController* const parent_;
68 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> base_;
69};
70
71ExternalTimeController::ExternalTimeController(ControlledAlarmClock* alarm)
Sebastian Jansson340af972019-12-04 10:07:48 +010072 : alarm_(alarm),
73 impl_(alarm_->GetClock()->CurrentTime()),
74 yield_policy_(&impl_) {
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080075 global_clock_.SetTime(alarm_->GetClock()->CurrentTime());
76 alarm_->SetCallback([this] { Run(); });
77}
78
79Clock* ExternalTimeController::GetClock() {
80 return alarm_->GetClock();
81}
82
83TaskQueueFactory* ExternalTimeController::GetTaskQueueFactory() {
84 return this;
85}
86
Markus Handell486cc552019-12-03 14:37:28 +010087void ExternalTimeController::AdvanceTime(TimeDelta duration) {
Bjorn A Mellemc4f86542019-11-21 10:37:18 -080088 alarm_->Sleep(duration);
89}
90
Sebastian Janssonfc8279d2020-01-16 11:45:59 +010091std::unique_ptr<rtc::Thread> ExternalTimeController::CreateThread(
92 const std::string& name,
93 std::unique_ptr<rtc::SocketServer> socket_server) {
Artem Titovd3251962021-11-15 16:57:07 +010094 RTC_DCHECK_NOTREACHED();
Sebastian Janssonfc8279d2020-01-16 11:45:59 +010095 return nullptr;
96}
97
98rtc::Thread* ExternalTimeController::GetMainThread() {
Artem Titovd3251962021-11-15 16:57:07 +010099 RTC_DCHECK_NOTREACHED();
Sebastian Janssonfc8279d2020-01-16 11:45:59 +0100100 return nullptr;
101}
102
Bjorn A Mellemc4f86542019-11-21 10:37:18 -0800103std::unique_ptr<TaskQueueBase, TaskQueueDeleter>
104ExternalTimeController::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
112void ExternalTimeController::Run() {
113 rtc::ScopedYieldPolicy yield_policy(&impl_);
114 UpdateTime();
115 impl_.RunReadyRunners();
116 ScheduleNext();
117}
118
119void ExternalTimeController::UpdateTime() {
120 Timestamp now = alarm_->GetClock()->CurrentTime();
121 impl_.AdvanceTime(now);
122 global_clock_.SetTime(now);
123}
124
125void 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