1 /* 2 * Copyright 2019 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 #ifndef TEST_TIME_CONTROLLER_SIMULATED_TIME_CONTROLLER_H_ 11 #define TEST_TIME_CONTROLLER_SIMULATED_TIME_CONTROLLER_H_ 12 13 #include <list> 14 #include <memory> 15 #include <unordered_set> 16 #include <utility> 17 #include <vector> 18 19 #include "absl/strings/string_view.h" 20 #include "api/test/time_controller.h" 21 #include "api/units/timestamp.h" 22 #include "modules/include/module.h" 23 #include "modules/utility/include/process_thread.h" 24 #include "rtc_base/fake_clock.h" 25 #include "rtc_base/platform_thread_types.h" 26 #include "rtc_base/synchronization/mutex.h" 27 #include "rtc_base/synchronization/yield_policy.h" 28 #include "rtc_base/thread_checker.h" 29 30 namespace webrtc { 31 namespace sim_time_impl { 32 class SimulatedSequenceRunner { 33 public: 34 virtual ~SimulatedSequenceRunner() = default; 35 // Provides next run time. 36 virtual Timestamp GetNextRunTime() const = 0; 37 // Runs all ready tasks and modules and updates next run time. 38 virtual void RunReady(Timestamp at_time) = 0; 39 40 // All implementations also implements TaskQueueBase in some form, but if we'd 41 // inherit from it in this interface we'd run into issues with double 42 // inheritance. Therefore we simply allow the implementations to provide a 43 // casted pointer to themself. 44 virtual TaskQueueBase* GetAsTaskQueue() = 0; 45 }; 46 47 class SimulatedTimeControllerImpl : public TaskQueueFactory, 48 public rtc::YieldInterface { 49 public: 50 explicit SimulatedTimeControllerImpl(Timestamp start_time); 51 ~SimulatedTimeControllerImpl() override; 52 53 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue( 54 absl::string_view name, 55 Priority priority) const RTC_LOCKS_EXCLUDED(time_lock_) override; 56 57 // Implements the YieldInterface by running ready tasks on all task queues, 58 // except that if this method is called from a task, the task queue running 59 // that task is skipped. 60 void YieldExecution() RTC_LOCKS_EXCLUDED(time_lock_, lock_) override; 61 // Create process thread with the name |thread_name|. 62 std::unique_ptr<ProcessThread> CreateProcessThread(const char* thread_name) 63 RTC_LOCKS_EXCLUDED(time_lock_, lock_); 64 // Create thread using provided |socket_server|. 65 std::unique_ptr<rtc::Thread> CreateThread( 66 const std::string& name, 67 std::unique_ptr<rtc::SocketServer> socket_server) 68 RTC_LOCKS_EXCLUDED(time_lock_, lock_); 69 70 // Runs all runners in |runners_| that has tasks or modules ready for 71 // execution. 72 void RunReadyRunners() RTC_LOCKS_EXCLUDED(time_lock_, lock_); 73 // Return |current_time_|. 74 Timestamp CurrentTime() const RTC_LOCKS_EXCLUDED(time_lock_); 75 // Return min of runner->GetNextRunTime() for runner in |runners_|. 76 Timestamp NextRunTime() const RTC_LOCKS_EXCLUDED(lock_); 77 // Set |current_time_| to |target_time|. 78 void AdvanceTime(Timestamp target_time) RTC_LOCKS_EXCLUDED(time_lock_); 79 // Adds |runner| to |runners_|. 80 void Register(SimulatedSequenceRunner* runner) RTC_LOCKS_EXCLUDED(lock_); 81 // Removes |runner| from |runners_|. 82 void Unregister(SimulatedSequenceRunner* runner) RTC_LOCKS_EXCLUDED(lock_); 83 84 // Indicates that |yielding_from| is not ready to run. 85 void StartYield(TaskQueueBase* yielding_from); 86 // Indicates that processing can be continued on |yielding_from|. 87 void StopYield(TaskQueueBase* yielding_from); 88 89 private: 90 const rtc::PlatformThreadId thread_id_; 91 const std::unique_ptr<rtc::Thread> dummy_thread_ = rtc::Thread::Create(); 92 mutable Mutex time_lock_; 93 Timestamp current_time_ RTC_GUARDED_BY(time_lock_); 94 mutable Mutex lock_; 95 std::vector<SimulatedSequenceRunner*> runners_ RTC_GUARDED_BY(lock_); 96 // Used in RunReadyRunners() to keep track of ready runners that are to be 97 // processed in a round robin fashion. the reason it's a member is so that 98 // runners can removed from here by Unregister(). 99 std::list<SimulatedSequenceRunner*> ready_runners_ RTC_GUARDED_BY(lock_); 100 101 // Runners on which YieldExecution has been called. 102 std::unordered_set<TaskQueueBase*> yielded_; 103 }; 104 } // namespace sim_time_impl 105 106 // Used to satisfy sequence checkers for non task queue sequences. 107 class TokenTaskQueue : public TaskQueueBase { 108 public: 109 // Promoted to public 110 using CurrentTaskQueueSetter = TaskQueueBase::CurrentTaskQueueSetter; 111 Delete()112 void Delete() override { RTC_NOTREACHED(); } PostTask(std::unique_ptr<QueuedTask>)113 void PostTask(std::unique_ptr<QueuedTask> /*task*/) override { 114 RTC_NOTREACHED(); 115 } PostDelayedTask(std::unique_ptr<QueuedTask>,uint32_t)116 void PostDelayedTask(std::unique_ptr<QueuedTask> /*task*/, 117 uint32_t /*milliseconds*/) override { 118 RTC_NOTREACHED(); 119 } 120 }; 121 122 // TimeController implementation using completely simulated time. Task queues 123 // and process threads created by this controller will run delayed activities 124 // when AdvanceTime() is called. Overrides the global clock backing 125 // rtc::TimeMillis() and rtc::TimeMicros(). Note that this is not thread safe 126 // since it modifies global state. 127 class GlobalSimulatedTimeController : public TimeController { 128 public: 129 explicit GlobalSimulatedTimeController(Timestamp start_time); 130 ~GlobalSimulatedTimeController() override; 131 132 Clock* GetClock() override; 133 TaskQueueFactory* GetTaskQueueFactory() override; 134 std::unique_ptr<ProcessThread> CreateProcessThread( 135 const char* thread_name) override; 136 std::unique_ptr<rtc::Thread> CreateThread( 137 const std::string& name, 138 std::unique_ptr<rtc::SocketServer> socket_server) override; 139 rtc::Thread* GetMainThread() override; 140 141 void AdvanceTime(TimeDelta duration) override; 142 143 private: 144 rtc::ScopedBaseFakeClock global_clock_; 145 // Provides simulated CurrentNtpInMilliseconds() 146 SimulatedClock sim_clock_; 147 sim_time_impl::SimulatedTimeControllerImpl impl_; 148 rtc::ScopedYieldPolicy yield_policy_; 149 std::unique_ptr<rtc::Thread> main_thread_; 150 }; 151 } // namespace webrtc 152 153 #endif // TEST_TIME_CONTROLLER_SIMULATED_TIME_CONTROLLER_H_ 154