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