blob: afd1ed517b8c37542cbe9f999f79127021576caa [file] [log] [blame] [edit]
/*
* Copyright 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/time_controller/simulated_time_controller.h"
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include "api/task_queue/task_queue_factory.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/checks.h"
#include "rtc_base/socket_server.h"
#include "rtc_base/synchronization/yield_policy.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
#include "system_wrappers/include/clock.h"
#include "test/time_controller/simulated_thread.h"
namespace webrtc {
GlobalSimulatedTimeController::GlobalSimulatedTimeController(
Timestamp start_time)
: sim_clock_(start_time.us()), impl_(start_time), yield_policy_(&impl_) {
global_clock_.SetTime(start_time);
auto main_thread = std::make_unique<SimulatedMainThread>(&impl_);
impl_.Register(main_thread.get());
main_thread_ = std::move(main_thread);
}
GlobalSimulatedTimeController::~GlobalSimulatedTimeController() = default;
Clock* GlobalSimulatedTimeController::GetClock() {
return &sim_clock_;
}
TaskQueueFactory* GlobalSimulatedTimeController::GetTaskQueueFactory() {
return &impl_;
}
std::unique_ptr<Thread> GlobalSimulatedTimeController::CreateThread(
const std::string& name,
std::unique_ptr<SocketServer> socket_server) {
return impl_.CreateThread(name, std::move(socket_server));
}
Thread* GlobalSimulatedTimeController::GetMainThread() {
return main_thread_.get();
}
void GlobalSimulatedTimeController::AdvanceTime(TimeDelta duration) {
ScopedYieldPolicy yield_policy(&impl_);
Timestamp current_time = impl_.CurrentTime();
RTC_DCHECK_EQ(current_time, sim_clock_.CurrentTime());
RTC_DCHECK_EQ(current_time.us(), TimeMicros());
Timestamp target_time = current_time + duration;
while (current_time < target_time) {
impl_.RunReadyRunners();
Timestamp next_time = std::min(impl_.NextRunTime(), target_time);
impl_.AdvanceTime(next_time);
auto delta = next_time - current_time;
current_time = next_time;
sim_clock_.AdvanceTimeMicroseconds(delta.us());
global_clock_.AdvanceTime(delta);
}
// After time has been simulated up until `target_time` we also need to run
// tasks meant to be executed at `target_time`.
impl_.RunReadyRunners();
}
void GlobalSimulatedTimeController::SkipForwardBy(TimeDelta duration) {
ScopedYieldPolicy yield_policy(&impl_);
Timestamp current_time = impl_.CurrentTime();
Timestamp target_time = current_time + duration;
impl_.AdvanceTime(target_time);
sim_clock_.AdvanceTimeMicroseconds(duration.us());
global_clock_.AdvanceTime(duration);
}
} // namespace webrtc