Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 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 | |
Sebastian Jansson | 7b6add3 | 2019-03-29 10:34:26 +0100 | [diff] [blame] | 13 | #include <list> |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 14 | #include <memory> |
| 15 | #include <unordered_set> |
| 16 | #include <utility> |
| 17 | #include <vector> |
| 18 | |
Sebastian Jansson | 53cd9e2 | 2020-01-13 10:33:19 +0100 | [diff] [blame] | 19 | #include "absl/strings/string_view.h" |
Bjorn A Mellem | c4f8654 | 2019-11-21 10:37:18 -0800 | [diff] [blame] | 20 | #include "api/test/time_controller.h" |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 21 | #include "api/units/timestamp.h" |
| 22 | #include "modules/include/module.h" |
| 23 | #include "modules/utility/include/process_thread.h" |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 24 | #include "rtc_base/fake_clock.h" |
| 25 | #include "rtc_base/platform_thread_types.h" |
Markus Handell | e56976d | 2020-07-08 17:34:37 +0200 | [diff] [blame] | 26 | #include "rtc_base/synchronization/mutex.h" |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 27 | #include "rtc_base/synchronization/yield_policy.h" |
| 28 | #include "rtc_base/thread_checker.h" |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 29 | |
| 30 | namespace webrtc { |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 31 | namespace sim_time_impl { |
Sebastian Jansson | 53cd9e2 | 2020-01-13 10:33:19 +0100 | [diff] [blame] | 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 | }; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 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, |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 55 | Priority priority) const RTC_LOCKS_EXCLUDED(time_lock_) override; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 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. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 60 | void YieldExecution() RTC_LOCKS_EXCLUDED(time_lock_, lock_) override; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 61 | // Create process thread with the name |thread_name|. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 62 | std::unique_ptr<ProcessThread> CreateProcessThread(const char* thread_name) |
| 63 | RTC_LOCKS_EXCLUDED(time_lock_, lock_); |
Sebastian Jansson | fc8279d | 2020-01-16 11:45:59 +0100 | [diff] [blame] | 64 | // Create thread using provided |socket_server|. |
| 65 | std::unique_ptr<rtc::Thread> CreateThread( |
| 66 | const std::string& name, |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 67 | std::unique_ptr<rtc::SocketServer> socket_server) |
| 68 | RTC_LOCKS_EXCLUDED(time_lock_, lock_); |
Sebastian Jansson | 53cd9e2 | 2020-01-13 10:33:19 +0100 | [diff] [blame] | 69 | |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 70 | // Runs all runners in |runners_| that has tasks or modules ready for |
| 71 | // execution. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 72 | void RunReadyRunners() RTC_LOCKS_EXCLUDED(time_lock_, lock_); |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 73 | // Return |current_time_|. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 74 | Timestamp CurrentTime() const RTC_LOCKS_EXCLUDED(time_lock_); |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 75 | // Return min of runner->GetNextRunTime() for runner in |runners_|. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 76 | Timestamp NextRunTime() const RTC_LOCKS_EXCLUDED(lock_); |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 77 | // Set |current_time_| to |target_time|. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 78 | void AdvanceTime(Timestamp target_time) RTC_LOCKS_EXCLUDED(time_lock_); |
Sebastian Jansson | fc8279d | 2020-01-16 11:45:59 +0100 | [diff] [blame] | 79 | // Adds |runner| to |runners_|. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 80 | void Register(SimulatedSequenceRunner* runner) RTC_LOCKS_EXCLUDED(lock_); |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 81 | // Removes |runner| from |runners_|. |
Markus Handell | 222598d | 2020-05-15 18:43:05 +0200 | [diff] [blame] | 82 | void Unregister(SimulatedSequenceRunner* runner) RTC_LOCKS_EXCLUDED(lock_); |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 83 | |
Sebastian Jansson | 274cc7f | 2020-01-17 13:58:54 +0100 | [diff] [blame] | 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 | |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 89 | private: |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 90 | const rtc::PlatformThreadId thread_id_; |
Sebastian Jansson | fc8279d | 2020-01-16 11:45:59 +0100 | [diff] [blame] | 91 | const std::unique_ptr<rtc::Thread> dummy_thread_ = rtc::Thread::Create(); |
Markus Handell | e56976d | 2020-07-08 17:34:37 +0200 | [diff] [blame] | 92 | mutable Mutex time_lock_; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 93 | Timestamp current_time_ RTC_GUARDED_BY(time_lock_); |
Markus Handell | e56976d | 2020-07-08 17:34:37 +0200 | [diff] [blame] | 94 | mutable Mutex lock_; |
Sebastian Jansson | 7b6add3 | 2019-03-29 10:34:26 +0100 | [diff] [blame] | 95 | std::vector<SimulatedSequenceRunner*> runners_ RTC_GUARDED_BY(lock_); |
Sebastian Jansson | 7654081 | 2019-04-11 17:48:30 +0200 | [diff] [blame] | 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 | |
Sebastian Jansson | 53cd9e2 | 2020-01-13 10:33:19 +0100 | [diff] [blame] | 101 | // Runners on which YieldExecution has been called. |
| 102 | std::unordered_set<TaskQueueBase*> yielded_; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 103 | }; |
| 104 | } // namespace sim_time_impl |
| 105 | |
Sebastian Jansson | 53cd9e2 | 2020-01-13 10:33:19 +0100 | [diff] [blame] | 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 | |
| 112 | void Delete() override { RTC_NOTREACHED(); } |
| 113 | void PostTask(std::unique_ptr<QueuedTask> /*task*/) override { |
| 114 | RTC_NOTREACHED(); |
| 115 | } |
| 116 | void PostDelayedTask(std::unique_ptr<QueuedTask> /*task*/, |
| 117 | uint32_t /*milliseconds*/) override { |
| 118 | RTC_NOTREACHED(); |
| 119 | } |
| 120 | }; |
| 121 | |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 122 | // TimeController implementation using completely simulated time. Task queues |
| 123 | // and process threads created by this controller will run delayed activities |
Markus Handell | 486cc55 | 2019-12-03 14:37:28 +0100 | [diff] [blame] | 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. |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 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; |
Sebastian Jansson | fc8279d | 2020-01-16 11:45:59 +0100 | [diff] [blame] | 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; |
Sebastian Jansson | 53cd9e2 | 2020-01-13 10:33:19 +0100 | [diff] [blame] | 140 | |
Markus Handell | 486cc55 | 2019-12-03 14:37:28 +0100 | [diff] [blame] | 141 | void AdvanceTime(TimeDelta duration) override; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 142 | |
| 143 | private: |
Sebastian Jansson | d624c39 | 2019-04-17 10:36:03 +0200 | [diff] [blame] | 144 | rtc::ScopedBaseFakeClock global_clock_; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 145 | // Provides simulated CurrentNtpInMilliseconds() |
| 146 | SimulatedClock sim_clock_; |
| 147 | sim_time_impl::SimulatedTimeControllerImpl impl_; |
Sebastian Jansson | 340af97 | 2019-12-04 10:07:48 +0100 | [diff] [blame] | 148 | rtc::ScopedYieldPolicy yield_policy_; |
Sebastian Jansson | fc8279d | 2020-01-16 11:45:59 +0100 | [diff] [blame] | 149 | std::unique_ptr<rtc::Thread> main_thread_; |
Sebastian Jansson | 0d617cc | 2019-03-22 15:22:16 +0100 | [diff] [blame] | 150 | }; |
| 151 | } // namespace webrtc |
| 152 | |
| 153 | #endif // TEST_TIME_CONTROLLER_SIMULATED_TIME_CONTROLLER_H_ |