xref: /aosp_15_r20/external/webrtc/test/time_controller/simulated_time_controller.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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/sequence_checker.h"
21 #include "api/test/time_controller.h"
22 #include "api/units/timestamp.h"
23 #include "rtc_base/fake_clock.h"
24 #include "rtc_base/platform_thread_types.h"
25 #include "rtc_base/synchronization/mutex.h"
26 #include "rtc_base/synchronization/yield_policy.h"
27 
28 namespace webrtc {
29 namespace sim_time_impl {
30 class SimulatedSequenceRunner {
31  public:
32   virtual ~SimulatedSequenceRunner() = default;
33   // Provides next run time.
34   virtual Timestamp GetNextRunTime() const = 0;
35   // Runs all ready tasks and modules and updates next run time.
36   virtual void RunReady(Timestamp at_time) = 0;
37 
38   // All implementations also implements TaskQueueBase in some form, but if we'd
39   // inherit from it in this interface we'd run into issues with double
40   // inheritance. Therefore we simply allow the implementations to provide a
41   // casted pointer to themself.
42   virtual TaskQueueBase* GetAsTaskQueue() = 0;
43 };
44 
45 class SimulatedTimeControllerImpl : public TaskQueueFactory,
46                                     public rtc::YieldInterface {
47  public:
48   explicit SimulatedTimeControllerImpl(Timestamp start_time);
49   ~SimulatedTimeControllerImpl() override;
50 
51   std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
52       absl::string_view name,
53       Priority priority) const RTC_LOCKS_EXCLUDED(time_lock_) override;
54 
55   // Implements the YieldInterface by running ready tasks on all task queues,
56   // except that if this method is called from a task, the task queue running
57   // that task is skipped.
58   void YieldExecution() RTC_LOCKS_EXCLUDED(time_lock_, lock_) override;
59 
60   // Create thread using provided `socket_server`.
61   std::unique_ptr<rtc::Thread> CreateThread(
62       const std::string& name,
63       std::unique_ptr<rtc::SocketServer> socket_server)
64       RTC_LOCKS_EXCLUDED(time_lock_, lock_);
65 
66   // Runs all runners in `runners_` that has tasks or modules ready for
67   // execution.
68   void RunReadyRunners() RTC_LOCKS_EXCLUDED(time_lock_, lock_);
69   // Return `current_time_`.
70   Timestamp CurrentTime() const RTC_LOCKS_EXCLUDED(time_lock_);
71   // Return min of runner->GetNextRunTime() for runner in `runners_`.
72   Timestamp NextRunTime() const RTC_LOCKS_EXCLUDED(lock_);
73   // Set `current_time_` to `target_time`.
74   void AdvanceTime(Timestamp target_time) RTC_LOCKS_EXCLUDED(time_lock_);
75   // Adds `runner` to `runners_`.
76   void Register(SimulatedSequenceRunner* runner) RTC_LOCKS_EXCLUDED(lock_);
77   // Removes `runner` from `runners_`.
78   void Unregister(SimulatedSequenceRunner* runner) RTC_LOCKS_EXCLUDED(lock_);
79 
80   // Indicates that `yielding_from` is not ready to run.
81   void StartYield(TaskQueueBase* yielding_from);
82   // Indicates that processing can be continued on `yielding_from`.
83   void StopYield(TaskQueueBase* yielding_from);
84 
85  private:
86   const rtc::PlatformThreadId thread_id_;
87   const std::unique_ptr<rtc::Thread> dummy_thread_ = rtc::Thread::Create();
88   mutable Mutex time_lock_;
89   Timestamp current_time_ RTC_GUARDED_BY(time_lock_);
90   mutable Mutex lock_;
91   std::vector<SimulatedSequenceRunner*> runners_ RTC_GUARDED_BY(lock_);
92   // Used in RunReadyRunners() to keep track of ready runners that are to be
93   // processed in a round robin fashion. the reason it's a member is so that
94   // runners can removed from here by Unregister().
95   std::list<SimulatedSequenceRunner*> ready_runners_ RTC_GUARDED_BY(lock_);
96 
97   // Runners on which YieldExecution has been called.
98   std::unordered_set<TaskQueueBase*> yielded_;
99 };
100 }  // namespace sim_time_impl
101 
102 // Used to satisfy sequence checkers for non task queue sequences.
103 class TokenTaskQueue : public TaskQueueBase {
104  public:
105   // Promoted to public
106   using CurrentTaskQueueSetter = TaskQueueBase::CurrentTaskQueueSetter;
107 
Delete()108   void Delete() override { RTC_DCHECK_NOTREACHED(); }
PostTask(absl::AnyInvocable<void ()&&>)109   void PostTask(absl::AnyInvocable<void() &&> /*task*/) override {
110     RTC_DCHECK_NOTREACHED();
111   }
PostDelayedTask(absl::AnyInvocable<void ()&&>,TimeDelta)112   void PostDelayedTask(absl::AnyInvocable<void() &&> /*task*/,
113                        TimeDelta /*delay*/) override {
114     RTC_DCHECK_NOTREACHED();
115   }
PostDelayedHighPrecisionTask(absl::AnyInvocable<void ()&&>,TimeDelta)116   void PostDelayedHighPrecisionTask(absl::AnyInvocable<void() &&> /*task*/,
117                                     TimeDelta /*delay*/) override {
118     RTC_DCHECK_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<rtc::Thread> CreateThread(
135       const std::string& name,
136       std::unique_ptr<rtc::SocketServer> socket_server) override;
137   rtc::Thread* GetMainThread() override;
138 
139   void AdvanceTime(TimeDelta duration) override;
140 
141   // Makes the simulated time controller aware of a custom
142   // SimulatedSequenceRunner.
143   // TODO(bugs.webrtc.org/11581): remove method once the ModuleRtpRtcpImpl2 unit
144   // test stops using it.
145   void Register(sim_time_impl::SimulatedSequenceRunner* runner);
146   // Removes a previously installed custom SimulatedSequenceRunner from the
147   // simulated time controller.
148   // TODO(bugs.webrtc.org/11581): remove method once the ModuleRtpRtcpImpl2 unit
149   // test stops using it.
150   void Unregister(sim_time_impl::SimulatedSequenceRunner* runner);
151 
152  private:
153   rtc::ScopedBaseFakeClock global_clock_;
154   // Provides simulated CurrentNtpInMilliseconds()
155   SimulatedClock sim_clock_;
156   sim_time_impl::SimulatedTimeControllerImpl impl_;
157   rtc::ScopedYieldPolicy yield_policy_;
158   std::unique_ptr<rtc::Thread> main_thread_;
159 };
160 }  // namespace webrtc
161 
162 #endif  // TEST_TIME_CONTROLLER_SIMULATED_TIME_CONTROLLER_H_
163