1 // Copyright 2018 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_WITH_MESSAGE_PUMP_IMPL_H_ 6 #define BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_WITH_MESSAGE_PUMP_IMPL_H_ 7 8 #include <memory> 9 #include <optional> 10 11 #include "base/base_export.h" 12 #include "base/memory/raw_ptr.h" 13 #include "base/message_loop/message_pump.h" 14 #include "base/message_loop/work_id_provider.h" 15 #include "base/run_loop.h" 16 #include "base/task/common/checked_lock.h" 17 #include "base/task/common/task_annotator.h" 18 #include "base/task/sequence_manager/sequence_manager_impl.h" 19 #include "base/task/sequence_manager/sequenced_task_source.h" 20 #include "base/task/sequence_manager/thread_controller.h" 21 #include "base/task/sequence_manager/thread_controller_power_monitor.h" 22 #include "base/task/sequence_manager/work_deduplicator.h" 23 #include "base/thread_annotations.h" 24 #include "base/threading/hang_watcher.h" 25 #include "base/threading/platform_thread.h" 26 #include "base/threading/sequence_local_storage_map.h" 27 #include "build/build_config.h" 28 29 namespace base { 30 namespace sequence_manager { 31 namespace internal { 32 33 // This is the interface between the SequenceManager and the MessagePump. 34 class BASE_EXPORT ThreadControllerWithMessagePumpImpl 35 : public ThreadController, 36 public MessagePump::Delegate, 37 public RunLoop::Delegate, 38 public RunLoop::NestingObserver { 39 public: 40 static void InitializeFeatures(); 41 static void ResetFeatures(); 42 43 ThreadControllerWithMessagePumpImpl( 44 std::unique_ptr<MessagePump> message_pump, 45 const SequenceManager::Settings& settings); 46 ThreadControllerWithMessagePumpImpl( 47 const ThreadControllerWithMessagePumpImpl&) = delete; 48 ThreadControllerWithMessagePumpImpl& operator=( 49 const ThreadControllerWithMessagePumpImpl&) = delete; 50 ~ThreadControllerWithMessagePumpImpl() override; 51 52 using ShouldScheduleWork = WorkDeduplicator::ShouldScheduleWork; 53 54 static std::unique_ptr<ThreadControllerWithMessagePumpImpl> CreateUnbound( 55 const SequenceManager::Settings& settings); 56 57 // ThreadController implementation: 58 void SetSequencedTaskSource(SequencedTaskSource* task_source) override; 59 void BindToCurrentThread(std::unique_ptr<MessagePump> message_pump) override; 60 void SetWorkBatchSize(int work_batch_size) override; 61 void WillQueueTask(PendingTask* pending_task) override; 62 void ScheduleWork() override; 63 void SetNextDelayedDoWork(LazyNow* lazy_now, 64 std::optional<WakeUp> wake_up) override; 65 bool RunsTasksInCurrentSequence() override; 66 void SetDefaultTaskRunner( 67 scoped_refptr<SingleThreadTaskRunner> task_runner) override; 68 scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override; 69 void RestoreDefaultTaskRunner() override; 70 void AddNestingObserver(RunLoop::NestingObserver* observer) override; 71 void RemoveNestingObserver(RunLoop::NestingObserver* observer) override; 72 void SetTaskExecutionAllowedInNativeNestedLoop(bool allowed) override; 73 bool IsTaskExecutionAllowed() const override; 74 MessagePump* GetBoundMessagePump() const override; 75 void PrioritizeYieldingToNative(base::TimeTicks prioritize_until) override; 76 #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) 77 void AttachToMessagePump() override; 78 #endif 79 #if BUILDFLAG(IS_IOS) 80 void DetachFromMessagePump() override; 81 #endif 82 bool ShouldQuitRunLoopWhenIdle() override; 83 84 // RunLoop::NestingObserver: 85 void OnBeginNestedRunLoop() override; 86 void OnExitNestedRunLoop() override; 87 88 protected: 89 explicit ThreadControllerWithMessagePumpImpl( 90 const SequenceManager::Settings& settings); 91 92 // MessagePump::Delegate implementation. 93 void OnBeginWorkItem() override; 94 void OnEndWorkItem(int run_level_depth) override; 95 void BeforeWait() override; 96 void BeginNativeWorkBeforeDoWork() override; 97 MessagePump::Delegate::NextWorkInfo DoWork() override; 98 bool DoIdleWork() override; 99 int RunDepth() override; 100 101 void OnBeginWorkItemImpl(LazyNow& lazy_now); 102 void OnEndWorkItemImpl(LazyNow& lazy_now, int run_level_depth); 103 104 // RunLoop::Delegate implementation. 105 void Run(bool application_tasks_allowed, TimeDelta timeout) override; 106 void Quit() override; 107 void EnsureWorkScheduled() override; 108 109 struct MainThreadOnly { 110 MainThreadOnly(); 111 ~MainThreadOnly(); 112 113 raw_ptr<SequencedTaskSource> task_source = nullptr; // Not owned. 114 raw_ptr<RunLoop::NestingObserver> nesting_observer = nullptr; // Not owned. 115 std::unique_ptr<SingleThreadTaskRunner::CurrentDefaultHandle> 116 thread_task_runner_handle; 117 118 // Indicates that we should yield DoWork between each task to let a possibly 119 // nested RunLoop exit. 120 bool quit_pending = false; 121 122 // Whether high resolution timing is enabled or not. 123 bool in_high_res_mode = false; 124 125 // Number of tasks processed in a single DoWork invocation. 126 int work_batch_size = 1; 127 128 bool can_change_batch_size = true; 129 130 // While Now() is less than |yield_to_native_after_batch| we will request a 131 // yield to the MessagePump after |work_batch_size| work items. 132 base::TimeTicks yield_to_native_after_batch = base::TimeTicks(); 133 134 // The time after which the runloop should quit. 135 TimeTicks quit_runloop_after = TimeTicks::Max(); 136 137 bool task_execution_allowed = true; 138 }; 139 MainThreadOnlyForTesting()140 const MainThreadOnly& MainThreadOnlyForTesting() const { 141 return main_thread_only_; 142 } 143 ThreadControllerPowerMonitorForTesting()144 ThreadControllerPowerMonitor* ThreadControllerPowerMonitorForTesting() { 145 return &power_monitor_; 146 } 147 148 private: 149 friend class DoWorkScope; 150 friend class RunScope; 151 152 // Returns a WakeUp for the next pending task, is_immediate() if the next task 153 // can run immediately, or nullopt if there are no more immediate or delayed 154 // tasks. 155 std::optional<WakeUp> DoWorkImpl(LazyNow* continuation_lazy_now); 156 157 bool RunsTasksByBatches() const; 158 159 void InitializeSingleThreadTaskRunnerCurrentDefaultHandle() 160 EXCLUSIVE_LOCKS_REQUIRED(task_runner_lock_); 161 main_thread_only()162 MainThreadOnly& main_thread_only() { 163 DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); 164 return main_thread_only_; 165 } 166 main_thread_only()167 const MainThreadOnly& main_thread_only() const { 168 DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); 169 return main_thread_only_; 170 } 171 172 MainThreadOnly main_thread_only_; 173 174 mutable base::internal::CheckedLock task_runner_lock_; 175 scoped_refptr<SingleThreadTaskRunner> task_runner_ 176 GUARDED_BY(task_runner_lock_); 177 178 WorkDeduplicator work_deduplicator_; 179 bool in_native_work_batch_ = false; 180 181 ThreadControllerPowerMonitor power_monitor_; 182 183 TaskAnnotator task_annotator_; 184 185 // Non-null provider of id state for identifying distinct work items executed 186 // by the message loop (task, event, etc.). Cached on the class to avoid TLS 187 // lookups on task execution. 188 raw_ptr<WorkIdProvider> work_id_provider_ = nullptr; 189 190 // Required to register the current thread as a sequence. Must be declared 191 // after |main_thread_only_| so that the destructors of state stored in the 192 // map run while the main thread state is still valid (crbug.com/1221382) 193 base::internal::SequenceLocalStorageMap sequence_local_storage_map_; 194 std::unique_ptr< 195 base::internal::ScopedSetSequenceLocalStorageMapForCurrentThread> 196 scoped_set_sequence_local_storage_map_for_current_thread_; 197 198 // Whether tasks can run by batches (i.e. multiple tasks run between each 199 // check for native work). Tasks will only run by batches if this is true and 200 // the "RunTasksByBatches" feature is enabled. 201 bool can_run_tasks_by_batches_ = false; 202 203 // Reset at the start & end of each unit of work to cover the work itself and 204 // the overhead between each work item (no-op if HangWatcher is not enabled 205 // on this thread). Cleared when going to sleep and at the end of a Run() 206 // (i.e. when Quit()). Nested runs override their parent. 207 std::optional<WatchHangsInScope> hang_watch_scope_; 208 209 // Can only be set once (just before calling 210 // work_deduplicator_.BindToCurrentThread()). After that only read access is 211 // allowed. 212 // NOTE: |pump_| accesses other members but other members should not access 213 // |pump_|. This means that it should be destroyed first. This member cannot 214 // be moved up. 215 std::unique_ptr<MessagePump> pump_; 216 }; 217 218 } // namespace internal 219 } // namespace sequence_manager 220 } // namespace base 221 222 #endif // BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_WITH_MESSAGE_PUMP_IMPL_H_ 223