1 /*
2 * Copyright (c) 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 "test/pc/e2e/test_activities_executor.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "absl/memory/memory.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/location.h"
19 #include "rtc_base/logging.h"
20
21 namespace webrtc {
22 namespace webrtc_pc_e2e {
23
Start(TaskQueueForTest * task_queue)24 void TestActivitiesExecutor::Start(TaskQueueForTest* task_queue) {
25 RTC_DCHECK(task_queue);
26 task_queue_ = task_queue;
27 MutexLock lock(&lock_);
28 start_time_ = Now();
29 while (!scheduled_activities_.empty()) {
30 PostActivity(std::move(scheduled_activities_.front()));
31 scheduled_activities_.pop();
32 }
33 }
34
Stop()35 void TestActivitiesExecutor::Stop() {
36 if (task_queue_ == nullptr) {
37 // Already stopped or not started.
38 return;
39 }
40 task_queue_->SendTask(
41 [this]() {
42 MutexLock lock(&lock_);
43 for (auto& handle : repeating_task_handles_) {
44 handle.Stop();
45 }
46 },
47 RTC_FROM_HERE);
48 task_queue_ = nullptr;
49 }
50
ScheduleActivity(TimeDelta initial_delay_since_start,absl::optional<TimeDelta> interval,std::function<void (TimeDelta)> func)51 void TestActivitiesExecutor::ScheduleActivity(
52 TimeDelta initial_delay_since_start,
53 absl::optional<TimeDelta> interval,
54 std::function<void(TimeDelta)> func) {
55 RTC_CHECK(initial_delay_since_start.IsFinite() &&
56 initial_delay_since_start >= TimeDelta::Zero());
57 RTC_CHECK(!interval ||
58 (interval->IsFinite() && *interval > TimeDelta::Zero()));
59 MutexLock lock(&lock_);
60 ScheduledActivity activity(initial_delay_since_start, interval, func);
61 if (start_time_.IsInfinite()) {
62 scheduled_activities_.push(std::move(activity));
63 } else {
64 PostActivity(std::move(activity));
65 }
66 }
67
PostActivity(ScheduledActivity activity)68 void TestActivitiesExecutor::PostActivity(ScheduledActivity activity) {
69 // Because start_time_ will never change at this point copy it to local
70 // variable to capture in in lambda without requirement to hold a lock.
71 Timestamp start_time = start_time_;
72
73 TimeDelta remaining_delay =
74 activity.initial_delay_since_start == TimeDelta::Zero()
75 ? TimeDelta::Zero()
76 : activity.initial_delay_since_start - (Now() - start_time);
77 if (remaining_delay < TimeDelta::Zero()) {
78 RTC_LOG(WARNING) << "Executing late task immediately, late by="
79 << ToString(remaining_delay.Abs());
80 remaining_delay = TimeDelta::Zero();
81 }
82
83 if (activity.interval) {
84 if (remaining_delay == TimeDelta::Zero()) {
85 repeating_task_handles_.push_back(RepeatingTaskHandle::Start(
86 task_queue_->Get(), [activity, start_time, this]() {
87 activity.func(Now() - start_time);
88 return *activity.interval;
89 }));
90 return;
91 }
92 repeating_task_handles_.push_back(RepeatingTaskHandle::DelayedStart(
93 task_queue_->Get(), remaining_delay, [activity, start_time, this]() {
94 activity.func(Now() - start_time);
95 return *activity.interval;
96 }));
97 return;
98 }
99
100 if (remaining_delay == TimeDelta::Zero()) {
101 task_queue_->PostTask(
102 [activity, start_time, this]() { activity.func(Now() - start_time); });
103 return;
104 }
105
106 task_queue_->PostDelayedTask(
107 [activity, start_time, this]() { activity.func(Now() - start_time); },
108 remaining_delay.ms());
109 }
110
Now() const111 Timestamp TestActivitiesExecutor::Now() const {
112 return clock_->CurrentTime();
113 }
114
ScheduledActivity(TimeDelta initial_delay_since_start,absl::optional<TimeDelta> interval,std::function<void (TimeDelta)> func)115 TestActivitiesExecutor::ScheduledActivity::ScheduledActivity(
116 TimeDelta initial_delay_since_start,
117 absl::optional<TimeDelta> interval,
118 std::function<void(TimeDelta)> func)
119 : initial_delay_since_start(initial_delay_since_start),
120 interval(interval),
121 func(std::move(func)) {}
122
123 } // namespace webrtc_pc_e2e
124 } // namespace webrtc
125