Add TimeController to api/test/ and add a CreateTimeController API.
Creates an abstraction for an "alarm clock" which can schedule time-controller callbacks and exposes a time controller driven by an external alarm. Bug: webrtc:9719 Change-Id: I08c2aa9dba25603043bfba48f55c925716a55bae Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158969 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Per Kjellander <perkj@webrtc.org> Reviewed-by: Artem Titov <titovartem@webrtc.org> Reviewed-by: Steve Anton <steveanton@webrtc.org> Commit-Queue: Bjorn Mellem <mellem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29879}
This commit is contained in:
committed by
Commit Bot
parent
3daedb6c88
commit
c4f865413a
46
api/BUILD.gn
46
api/BUILD.gn
@ -946,6 +946,45 @@ if (rtc_include_tests) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_library("time_controller") {
|
||||||
|
visibility = [ "*" ]
|
||||||
|
testonly = true
|
||||||
|
sources = [
|
||||||
|
"test/time_controller.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
"../modules:module_api",
|
||||||
|
"../modules/utility:utility",
|
||||||
|
"../rtc_base",
|
||||||
|
"../rtc_base:rtc_base_tests_utils",
|
||||||
|
"../rtc_base:rtc_event",
|
||||||
|
"../rtc_base/synchronization:sequence_checker",
|
||||||
|
"../rtc_base/synchronization:yield_policy",
|
||||||
|
"../rtc_base/task_utils:to_queued_task",
|
||||||
|
"../system_wrappers",
|
||||||
|
"task_queue",
|
||||||
|
"task_queue:default_task_queue_factory",
|
||||||
|
"units:time_delta",
|
||||||
|
"units:timestamp",
|
||||||
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_library("create_time_controller") {
|
||||||
|
visibility = [ "*" ]
|
||||||
|
testonly = true
|
||||||
|
sources = [
|
||||||
|
"test/create_time_controller.cc",
|
||||||
|
"test/create_time_controller.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
":time_controller",
|
||||||
|
"../test/time_controller",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
rtc_library("rtc_api_unittests") {
|
rtc_library("rtc_api_unittests") {
|
||||||
testonly = true
|
testonly = true
|
||||||
|
|
||||||
@ -958,11 +997,13 @@ if (rtc_include_tests) {
|
|||||||
"rtp_packet_infos_unittest.cc",
|
"rtp_packet_infos_unittest.cc",
|
||||||
"rtp_parameters_unittest.cc",
|
"rtp_parameters_unittest.cc",
|
||||||
"scoped_refptr_unittest.cc",
|
"scoped_refptr_unittest.cc",
|
||||||
|
"test/create_time_controller_unittest.cc",
|
||||||
"test/loopback_media_transport_unittest.cc",
|
"test/loopback_media_transport_unittest.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":array_view",
|
":array_view",
|
||||||
|
":create_time_controller",
|
||||||
":function_view",
|
":function_view",
|
||||||
":libjingle_peerconnection_api",
|
":libjingle_peerconnection_api",
|
||||||
":loopback_media_transport",
|
":loopback_media_transport",
|
||||||
@ -971,12 +1012,17 @@ if (rtc_include_tests) {
|
|||||||
":rtp_packet_info",
|
":rtp_packet_info",
|
||||||
":rtp_parameters",
|
":rtp_parameters",
|
||||||
":scoped_refptr",
|
":scoped_refptr",
|
||||||
|
":time_controller",
|
||||||
"../rtc_base:checks",
|
"../rtc_base:checks",
|
||||||
"../rtc_base:gunit_helpers",
|
"../rtc_base:gunit_helpers",
|
||||||
"../rtc_base:rtc_base_approved",
|
"../rtc_base:rtc_base_approved",
|
||||||
|
"../rtc_base:rtc_task_queue",
|
||||||
|
"../rtc_base/task_utils:repeating_task",
|
||||||
"../test:fileutils",
|
"../test:fileutils",
|
||||||
"../test:test_support",
|
"../test:test_support",
|
||||||
"task_queue:task_queue_default_factory_unittests",
|
"task_queue:task_queue_default_factory_unittests",
|
||||||
|
"units:time_delta",
|
||||||
|
"units:timestamp",
|
||||||
"units:units_unittests",
|
"units:units_unittests",
|
||||||
"video:video_unittests",
|
"video:video_unittests",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -32,4 +32,9 @@ specific_include_rules = {
|
|||||||
"+rtc_base/thread.h",
|
"+rtc_base/thread.h",
|
||||||
"+media/base/media_constants.h",
|
"+media/base/media_constants.h",
|
||||||
],
|
],
|
||||||
|
"time_controller\.h": [
|
||||||
|
"+modules/utility/include/process_thread.h",
|
||||||
|
"+rtc_base/synchronization/yield_policy.h",
|
||||||
|
"+system_wrappers/include/clock.h",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
24
api/test/create_time_controller.cc
Normal file
24
api/test/create_time_controller.cc
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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 "api/test/create_time_controller.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "test/time_controller/external_time_controller.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
std::unique_ptr<TimeController> CreateTimeController(
|
||||||
|
ControlledAlarmClock* alarm) {
|
||||||
|
return std::make_unique<ExternalTimeController>(alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
24
api/test/create_time_controller.h
Normal file
24
api/test/create_time_controller.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#ifndef API_TEST_CREATE_TIME_CONTROLLER_H_
|
||||||
|
#define API_TEST_CREATE_TIME_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
std::unique_ptr<TimeController> CreateTimeController(
|
||||||
|
ControlledAlarmClock* alarm);
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // API_TEST_CREATE_TIME_CONTROLLER_H_
|
||||||
76
api/test/create_time_controller_unittest.cc
Normal file
76
api/test/create_time_controller_unittest.cc
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* 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 "api/test/create_time_controller.h"
|
||||||
|
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
|
#include "api/units/time_delta.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
|
#include "test/gmock.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class FakeAlarm : public ControlledAlarmClock {
|
||||||
|
public:
|
||||||
|
explicit FakeAlarm(Timestamp start_time);
|
||||||
|
|
||||||
|
Clock* GetClock() override;
|
||||||
|
bool ScheduleAlarmAt(Timestamp deadline) override;
|
||||||
|
void SetCallback(std::function<void()> callback) override;
|
||||||
|
void Sleep(TimeDelta duration) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SimulatedClock clock_;
|
||||||
|
Timestamp deadline_;
|
||||||
|
std::function<void()> callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeAlarm::FakeAlarm(Timestamp start_time)
|
||||||
|
: clock_(start_time),
|
||||||
|
deadline_(Timestamp::PlusInfinity()),
|
||||||
|
callback_([] {}) {}
|
||||||
|
|
||||||
|
Clock* FakeAlarm::GetClock() {
|
||||||
|
return &clock_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FakeAlarm::ScheduleAlarmAt(Timestamp deadline) {
|
||||||
|
if (deadline < deadline_) {
|
||||||
|
deadline_ = deadline;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeAlarm::SetCallback(std::function<void()> callback) {
|
||||||
|
callback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeAlarm::Sleep(TimeDelta duration) {
|
||||||
|
Timestamp end_time = clock_.CurrentTime() + duration;
|
||||||
|
|
||||||
|
while (deadline_ <= end_time) {
|
||||||
|
clock_.AdvanceTime(deadline_ - clock_.CurrentTime());
|
||||||
|
deadline_ = Timestamp::PlusInfinity();
|
||||||
|
callback_();
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_.AdvanceTime(end_time - clock_.CurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(CreateTimeControllerTest, CreatesNonNullController) {
|
||||||
|
FakeAlarm alarm(Timestamp::ms(100));
|
||||||
|
EXPECT_NE(CreateTimeController(&alarm), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace webrtc
|
||||||
@ -7,15 +7,17 @@
|
|||||||
* in the file PATENTS. All contributing project authors may
|
* in the file PATENTS. All contributing project authors may
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
#ifndef TEST_TIME_CONTROLLER_TIME_CONTROLLER_H_
|
#ifndef API_TEST_TIME_CONTROLLER_H_
|
||||||
#define TEST_TIME_CONTROLLER_TIME_CONTROLLER_H_
|
#define API_TEST_TIME_CONTROLLER_H_
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "api/task_queue/task_queue_factory.h"
|
#include "api/task_queue/task_queue_factory.h"
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
#include "modules/utility/include/process_thread.h"
|
#include "modules/utility/include/process_thread.h"
|
||||||
|
#include "rtc_base/synchronization/yield_policy.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
#include "system_wrappers/include/clock.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -42,6 +44,32 @@ class TimeController {
|
|||||||
// might yield to execute other tasks. This allows doing blocking waits on
|
// might yield to execute other tasks. This allows doing blocking waits on
|
||||||
// tasks on other task queues froma a task queue without deadlocking.
|
// tasks on other task queues froma a task queue without deadlocking.
|
||||||
virtual void InvokeWithControlledYield(std::function<void()> closure) = 0;
|
virtual void InvokeWithControlledYield(std::function<void()> closure) = 0;
|
||||||
|
// Returns a YieldInterface which can be installed as a ScopedYieldPolicy.
|
||||||
|
virtual rtc::YieldInterface* YieldInterface() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Interface for telling time, scheduling an event to fire at a particular time,
|
||||||
|
// and waiting for time to pass.
|
||||||
|
class ControlledAlarmClock {
|
||||||
|
public:
|
||||||
|
virtual ~ControlledAlarmClock() = default;
|
||||||
|
|
||||||
|
// Gets a clock that tells the alarm clock's notion of time.
|
||||||
|
virtual Clock* GetClock() = 0;
|
||||||
|
|
||||||
|
// Schedules the alarm to fire at |deadline|.
|
||||||
|
// An alarm clock only supports one deadline. Calls to |ScheduleAlarmAt| with
|
||||||
|
// an earlier deadline will reset the alarm to fire earlier.Calls to
|
||||||
|
// |ScheduleAlarmAt| with a later deadline are ignored. Returns true if the
|
||||||
|
// deadline changed, false otherwise.
|
||||||
|
virtual bool ScheduleAlarmAt(Timestamp deadline) = 0;
|
||||||
|
|
||||||
|
// Sets the callback that should be run when the alarm fires.
|
||||||
|
virtual void SetCallback(std::function<void()> callback) = 0;
|
||||||
|
|
||||||
|
// Waits for |duration| to pass, according to the alarm clock.
|
||||||
|
virtual void Sleep(TimeDelta duration) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif // TEST_TIME_CONTROLLER_TIME_CONTROLLER_H_
|
#endif // API_TEST_TIME_CONTROLLER_H_
|
||||||
@ -41,6 +41,7 @@ rtc_library("emulated_network") {
|
|||||||
deps = [
|
deps = [
|
||||||
"../../api:network_emulation_manager_api",
|
"../../api:network_emulation_manager_api",
|
||||||
"../../api:simulated_network_api",
|
"../../api:simulated_network_api",
|
||||||
|
"../../api:time_controller",
|
||||||
"../../api/units:data_rate",
|
"../../api/units:data_rate",
|
||||||
"../../api/units:data_size",
|
"../../api/units:data_size",
|
||||||
"../../api/units:time_delta",
|
"../../api/units:time_delta",
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "api/test/network_emulation_manager.h"
|
#include "api/test/network_emulation_manager.h"
|
||||||
#include "api/test/simulated_network.h"
|
#include "api/test/simulated_network.h"
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
@ -33,7 +34,6 @@
|
|||||||
#include "test/network/network_emulation.h"
|
#include "test/network/network_emulation.h"
|
||||||
#include "test/network/simulated_network_node.h"
|
#include "test/network/simulated_network_node.h"
|
||||||
#include "test/network/traffic_route.h"
|
#include "test/network/traffic_route.h"
|
||||||
#include "test/time_controller/time_controller.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|||||||
@ -84,6 +84,8 @@ if (rtc_include_tests) {
|
|||||||
"../../api:libjingle_peerconnection_api",
|
"../../api:libjingle_peerconnection_api",
|
||||||
"../../api:rtc_event_log_output_file",
|
"../../api:rtc_event_log_output_file",
|
||||||
"../../api:rtp_parameters",
|
"../../api:rtp_parameters",
|
||||||
|
"../../api:time_controller",
|
||||||
|
"../../api:time_controller",
|
||||||
"../../api:transport_api",
|
"../../api:transport_api",
|
||||||
"../../api/audio_codecs:builtin_audio_decoder_factory",
|
"../../api/audio_codecs:builtin_audio_decoder_factory",
|
||||||
"../../api/audio_codecs:builtin_audio_encoder_factory",
|
"../../api/audio_codecs:builtin_audio_encoder_factory",
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "api/rtc_event_log/rtc_event_log.h"
|
#include "api/rtc_event_log/rtc_event_log.h"
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
#include "call/call.h"
|
#include "call/call.h"
|
||||||
#include "modules/audio_device/include/test_audio_device.h"
|
#include "modules/audio_device/include/test_audio_device.h"
|
||||||
#include "modules/congestion_controller/goog_cc/test/goog_cc_printer.h"
|
#include "modules/congestion_controller/goog_cc/test/goog_cc_printer.h"
|
||||||
@ -28,7 +29,6 @@
|
|||||||
#include "test/scenario/column_printer.h"
|
#include "test/scenario/column_printer.h"
|
||||||
#include "test/scenario/network_node.h"
|
#include "test/scenario/network_node.h"
|
||||||
#include "test/scenario/scenario_config.h"
|
#include "test/scenario/scenario_config.h"
|
||||||
#include "test/time_controller/time_controller.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
#include "rtc_base/constructor_magic.h"
|
#include "rtc_base/constructor_magic.h"
|
||||||
#include "rtc_base/fake_clock.h"
|
#include "rtc_base/fake_clock.h"
|
||||||
#include "rtc_base/task_queue.h"
|
#include "rtc_base/task_queue.h"
|
||||||
@ -26,7 +27,6 @@
|
|||||||
#include "test/scenario/network_node.h"
|
#include "test/scenario/network_node.h"
|
||||||
#include "test/scenario/scenario_config.h"
|
#include "test/scenario/scenario_config.h"
|
||||||
#include "test/scenario/video_stream.h"
|
#include "test/scenario/video_stream.h"
|
||||||
#include "test/time_controller/time_controller.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|||||||
@ -12,14 +12,16 @@ if (rtc_include_tests) {
|
|||||||
rtc_library("time_controller") {
|
rtc_library("time_controller") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
|
"external_time_controller.cc",
|
||||||
|
"external_time_controller.h",
|
||||||
"real_time_controller.cc",
|
"real_time_controller.cc",
|
||||||
"real_time_controller.h",
|
"real_time_controller.h",
|
||||||
"simulated_time_controller.cc",
|
"simulated_time_controller.cc",
|
||||||
"simulated_time_controller.h",
|
"simulated_time_controller.h",
|
||||||
"time_controller.h",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
|
"../../api:time_controller",
|
||||||
"../../api/task_queue",
|
"../../api/task_queue",
|
||||||
"../../api/task_queue:default_task_queue_factory",
|
"../../api/task_queue:default_task_queue_factory",
|
||||||
"../../api/units:time_delta",
|
"../../api/units:time_delta",
|
||||||
@ -39,6 +41,7 @@ if (rtc_include_tests) {
|
|||||||
rtc_library("time_controller_unittests") {
|
rtc_library("time_controller_unittests") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
|
"external_time_controller_unittest.cc",
|
||||||
"simulated_time_controller_unittest.cc",
|
"simulated_time_controller_unittest.cc",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
226
test/time_controller/external_time_controller.cc
Normal file
226
test/time_controller/external_time_controller.cc
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/*
|
||||||
|
* 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/external_time_controller.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "api/task_queue/queued_task.h"
|
||||||
|
#include "api/task_queue/task_queue_base.h"
|
||||||
|
#include "api/task_queue/task_queue_factory.h"
|
||||||
|
#include "api/units/time_delta.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
|
#include "modules/include/module.h"
|
||||||
|
#include "modules/utility/include/process_thread.h"
|
||||||
|
#include "rtc_base/synchronization/yield_policy.h"
|
||||||
|
#include "test/time_controller/simulated_time_controller.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// Wraps a ProcessThread so that it can reschedule the time controller whenever
|
||||||
|
// an external call changes the ProcessThread's state. For example, when a new
|
||||||
|
// module is registered, the ProcessThread may need to be called sooner than the
|
||||||
|
// time controller's currently-scheduled deadline.
|
||||||
|
class ExternalTimeController::ProcessThreadWrapper : public ProcessThread {
|
||||||
|
public:
|
||||||
|
ProcessThreadWrapper(ExternalTimeController* parent,
|
||||||
|
std::unique_ptr<ProcessThread> thread)
|
||||||
|
: parent_(parent), thread_(std::move(thread)) {}
|
||||||
|
|
||||||
|
void Start() override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
thread_->Start();
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stop() override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
thread_->Stop();
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WakeUp(Module* module) override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
thread_->WakeUp(GetWrapper(module));
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostTask(std::unique_ptr<QueuedTask> task) override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
thread_->PostTask(std::move(task));
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterModule(Module* module, const rtc::Location& from) override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
module_wrappers_.emplace(module, new ModuleWrapper(module, this));
|
||||||
|
thread_->RegisterModule(GetWrapper(module), from);
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeRegisterModule(Module* module) override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
thread_->DeRegisterModule(GetWrapper(module));
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
module_wrappers_.erase(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ModuleWrapper : public Module {
|
||||||
|
public:
|
||||||
|
ModuleWrapper(Module* module, ProcessThreadWrapper* thread)
|
||||||
|
: module_(module), thread_(thread) {}
|
||||||
|
|
||||||
|
int64_t TimeUntilNextProcess() override {
|
||||||
|
return module_->TimeUntilNextProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process() override { module_->Process(); }
|
||||||
|
|
||||||
|
void ProcessThreadAttached(ProcessThread* process_thread) override {
|
||||||
|
if (process_thread) {
|
||||||
|
module_->ProcessThreadAttached(thread_);
|
||||||
|
} else {
|
||||||
|
module_->ProcessThreadAttached(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Module* module_;
|
||||||
|
ProcessThreadWrapper* thread_;
|
||||||
|
};
|
||||||
|
|
||||||
|
ModuleWrapper* GetWrapper(Module* module) {
|
||||||
|
auto it = module_wrappers_.find(module);
|
||||||
|
RTC_DCHECK(it != module_wrappers_.end());
|
||||||
|
return it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalTimeController* const parent_;
|
||||||
|
std::unique_ptr<ProcessThread> thread_;
|
||||||
|
std::map<Module*, std::unique_ptr<ModuleWrapper>> module_wrappers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wraps a TaskQueue so that it can reschedule the time controller whenever
|
||||||
|
// an external call schedules a new task.
|
||||||
|
class ExternalTimeController::TaskQueueWrapper : public TaskQueueBase {
|
||||||
|
public:
|
||||||
|
TaskQueueWrapper(ExternalTimeController* parent,
|
||||||
|
std::unique_ptr<TaskQueueBase, TaskQueueDeleter> base)
|
||||||
|
: parent_(parent), base_(std::move(base)) {}
|
||||||
|
|
||||||
|
void PostTask(std::unique_ptr<QueuedTask> task) override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
base_->PostTask(std::make_unique<TaskWrapper>(std::move(task), this));
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostDelayedTask(std::unique_ptr<QueuedTask> task, uint32_t ms) override {
|
||||||
|
parent_->UpdateTime();
|
||||||
|
base_->PostDelayedTask(std::make_unique<TaskWrapper>(std::move(task), this),
|
||||||
|
ms);
|
||||||
|
parent_->ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delete() override { delete this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
class TaskWrapper : public QueuedTask {
|
||||||
|
public:
|
||||||
|
TaskWrapper(std::unique_ptr<QueuedTask> task, TaskQueueWrapper* queue)
|
||||||
|
: task_(std::move(task)), queue_(queue) {}
|
||||||
|
|
||||||
|
bool Run() override {
|
||||||
|
CurrentTaskQueueSetter current(queue_);
|
||||||
|
if (!task_->Run()) {
|
||||||
|
task_.release();
|
||||||
|
}
|
||||||
|
// The wrapper should always be deleted, even if it releases the inner
|
||||||
|
// task, in order to avoid leaking wrappers.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<QueuedTask> task_;
|
||||||
|
TaskQueueWrapper* queue_;
|
||||||
|
};
|
||||||
|
|
||||||
|
ExternalTimeController* const parent_;
|
||||||
|
std::unique_ptr<TaskQueueBase, TaskQueueDeleter> base_;
|
||||||
|
};
|
||||||
|
|
||||||
|
ExternalTimeController::ExternalTimeController(ControlledAlarmClock* alarm)
|
||||||
|
: alarm_(alarm), impl_(alarm_->GetClock()->CurrentTime()) {
|
||||||
|
global_clock_.SetTime(alarm_->GetClock()->CurrentTime());
|
||||||
|
alarm_->SetCallback([this] { Run(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
Clock* ExternalTimeController::GetClock() {
|
||||||
|
return alarm_->GetClock();
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskQueueFactory* ExternalTimeController::GetTaskQueueFactory() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ProcessThread> ExternalTimeController::CreateProcessThread(
|
||||||
|
const char* thread_name) {
|
||||||
|
return std::make_unique<ProcessThreadWrapper>(
|
||||||
|
this, impl_.CreateProcessThread(thread_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalTimeController::Sleep(TimeDelta duration) {
|
||||||
|
alarm_->Sleep(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalTimeController::InvokeWithControlledYield(
|
||||||
|
std::function<void()> closure) {
|
||||||
|
rtc::ScopedYieldPolicy policy(YieldInterface());
|
||||||
|
closure();
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::YieldInterface* ExternalTimeController::YieldInterface() {
|
||||||
|
return &impl_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<TaskQueueBase, TaskQueueDeleter>
|
||||||
|
ExternalTimeController::CreateTaskQueue(
|
||||||
|
absl::string_view name,
|
||||||
|
TaskQueueFactory::Priority priority) const {
|
||||||
|
return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(
|
||||||
|
new TaskQueueWrapper(const_cast<ExternalTimeController*>(this),
|
||||||
|
impl_.CreateTaskQueue(name, priority)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalTimeController::Run() {
|
||||||
|
rtc::ScopedYieldPolicy yield_policy(&impl_);
|
||||||
|
UpdateTime();
|
||||||
|
impl_.RunReadyRunners();
|
||||||
|
ScheduleNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalTimeController::UpdateTime() {
|
||||||
|
Timestamp now = alarm_->GetClock()->CurrentTime();
|
||||||
|
impl_.AdvanceTime(now);
|
||||||
|
global_clock_.SetTime(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalTimeController::ScheduleNext() {
|
||||||
|
RTC_DCHECK_EQ(impl_.CurrentTime(), alarm_->GetClock()->CurrentTime());
|
||||||
|
TimeDelta delay =
|
||||||
|
std::max(impl_.NextRunTime() - impl_.CurrentTime(), TimeDelta::Zero());
|
||||||
|
if (delay.IsFinite()) {
|
||||||
|
alarm_->ScheduleAlarmAt(alarm_->GetClock()->CurrentTime() + delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
70
test/time_controller/external_time_controller.h
Normal file
70
test/time_controller/external_time_controller.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#ifndef TEST_TIME_CONTROLLER_EXTERNAL_TIME_CONTROLLER_H_
|
||||||
|
#define TEST_TIME_CONTROLLER_EXTERNAL_TIME_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "absl/strings/string_view.h"
|
||||||
|
#include "api/task_queue/task_queue_base.h"
|
||||||
|
#include "api/task_queue/task_queue_factory.h"
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
|
#include "api/units/time_delta.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
|
#include "modules/utility/include/process_thread.h"
|
||||||
|
#include "system_wrappers/include/clock.h"
|
||||||
|
#include "test/time_controller/simulated_time_controller.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// TimeController implementation built on an external controlled alarm.
|
||||||
|
// This implementation is used to delegate scheduling and execution to an
|
||||||
|
// external run loop.
|
||||||
|
class ExternalTimeController : public TimeController, public TaskQueueFactory {
|
||||||
|
public:
|
||||||
|
explicit ExternalTimeController(ControlledAlarmClock* alarm);
|
||||||
|
|
||||||
|
// Implementation of TimeController.
|
||||||
|
Clock* GetClock() override;
|
||||||
|
TaskQueueFactory* GetTaskQueueFactory() override;
|
||||||
|
std::unique_ptr<ProcessThread> CreateProcessThread(
|
||||||
|
const char* thread_name) override;
|
||||||
|
void Sleep(TimeDelta duration) override;
|
||||||
|
void InvokeWithControlledYield(std::function<void()> closure) override;
|
||||||
|
rtc::YieldInterface* YieldInterface() override;
|
||||||
|
|
||||||
|
// Implementation of TaskQueueFactory.
|
||||||
|
std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
|
||||||
|
absl::string_view name,
|
||||||
|
TaskQueueFactory::Priority priority) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class ProcessThreadWrapper;
|
||||||
|
class TaskQueueWrapper;
|
||||||
|
|
||||||
|
// Executes any tasks scheduled at or before the current time. May call
|
||||||
|
// |ScheduleNext| to schedule the next call to |Run|.
|
||||||
|
void Run();
|
||||||
|
|
||||||
|
void UpdateTime();
|
||||||
|
void ScheduleNext();
|
||||||
|
|
||||||
|
ControlledAlarmClock* alarm_;
|
||||||
|
sim_time_impl::SimulatedTimeControllerImpl impl_;
|
||||||
|
|
||||||
|
// Overrides the global rtc::Clock to ensure that it reports the same times as
|
||||||
|
// the time controller.
|
||||||
|
rtc::ScopedBaseFakeClock global_clock_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // TEST_TIME_CONTROLLER_EXTERNAL_TIME_CONTROLLER_H_
|
||||||
181
test/time_controller/external_time_controller_unittest.cc
Normal file
181
test/time_controller/external_time_controller_unittest.cc
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* 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/external_time_controller.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "rtc_base/event.h"
|
||||||
|
#include "rtc_base/task_queue.h"
|
||||||
|
#include "rtc_base/task_utils/repeating_task.h"
|
||||||
|
#include "test/gmock.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
|
// NOTE: Since these tests rely on real time behavior, they will be flaky
|
||||||
|
// if run on heavily loaded systems.
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
using ::testing::AtLeast;
|
||||||
|
using ::testing::Invoke;
|
||||||
|
using ::testing::MockFunction;
|
||||||
|
using ::testing::NiceMock;
|
||||||
|
using ::testing::Return;
|
||||||
|
constexpr Timestamp kStartTime = Timestamp::Seconds<1000>();
|
||||||
|
|
||||||
|
class FakeAlarm : public ControlledAlarmClock {
|
||||||
|
public:
|
||||||
|
explicit FakeAlarm(Timestamp start_time);
|
||||||
|
|
||||||
|
Clock* GetClock() override;
|
||||||
|
bool ScheduleAlarmAt(Timestamp deadline) override;
|
||||||
|
void SetCallback(std::function<void()> callback) override;
|
||||||
|
void Sleep(TimeDelta duration) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SimulatedClock clock_;
|
||||||
|
Timestamp deadline_;
|
||||||
|
std::function<void()> callback_;
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeAlarm::FakeAlarm(Timestamp start_time)
|
||||||
|
: clock_(start_time),
|
||||||
|
deadline_(Timestamp::PlusInfinity()),
|
||||||
|
callback_([] {}) {}
|
||||||
|
|
||||||
|
Clock* FakeAlarm::GetClock() {
|
||||||
|
return &clock_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FakeAlarm::ScheduleAlarmAt(Timestamp deadline) {
|
||||||
|
if (deadline < deadline_) {
|
||||||
|
deadline_ = deadline;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeAlarm::SetCallback(std::function<void()> callback) {
|
||||||
|
callback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FakeAlarm::Sleep(TimeDelta duration) {
|
||||||
|
Timestamp end_time = clock_.CurrentTime() + duration;
|
||||||
|
|
||||||
|
while (deadline_ <= end_time) {
|
||||||
|
clock_.AdvanceTime(deadline_ - clock_.CurrentTime());
|
||||||
|
deadline_ = Timestamp::PlusInfinity();
|
||||||
|
callback_();
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_.AdvanceTime(end_time - clock_.CurrentTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(ExternalTimeControllerTest, TaskIsStoppedOnStop) {
|
||||||
|
const TimeDelta kShortInterval = TimeDelta::ms(5);
|
||||||
|
const TimeDelta kLongInterval = TimeDelta::ms(20);
|
||||||
|
const int kShortIntervalCount = 4;
|
||||||
|
const int kMargin = 1;
|
||||||
|
FakeAlarm alarm(kStartTime);
|
||||||
|
ExternalTimeController time_simulation(&alarm);
|
||||||
|
rtc::TaskQueue task_queue(
|
||||||
|
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
|
||||||
|
"TestQueue", TaskQueueFactory::Priority::NORMAL));
|
||||||
|
std::atomic_int counter(0);
|
||||||
|
auto handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
|
||||||
|
if (++counter >= kShortIntervalCount)
|
||||||
|
return kLongInterval;
|
||||||
|
return kShortInterval;
|
||||||
|
});
|
||||||
|
// Sleep long enough to go through the initial phase.
|
||||||
|
time_simulation.Sleep(kShortInterval * (kShortIntervalCount + kMargin));
|
||||||
|
EXPECT_EQ(counter.load(), kShortIntervalCount);
|
||||||
|
|
||||||
|
task_queue.PostTask(
|
||||||
|
[handle = std::move(handle)]() mutable { handle.Stop(); });
|
||||||
|
|
||||||
|
// Sleep long enough that the task would run at least once more if not
|
||||||
|
// stopped.
|
||||||
|
time_simulation.Sleep(kLongInterval * 2);
|
||||||
|
EXPECT_EQ(counter.load(), kShortIntervalCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExternalTimeControllerTest, TaskCanStopItself) {
|
||||||
|
std::atomic_int counter(0);
|
||||||
|
FakeAlarm alarm(kStartTime);
|
||||||
|
ExternalTimeController time_simulation(&alarm);
|
||||||
|
rtc::TaskQueue task_queue(
|
||||||
|
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
|
||||||
|
"TestQueue", TaskQueueFactory::Priority::NORMAL));
|
||||||
|
|
||||||
|
RepeatingTaskHandle handle;
|
||||||
|
task_queue.PostTask([&] {
|
||||||
|
handle = RepeatingTaskHandle::Start(task_queue.Get(), [&] {
|
||||||
|
++counter;
|
||||||
|
handle.Stop();
|
||||||
|
return TimeDelta::ms(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
time_simulation.Sleep(TimeDelta::ms(10));
|
||||||
|
EXPECT_EQ(counter.load(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExternalTimeControllerTest, YieldForTask) {
|
||||||
|
FakeAlarm alarm(kStartTime);
|
||||||
|
ExternalTimeController time_simulation(&alarm);
|
||||||
|
|
||||||
|
rtc::TaskQueue task_queue(
|
||||||
|
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
|
||||||
|
"TestQueue", TaskQueueFactory::Priority::NORMAL));
|
||||||
|
|
||||||
|
time_simulation.InvokeWithControlledYield([&] {
|
||||||
|
rtc::Event event;
|
||||||
|
task_queue.PostTask([&] { event.Set(); });
|
||||||
|
EXPECT_TRUE(event.Wait(200));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExternalTimeControllerTest, TasksYieldToEachOther) {
|
||||||
|
FakeAlarm alarm(kStartTime);
|
||||||
|
ExternalTimeController time_simulation(&alarm);
|
||||||
|
|
||||||
|
rtc::TaskQueue task_queue(
|
||||||
|
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
|
||||||
|
"TestQueue", TaskQueueFactory::Priority::NORMAL));
|
||||||
|
rtc::TaskQueue other_queue(
|
||||||
|
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
|
||||||
|
"OtherQueue", TaskQueueFactory::Priority::NORMAL));
|
||||||
|
|
||||||
|
task_queue.PostTask([&] {
|
||||||
|
rtc::Event event;
|
||||||
|
other_queue.PostTask([&] { event.Set(); });
|
||||||
|
EXPECT_TRUE(event.Wait(200));
|
||||||
|
});
|
||||||
|
|
||||||
|
time_simulation.Sleep(TimeDelta::ms(300));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExternalTimeControllerTest, CurrentTaskQueue) {
|
||||||
|
FakeAlarm alarm(kStartTime);
|
||||||
|
ExternalTimeController time_simulation(&alarm);
|
||||||
|
|
||||||
|
rtc::TaskQueue task_queue(
|
||||||
|
time_simulation.GetTaskQueueFactory()->CreateTaskQueue(
|
||||||
|
"TestQueue", TaskQueueFactory::Priority::NORMAL));
|
||||||
|
|
||||||
|
task_queue.PostTask([&] { EXPECT_TRUE(task_queue.IsCurrent()); });
|
||||||
|
|
||||||
|
time_simulation.Sleep(TimeDelta::ms(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
@ -39,6 +39,10 @@ void RealTimeController::InvokeWithControlledYield(
|
|||||||
closure();
|
closure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc::YieldInterface* RealTimeController::YieldInterface() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
RealTimeController* GlobalRealTimeController() {
|
RealTimeController* GlobalRealTimeController() {
|
||||||
static RealTimeController* time_controller = new RealTimeController();
|
static RealTimeController* time_controller = new RealTimeController();
|
||||||
return time_controller;
|
return time_controller;
|
||||||
|
|||||||
@ -14,10 +14,10 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "api/task_queue/task_queue_factory.h"
|
#include "api/task_queue/task_queue_factory.h"
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
#include "api/units/time_delta.h"
|
#include "api/units/time_delta.h"
|
||||||
#include "modules/utility/include/process_thread.h"
|
#include "modules/utility/include/process_thread.h"
|
||||||
#include "system_wrappers/include/clock.h"
|
#include "system_wrappers/include/clock.h"
|
||||||
#include "test/time_controller/time_controller.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
class RealTimeController : public TimeController {
|
class RealTimeController : public TimeController {
|
||||||
@ -30,6 +30,7 @@ class RealTimeController : public TimeController {
|
|||||||
const char* thread_name) override;
|
const char* thread_name) override;
|
||||||
void Sleep(TimeDelta duration) override;
|
void Sleep(TimeDelta duration) override;
|
||||||
void InvokeWithControlledYield(std::function<void()> closure) override;
|
void InvokeWithControlledYield(std::function<void()> closure) override;
|
||||||
|
rtc::YieldInterface* YieldInterface() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<TaskQueueFactory> task_queue_factory_;
|
std::unique_ptr<TaskQueueFactory> task_queue_factory_;
|
||||||
|
|||||||
@ -440,6 +440,10 @@ void GlobalSimulatedTimeController::InvokeWithControlledYield(
|
|||||||
closure();
|
closure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc::YieldInterface* GlobalSimulatedTimeController::YieldInterface() {
|
||||||
|
return &impl_;
|
||||||
|
}
|
||||||
|
|
||||||
// namespace sim_time_impl
|
// namespace sim_time_impl
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "api/test/time_controller.h"
|
||||||
#include "api/units/timestamp.h"
|
#include "api/units/timestamp.h"
|
||||||
#include "modules/include/module.h"
|
#include "modules/include/module.h"
|
||||||
#include "modules/utility/include/process_thread.h"
|
#include "modules/utility/include/process_thread.h"
|
||||||
@ -24,7 +25,6 @@
|
|||||||
#include "rtc_base/platform_thread_types.h"
|
#include "rtc_base/platform_thread_types.h"
|
||||||
#include "rtc_base/synchronization/yield_policy.h"
|
#include "rtc_base/synchronization/yield_policy.h"
|
||||||
#include "rtc_base/thread_checker.h"
|
#include "rtc_base/thread_checker.h"
|
||||||
#include "test/time_controller/time_controller.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -92,6 +92,7 @@ class GlobalSimulatedTimeController : public TimeController {
|
|||||||
const char* thread_name) override;
|
const char* thread_name) override;
|
||||||
void Sleep(TimeDelta duration) override;
|
void Sleep(TimeDelta duration) override;
|
||||||
void InvokeWithControlledYield(std::function<void()> closure) override;
|
void InvokeWithControlledYield(std::function<void()> closure) override;
|
||||||
|
rtc::YieldInterface* YieldInterface() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rtc::ScopedBaseFakeClock global_clock_;
|
rtc::ScopedBaseFakeClock global_clock_;
|
||||||
|
|||||||
Reference in New Issue
Block a user