• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 #include "base/base_export.h"
11 #include "base/memory/raw_ptr.h"
12 #include "base/message_loop/message_pump.h"
13 #include "base/message_loop/work_id_provider.h"
14 #include "base/run_loop.h"
15 #include "base/task/common/checked_lock.h"
16 #include "base/task/common/task_annotator.h"
17 #include "base/task/sequence_manager/sequence_manager_impl.h"
18 #include "base/task/sequence_manager/sequenced_task_source.h"
19 #include "base/task/sequence_manager/thread_controller.h"
20 #include "base/task/sequence_manager/thread_controller_power_monitor.h"
21 #include "base/task/sequence_manager/work_deduplicator.h"
22 #include "base/thread_annotations.h"
23 #include "base/threading/hang_watcher.h"
24 #include "base/threading/platform_thread.h"
25 #include "base/threading/sequence_local_storage_map.h"
26 #include "build/build_config.h"
27 #include "third_party/abseil-cpp/absl/types/optional.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                             absl::optional<WakeUp> wake_up) override;
65   void SetTimerSlack(TimerSlack timer_slack) override;
66   bool RunsTasksInCurrentSequence() override;
67   void SetDefaultTaskRunner(
68       scoped_refptr<SingleThreadTaskRunner> task_runner) override;
69   scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override;
70   void RestoreDefaultTaskRunner() override;
71   void AddNestingObserver(RunLoop::NestingObserver* observer) override;
72   void RemoveNestingObserver(RunLoop::NestingObserver* observer) override;
73   void SetTaskExecutionAllowed(bool allowed) override;
74   bool IsTaskExecutionAllowed() const override;
75   MessagePump* GetBoundMessagePump() const override;
76   void PrioritizeYieldingToNative(base::TimeTicks prioritize_until) override;
77 #if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID)
78   void AttachToMessagePump() override;
79 #endif
80 #if BUILDFLAG(IS_IOS)
81   void DetachFromMessagePump() override;
82 #endif
83   bool ShouldQuitRunLoopWhenIdle() override;
84 
85   // RunLoop::NestingObserver:
86   void OnBeginNestedRunLoop() override;
87   void OnExitNestedRunLoop() override;
88 
89  protected:
90   explicit ThreadControllerWithMessagePumpImpl(
91       const SequenceManager::Settings& settings);
92 
93   // MessagePump::Delegate implementation.
94   void OnBeginWorkItem() override;
95   void OnEndWorkItem(int run_level_depth) override;
96   void BeforeWait() 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     // When the next scheduled delayed work should run, if any.
135     TimeTicks next_delayed_do_work = TimeTicks::Max();
136 
137     // The time after which the runloop should quit.
138     TimeTicks quit_runloop_after = TimeTicks::Max();
139 
140     bool task_execution_allowed = true;
141   };
142 
MainThreadOnlyForTesting()143   const MainThreadOnly& MainThreadOnlyForTesting() const {
144     return main_thread_only_;
145   }
146 
ThreadControllerPowerMonitorForTesting()147   ThreadControllerPowerMonitor* ThreadControllerPowerMonitorForTesting() {
148     return &power_monitor_;
149   }
150 
151  private:
152   friend class DoWorkScope;
153   friend class RunScope;
154 
155   // Returns a WakeUp for the next pending task, is_immediate() if the next task
156   // can run immediately, or nullopt if there are no more immediate or delayed
157   // tasks.
158   absl::optional<WakeUp> DoWorkImpl(LazyNow* continuation_lazy_now);
159 
160   bool RunsTasksByBatches() const;
161 
162   void InitializeSingleThreadTaskRunnerCurrentDefaultHandle()
163       EXCLUSIVE_LOCKS_REQUIRED(task_runner_lock_);
164 
main_thread_only()165   MainThreadOnly& main_thread_only() {
166     DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
167     return main_thread_only_;
168   }
169 
main_thread_only()170   const MainThreadOnly& main_thread_only() const {
171     DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
172     return main_thread_only_;
173   }
174 
175   MainThreadOnly main_thread_only_;
176 
177   mutable base::internal::CheckedLock task_runner_lock_;
178   scoped_refptr<SingleThreadTaskRunner> task_runner_
179       GUARDED_BY(task_runner_lock_);
180 
181   WorkDeduplicator work_deduplicator_;
182 
183   ThreadControllerPowerMonitor power_monitor_;
184 
185   TaskAnnotator task_annotator_;
186 
187   // Non-null provider of id state for identifying distinct work items executed
188   // by the message loop (task, event, etc.). Cached on the class to avoid TLS
189   // lookups on task execution.
190   raw_ptr<WorkIdProvider> work_id_provider_ = nullptr;
191 
192   // Required to register the current thread as a sequence. Must be declared
193   // after |main_thread_only_| so that the destructors of state stored in the
194   // map run while the main thread state is still valid (crbug.com/1221382)
195   base::internal::SequenceLocalStorageMap sequence_local_storage_map_;
196   std::unique_ptr<
197       base::internal::ScopedSetSequenceLocalStorageMapForCurrentThread>
198       scoped_set_sequence_local_storage_map_for_current_thread_;
199 
200   // Whether tasks can run by batches (i.e. multiple tasks run between each
201   // check for native work). Tasks will only run by batches if this is true and
202   // the "RunTasksByBatches" feature is enabled.
203   bool can_run_tasks_by_batches_ = false;
204 
205   // Reset at the start & end of each unit of work to cover the work itself and
206   // the overhead between each work item (no-op if HangWatcher is not enabled
207   // on this thread). Cleared when going to sleep and at the end of a Run()
208   // (i.e. when Quit()). Nested runs override their parent.
209   absl::optional<WatchHangsInScope> hang_watch_scope_;
210 
211   // Can only be set once (just before calling
212   // work_deduplicator_.BindToCurrentThread()). After that only read access is
213   // allowed.
214   // NOTE: |pump_| accesses other members but other members should not access
215   // |pump_|. This means that it should be destroyed first. This member cannot
216   // be moved up.
217   std::unique_ptr<MessagePump> pump_;
218 };
219 
220 }  // namespace internal
221 }  // namespace sequence_manager
222 }  // namespace base
223 
224 #endif  // BASE_TASK_SEQUENCE_MANAGER_THREAD_CONTROLLER_WITH_MESSAGE_PUMP_IMPL_H_
225