1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker #include "test/time_controller/simulated_thread.h"
11*d9f75844SAndroid Build Coastguard Worker
12*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
13*d9f75844SAndroid Build Coastguard Worker #include <utility>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
16*d9f75844SAndroid Build Coastguard Worker namespace {
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker // A socket server that does nothing. It's different from NullSocketServer in
19*d9f75844SAndroid Build Coastguard Worker // that it does allow sleep/wakeup. This avoids usage of an Event instance which
20*d9f75844SAndroid Build Coastguard Worker // otherwise would cause issues with the simulated Yeild behavior.
21*d9f75844SAndroid Build Coastguard Worker class DummySocketServer : public rtc::SocketServer {
22*d9f75844SAndroid Build Coastguard Worker public:
CreateSocket(int family,int type)23*d9f75844SAndroid Build Coastguard Worker rtc::Socket* CreateSocket(int family, int type) override {
24*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
25*d9f75844SAndroid Build Coastguard Worker return nullptr;
26*d9f75844SAndroid Build Coastguard Worker }
Wait(TimeDelta max_wait_duration,bool process_io)27*d9f75844SAndroid Build Coastguard Worker bool Wait(TimeDelta max_wait_duration, bool process_io) override {
28*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(max_wait_duration.IsZero());
29*d9f75844SAndroid Build Coastguard Worker return true;
30*d9f75844SAndroid Build Coastguard Worker }
WakeUp()31*d9f75844SAndroid Build Coastguard Worker void WakeUp() override {}
32*d9f75844SAndroid Build Coastguard Worker };
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker } // namespace
35*d9f75844SAndroid Build Coastguard Worker
SimulatedThread(sim_time_impl::SimulatedTimeControllerImpl * handler,absl::string_view name,std::unique_ptr<rtc::SocketServer> socket_server)36*d9f75844SAndroid Build Coastguard Worker SimulatedThread::SimulatedThread(
37*d9f75844SAndroid Build Coastguard Worker sim_time_impl::SimulatedTimeControllerImpl* handler,
38*d9f75844SAndroid Build Coastguard Worker absl::string_view name,
39*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SocketServer> socket_server)
40*d9f75844SAndroid Build Coastguard Worker : rtc::Thread(socket_server ? std::move(socket_server)
41*d9f75844SAndroid Build Coastguard Worker : std::make_unique<DummySocketServer>()),
42*d9f75844SAndroid Build Coastguard Worker handler_(handler),
43*d9f75844SAndroid Build Coastguard Worker name_(new char[name.size()]) {
44*d9f75844SAndroid Build Coastguard Worker std::copy_n(name.begin(), name.size(), name_);
45*d9f75844SAndroid Build Coastguard Worker }
46*d9f75844SAndroid Build Coastguard Worker
~SimulatedThread()47*d9f75844SAndroid Build Coastguard Worker SimulatedThread::~SimulatedThread() {
48*d9f75844SAndroid Build Coastguard Worker handler_->Unregister(this);
49*d9f75844SAndroid Build Coastguard Worker delete[] name_;
50*d9f75844SAndroid Build Coastguard Worker }
51*d9f75844SAndroid Build Coastguard Worker
RunReady(Timestamp at_time)52*d9f75844SAndroid Build Coastguard Worker void SimulatedThread::RunReady(Timestamp at_time) {
53*d9f75844SAndroid Build Coastguard Worker CurrentThreadSetter set_current(this);
54*d9f75844SAndroid Build Coastguard Worker ProcessMessages(0);
55*d9f75844SAndroid Build Coastguard Worker int delay_ms = GetDelay();
56*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
57*d9f75844SAndroid Build Coastguard Worker if (delay_ms == kForever) {
58*d9f75844SAndroid Build Coastguard Worker next_run_time_ = Timestamp::PlusInfinity();
59*d9f75844SAndroid Build Coastguard Worker } else {
60*d9f75844SAndroid Build Coastguard Worker next_run_time_ = at_time + TimeDelta::Millis(delay_ms);
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker }
63*d9f75844SAndroid Build Coastguard Worker
BlockingCall(rtc::FunctionView<void ()> functor)64*d9f75844SAndroid Build Coastguard Worker void SimulatedThread::BlockingCall(rtc::FunctionView<void()> functor) {
65*d9f75844SAndroid Build Coastguard Worker if (IsQuitting())
66*d9f75844SAndroid Build Coastguard Worker return;
67*d9f75844SAndroid Build Coastguard Worker
68*d9f75844SAndroid Build Coastguard Worker if (IsCurrent()) {
69*d9f75844SAndroid Build Coastguard Worker functor();
70*d9f75844SAndroid Build Coastguard Worker } else {
71*d9f75844SAndroid Build Coastguard Worker TaskQueueBase* yielding_from = TaskQueueBase::Current();
72*d9f75844SAndroid Build Coastguard Worker handler_->StartYield(yielding_from);
73*d9f75844SAndroid Build Coastguard Worker RunReady(Timestamp::MinusInfinity());
74*d9f75844SAndroid Build Coastguard Worker CurrentThreadSetter set_current(this);
75*d9f75844SAndroid Build Coastguard Worker functor();
76*d9f75844SAndroid Build Coastguard Worker handler_->StopYield(yielding_from);
77*d9f75844SAndroid Build Coastguard Worker }
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker
PostTask(absl::AnyInvocable<void ()&&> task)80*d9f75844SAndroid Build Coastguard Worker void SimulatedThread::PostTask(absl::AnyInvocable<void() &&> task) {
81*d9f75844SAndroid Build Coastguard Worker rtc::Thread::PostTask(std::move(task));
82*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
83*d9f75844SAndroid Build Coastguard Worker next_run_time_ = Timestamp::MinusInfinity();
84*d9f75844SAndroid Build Coastguard Worker }
85*d9f75844SAndroid Build Coastguard Worker
PostDelayedTask(absl::AnyInvocable<void ()&&> task,TimeDelta delay)86*d9f75844SAndroid Build Coastguard Worker void SimulatedThread::PostDelayedTask(absl::AnyInvocable<void() &&> task,
87*d9f75844SAndroid Build Coastguard Worker TimeDelta delay) {
88*d9f75844SAndroid Build Coastguard Worker rtc::Thread::PostDelayedTask(std::move(task), delay);
89*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
90*d9f75844SAndroid Build Coastguard Worker next_run_time_ =
91*d9f75844SAndroid Build Coastguard Worker std::min(next_run_time_, Timestamp::Millis(rtc::TimeMillis()) + delay);
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker
PostDelayedHighPrecisionTask(absl::AnyInvocable<void ()&&> task,TimeDelta delay)94*d9f75844SAndroid Build Coastguard Worker void SimulatedThread::PostDelayedHighPrecisionTask(
95*d9f75844SAndroid Build Coastguard Worker absl::AnyInvocable<void() &&> task,
96*d9f75844SAndroid Build Coastguard Worker TimeDelta delay) {
97*d9f75844SAndroid Build Coastguard Worker rtc::Thread::PostDelayedHighPrecisionTask(std::move(task), delay);
98*d9f75844SAndroid Build Coastguard Worker MutexLock lock(&lock_);
99*d9f75844SAndroid Build Coastguard Worker next_run_time_ =
100*d9f75844SAndroid Build Coastguard Worker std::min(next_run_time_, Timestamp::Millis(rtc::TimeMillis()) + delay);
101*d9f75844SAndroid Build Coastguard Worker }
102*d9f75844SAndroid Build Coastguard Worker
Stop()103*d9f75844SAndroid Build Coastguard Worker void SimulatedThread::Stop() {
104*d9f75844SAndroid Build Coastguard Worker Thread::Quit();
105*d9f75844SAndroid Build Coastguard Worker }
106*d9f75844SAndroid Build Coastguard Worker
SimulatedMainThread(sim_time_impl::SimulatedTimeControllerImpl * handler)107*d9f75844SAndroid Build Coastguard Worker SimulatedMainThread::SimulatedMainThread(
108*d9f75844SAndroid Build Coastguard Worker sim_time_impl::SimulatedTimeControllerImpl* handler)
109*d9f75844SAndroid Build Coastguard Worker : SimulatedThread(handler, "main", nullptr), current_setter_(this) {}
110*d9f75844SAndroid Build Coastguard Worker
~SimulatedMainThread()111*d9f75844SAndroid Build Coastguard Worker SimulatedMainThread::~SimulatedMainThread() {
112*d9f75844SAndroid Build Coastguard Worker // Removes pending tasks in case they keep shared pointer references to
113*d9f75844SAndroid Build Coastguard Worker // objects whose destructor expects to run before the Thread destructor.
114*d9f75844SAndroid Build Coastguard Worker Stop();
115*d9f75844SAndroid Build Coastguard Worker DoDestroy();
116*d9f75844SAndroid Build Coastguard Worker }
117*d9f75844SAndroid Build Coastguard Worker
118*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
119