/* * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "test/pc/e2e/test_activities_executor.h" #include #include #include "absl/memory/memory.h" #include "rtc_base/checks.h" #include "rtc_base/location.h" #include "rtc_base/logging.h" namespace webrtc { namespace webrtc_pc_e2e { void TestActivitiesExecutor::Start(TaskQueueForTest* task_queue) { RTC_DCHECK(task_queue); task_queue_ = task_queue; MutexLock lock(&lock_); start_time_ = Now(); while (!scheduled_activities_.empty()) { PostActivity(std::move(scheduled_activities_.front())); scheduled_activities_.pop(); } } void TestActivitiesExecutor::Stop() { if (task_queue_ == nullptr) { // Already stopped or not started. return; } task_queue_->SendTask( [this]() { MutexLock lock(&lock_); for (auto& handle : repeating_task_handles_) { handle.Stop(); } }, RTC_FROM_HERE); task_queue_ = nullptr; } void TestActivitiesExecutor::ScheduleActivity( TimeDelta initial_delay_since_start, absl::optional interval, std::function func) { RTC_CHECK(initial_delay_since_start.IsFinite() && initial_delay_since_start >= TimeDelta::Zero()); RTC_CHECK(!interval || (interval->IsFinite() && *interval > TimeDelta::Zero())); MutexLock lock(&lock_); ScheduledActivity activity(initial_delay_since_start, interval, func); if (start_time_.IsInfinite()) { scheduled_activities_.push(std::move(activity)); } else { PostActivity(std::move(activity)); } } void TestActivitiesExecutor::PostActivity(ScheduledActivity activity) { // Because start_time_ will never change at this point copy it to local // variable to capture in in lambda without requirement to hold a lock. Timestamp start_time = start_time_; TimeDelta remaining_delay = activity.initial_delay_since_start == TimeDelta::Zero() ? TimeDelta::Zero() : activity.initial_delay_since_start - (Now() - start_time); if (remaining_delay < TimeDelta::Zero()) { RTC_LOG(WARNING) << "Executing late task immediately, late by=" << ToString(remaining_delay.Abs()); remaining_delay = TimeDelta::Zero(); } if (activity.interval) { if (remaining_delay == TimeDelta::Zero()) { repeating_task_handles_.push_back(RepeatingTaskHandle::Start( task_queue_->Get(), [activity, start_time, this]() { activity.func(Now() - start_time); return *activity.interval; })); return; } repeating_task_handles_.push_back(RepeatingTaskHandle::DelayedStart( task_queue_->Get(), remaining_delay, [activity, start_time, this]() { activity.func(Now() - start_time); return *activity.interval; })); return; } if (remaining_delay == TimeDelta::Zero()) { task_queue_->PostTask( [activity, start_time, this]() { activity.func(Now() - start_time); }); return; } task_queue_->PostDelayedTask( [activity, start_time, this]() { activity.func(Now() - start_time); }, remaining_delay.ms()); } Timestamp TestActivitiesExecutor::Now() const { return clock_->CurrentTime(); } TestActivitiesExecutor::ScheduledActivity::ScheduledActivity( TimeDelta initial_delay_since_start, absl::optional interval, std::function func) : initial_delay_since_start(initial_delay_since_start), interval(interval), func(std::move(func)) {} } // namespace webrtc_pc_e2e } // namespace webrtc