xref: /aosp_15_r20/external/webrtc/test/time_controller/simulated_thread.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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