• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "rtc_base/task_utils/to_queued_task.h"
16 
17 namespace webrtc {
18 namespace {
19 
20 // A socket server that does nothing. It's different from NullSocketServer in
21 // that it does allow sleep/wakeup. This avoids usage of an Event instance which
22 // otherwise would cause issues with the simulated Yeild behavior.
23 class DummySocketServer : public rtc::SocketServer {
24  public:
CreateSocket(int family,int type)25   rtc::Socket* CreateSocket(int family, int type) override {
26     RTC_NOTREACHED();
27     return nullptr;
28   }
CreateAsyncSocket(int family,int type)29   rtc::AsyncSocket* CreateAsyncSocket(int family, int type) override {
30     RTC_NOTREACHED();
31     return nullptr;
32   }
Wait(int cms,bool process_io)33   bool Wait(int cms, bool process_io) override {
34     RTC_CHECK_EQ(cms, 0);
35     return true;
36   }
WakeUp()37   void WakeUp() override {}
38 };
39 
40 }  // namespace
41 
SimulatedThread(sim_time_impl::SimulatedTimeControllerImpl * handler,absl::string_view name,std::unique_ptr<rtc::SocketServer> socket_server)42 SimulatedThread::SimulatedThread(
43     sim_time_impl::SimulatedTimeControllerImpl* handler,
44     absl::string_view name,
45     std::unique_ptr<rtc::SocketServer> socket_server)
46     : rtc::Thread(socket_server ? std::move(socket_server)
47                                 : std::make_unique<DummySocketServer>()),
48       handler_(handler),
49       name_(new char[name.size()]) {
50   std::copy_n(name.begin(), name.size(), name_);
51 }
52 
~SimulatedThread()53 SimulatedThread::~SimulatedThread() {
54   handler_->Unregister(this);
55   delete[] name_;
56 }
57 
RunReady(Timestamp at_time)58 void SimulatedThread::RunReady(Timestamp at_time) {
59   CurrentThreadSetter set_current(this);
60   ProcessMessages(0);
61   int delay_ms = GetDelay();
62   MutexLock lock(&lock_);
63   if (delay_ms == kForever) {
64     next_run_time_ = Timestamp::PlusInfinity();
65   } else {
66     next_run_time_ = at_time + TimeDelta::Millis(delay_ms);
67   }
68 }
69 
Send(const rtc::Location & posted_from,rtc::MessageHandler * phandler,uint32_t id,rtc::MessageData * pdata)70 void SimulatedThread::Send(const rtc::Location& posted_from,
71                            rtc::MessageHandler* phandler,
72                            uint32_t id,
73                            rtc::MessageData* pdata) {
74   if (IsQuitting())
75     return;
76   rtc::Message msg;
77   msg.posted_from = posted_from;
78   msg.phandler = phandler;
79   msg.message_id = id;
80   msg.pdata = pdata;
81   if (IsCurrent()) {
82     msg.phandler->OnMessage(&msg);
83   } else {
84     TaskQueueBase* yielding_from = TaskQueueBase::Current();
85     handler_->StartYield(yielding_from);
86     CurrentThreadSetter set_current(this);
87     msg.phandler->OnMessage(&msg);
88     handler_->StopYield(yielding_from);
89   }
90 }
91 
Post(const rtc::Location & posted_from,rtc::MessageHandler * phandler,uint32_t id,rtc::MessageData * pdata,bool time_sensitive)92 void SimulatedThread::Post(const rtc::Location& posted_from,
93                            rtc::MessageHandler* phandler,
94                            uint32_t id,
95                            rtc::MessageData* pdata,
96                            bool time_sensitive) {
97   rtc::Thread::Post(posted_from, phandler, id, pdata, time_sensitive);
98   MutexLock lock(&lock_);
99   next_run_time_ = Timestamp::MinusInfinity();
100 }
101 
PostDelayed(const rtc::Location & posted_from,int delay_ms,rtc::MessageHandler * phandler,uint32_t id,rtc::MessageData * pdata)102 void SimulatedThread::PostDelayed(const rtc::Location& posted_from,
103                                   int delay_ms,
104                                   rtc::MessageHandler* phandler,
105                                   uint32_t id,
106                                   rtc::MessageData* pdata) {
107   rtc::Thread::PostDelayed(posted_from, delay_ms, phandler, id, pdata);
108   MutexLock lock(&lock_);
109   next_run_time_ =
110       std::min(next_run_time_, Timestamp::Millis(rtc::TimeMillis() + delay_ms));
111 }
112 
PostAt(const rtc::Location & posted_from,int64_t target_time_ms,rtc::MessageHandler * phandler,uint32_t id,rtc::MessageData * pdata)113 void SimulatedThread::PostAt(const rtc::Location& posted_from,
114                              int64_t target_time_ms,
115                              rtc::MessageHandler* phandler,
116                              uint32_t id,
117                              rtc::MessageData* pdata) {
118   rtc::Thread::PostAt(posted_from, target_time_ms, phandler, id, pdata);
119   MutexLock lock(&lock_);
120   next_run_time_ = std::min(next_run_time_, Timestamp::Millis(target_time_ms));
121 }
122 
Stop()123 void SimulatedThread::Stop() {
124   Thread::Quit();
125 }
126 
SimulatedMainThread(sim_time_impl::SimulatedTimeControllerImpl * handler)127 SimulatedMainThread::SimulatedMainThread(
128     sim_time_impl::SimulatedTimeControllerImpl* handler)
129     : SimulatedThread(handler, "main", nullptr), current_setter_(this) {}
130 
~SimulatedMainThread()131 SimulatedMainThread::~SimulatedMainThread() {
132   // Removes pending tasks in case they keep shared pointer references to
133   // objects whose destructor expects to run before the Thread destructor.
134   Stop();
135   DoDestroy();
136 }
137 
138 }  // namespace webrtc
139