OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_ | 5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_ |
6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_ | 6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_ |
7 | 7 |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/atomic_sequence_num.h" | 10 #include "base/atomic_sequence_num.h" |
11 #include "base/cancelable_callback.h" | |
12 #include "base/debug/task_annotator.h" | 11 #include "base/debug/task_annotator.h" |
13 #include "base/macros.h" | 12 #include "base/macros.h" |
14 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
15 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
16 #include "base/pending_task.h" | 15 #include "base/pending_task.h" |
17 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
18 #include "base/threading/thread_checker.h" | 17 #include "base/threading/thread_checker.h" |
19 #include "platform/scheduler/base/enqueue_order.h" | 18 #include "platform/scheduler/base/enqueue_order.h" |
20 #include "platform/scheduler/base/moveable_auto_lock.h" | |
21 #include "platform/scheduler/base/task_queue_impl.h" | 19 #include "platform/scheduler/base/task_queue_impl.h" |
22 #include "platform/scheduler/base/task_queue_selector.h" | 20 #include "platform/scheduler/base/task_queue_selector.h" |
23 | 21 |
24 namespace base { | 22 namespace base { |
25 namespace trace_event { | 23 namespace trace_event { |
26 class ConvertableToTraceFormat; | 24 class ConvertableToTraceFormat; |
27 } // namespace trace_event | 25 } // namespace trace_event |
28 } // namespace base | 26 } // namespace base |
29 | 27 |
30 namespace blink { | 28 namespace blink { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 DCHECK(main_thread_checker_.CalledOnValidThread()); | 133 DCHECK(main_thread_checker_.CalledOnValidThread()); |
136 return currently_executing_task_queue_; | 134 return currently_executing_task_queue_; |
137 } | 135 } |
138 | 136 |
139 // Return number of pending tasks in task queues. | 137 // Return number of pending tasks in task queues. |
140 size_t GetNumberOfPendingTasks() const; | 138 size_t GetNumberOfPendingTasks() const; |
141 | 139 |
142 // Returns true if there is a task that could be executed immediately. | 140 // Returns true if there is a task that could be executed immediately. |
143 bool HasImmediateWorkForTesting() const; | 141 bool HasImmediateWorkForTesting() const; |
144 | 142 |
145 // There is a small overhead to recording task delay histograms. If you don't | |
146 // need them, you can turn them off. | |
147 void SetRecordTaskDelayHistograms(bool record_task_delay_histograms); | |
148 | |
149 private: | 143 private: |
150 friend class LazyNow; | 144 friend class LazyNow; |
151 friend class internal::TaskQueueImpl; | 145 friend class internal::TaskQueueImpl; |
152 friend class TaskQueueManagerTest; | 146 friend class TaskQueueManagerTest; |
153 | 147 |
154 class DeletionSentinel : public base::RefCounted<DeletionSentinel> { | 148 class DeletionSentinel : public base::RefCounted<DeletionSentinel> { |
155 private: | 149 private: |
156 friend class base::RefCounted<DeletionSentinel>; | 150 friend class base::RefCounted<DeletionSentinel>; |
157 ~DeletionSentinel() {} | 151 ~DeletionSentinel() {} |
158 }; | 152 }; |
159 | 153 |
160 // Unregisters a TaskQueue previously created by |NewTaskQueue()|. | 154 // Unregisters a TaskQueue previously created by |NewTaskQueue()|. |
| 155 // NOTE we have to flush the queue from |newly_updatable_| which means as a |
| 156 // side effect MoveNewlyUpdatableQueuesIntoUpdatableQueueSet is called by this |
| 157 // function. |
161 void UnregisterTaskQueue(scoped_refptr<internal::TaskQueueImpl> task_queue); | 158 void UnregisterTaskQueue(scoped_refptr<internal::TaskQueueImpl> task_queue); |
162 | 159 |
163 // TaskQueueSelector::Observer implementation: | 160 // TaskQueueSelector::Observer implementation: |
164 void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) override; | 161 void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) override; |
165 void OnTriedToSelectBlockedWorkQueue( | 162 void OnTriedToSelectBlockedWorkQueue( |
166 internal::WorkQueue* work_queue) override; | 163 internal::WorkQueue* work_queue) override; |
167 | 164 |
168 // base::MessageLoop::NestingObserver implementation: | 165 // base::MessageLoop::NestingObserver implementation: |
169 void OnBeginNestedMessageLoop() override; | 166 void OnBeginNestedMessageLoop() override; |
170 | 167 |
171 // Called by the task queue to register a new pending task. | 168 // Called by the task queue to register a new pending task. |
172 void DidQueueTask(const internal::TaskQueueImpl::Task& pending_task); | 169 void DidQueueTask(const internal::TaskQueueImpl::Task& pending_task); |
173 | 170 |
174 // Use the selector to choose a pending task and run it. | 171 // Use the selector to choose a pending task and run it. |
175 void DoWork(bool delayed); | 172 void DoWork(base::TimeTicks run_time, bool from_main_thread); |
176 | |
177 // Post a DoWork continuation if |next_delay| is not empty. | |
178 void PostDoWorkContinuationLocked(base::Optional<base::TimeDelta> next_delay, | |
179 LazyNow* lazy_now, | |
180 MoveableAutoLock&& lock); | |
181 | 173 |
182 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and | 174 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and |
183 // reloads any empty work queues. | 175 // reloads any empty work queues. |
184 void UpdateWorkQueues( | 176 void UpdateWorkQueues(LazyNow lazy_now); |
185 const std::set<internal::TaskQueueImpl*>* queues_to_reload, | |
186 LazyNow* lazy_now); | |
187 | 177 |
188 // Chooses the next work queue to service. Returns true if |out_queue| | 178 // Chooses the next work queue to service. Returns true if |out_queue| |
189 // indicates the queue from which the next task should be run, false to | 179 // indicates the queue from which the next task should be run, false to |
190 // avoid running any tasks. | 180 // avoid running any tasks. |
191 bool SelectWorkQueueToService(internal::WorkQueue** out_work_queue); | 181 bool SelectWorkQueueToService(internal::WorkQueue** out_work_queue); |
192 | 182 |
193 // Runs a single nestable task from the |queue|. On exit, |out_task| will | 183 // Runs a single nestable task from the |queue|. On exit, |out_task| will |
194 // contain the task which was executed. Non-nestable task are reposted on the | 184 // contain the task which was executed. Non-nestable task are reposted on the |
195 // run loop. The queue must not be empty. | 185 // run loop. The queue must not be empty. |
196 enum class ProcessTaskResult { | 186 enum class ProcessTaskResult { |
197 DEFERRED, | 187 DEFERRED, |
198 EXECUTED, | 188 EXECUTED, |
199 TASK_QUEUE_MANAGER_DELETED | 189 TASK_QUEUE_MANAGER_DELETED |
200 }; | 190 }; |
201 ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue, | 191 ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue, |
202 bool is_nested, | 192 LazyNow*); |
203 LazyNow* lazy_now); | |
204 | 193 |
205 bool RunsTasksOnCurrentThread() const; | 194 bool RunsTasksOnCurrentThread() const; |
206 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 195 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
207 const base::Closure& task, | 196 const base::Closure& task, |
208 base::TimeDelta delay); | 197 base::TimeDelta delay); |
209 | 198 |
210 internal::EnqueueOrder GetNextSequenceNumber(); | 199 internal::EnqueueOrder GetNextSequenceNumber(); |
211 | 200 |
212 // Calls DelayTillNextTask on all time domains and returns the smallest delay | 201 // Calls MaybeAdvanceTime on all time domains and returns true if one of them |
213 // requested if any. | 202 // was able to advance. |
214 base::Optional<base::TimeDelta> ComputeDelayTillNextTaskLocked( | 203 bool TryAdvanceTimeDomains(); |
215 LazyNow* lazy_now); | |
216 | 204 |
217 void MaybeRecordTaskDelayHistograms( | 205 void MaybeRecordTaskDelayHistograms( |
218 const internal::TaskQueueImpl::Task& pending_task, | 206 const internal::TaskQueueImpl::Task& pending_task, |
219 const internal::TaskQueueImpl* queue); | 207 const internal::TaskQueueImpl* queue); |
220 | 208 |
221 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> | 209 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> |
222 AsValueWithSelectorResult(bool should_run, | 210 AsValueWithSelectorResult(bool should_run, |
223 internal::WorkQueue* selected_work_queue) const; | 211 internal::WorkQueue* selected_work_queue) const; |
224 | 212 |
225 void MaybeScheduleImmediateWorkLocked( | |
226 const tracked_objects::Location& from_here, | |
227 MoveableAutoLock&& lock); | |
228 | |
229 // Adds |queue| to |has_incoming_immediate_work_| and if | |
230 // |ensure_do_work_posted| is true it calls MaybeScheduleImmediateWorkLocked. | |
231 void OnQueueHasImmediateWork(internal::TaskQueueImpl* queue, | |
232 bool ensure_do_work_posted); | |
233 | |
234 std::set<TimeDomain*> time_domains_; | 213 std::set<TimeDomain*> time_domains_; |
235 std::unique_ptr<RealTimeDomain> real_time_domain_; | 214 std::unique_ptr<RealTimeDomain> real_time_domain_; |
236 | 215 |
237 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; | 216 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; |
238 | 217 |
239 // We have to be careful when deleting a queue because some of the code uses | 218 // We have to be careful when deleting a queue because some of the code uses |
240 // raw pointers and doesn't expect the rug to be pulled out from underneath. | 219 // raw pointers and doesn't expect the rug to be pulled out from underneath. |
241 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; | 220 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; |
242 | 221 |
243 internal::EnqueueOrderGenerator enqueue_order_generator_; | 222 internal::EnqueueOrderGenerator enqueue_order_generator_; |
244 base::debug::TaskAnnotator task_annotator_; | 223 base::debug::TaskAnnotator task_annotator_; |
245 | 224 |
246 base::ThreadChecker main_thread_checker_; | 225 base::ThreadChecker main_thread_checker_; |
247 scoped_refptr<TaskQueueManagerDelegate> delegate_; | 226 scoped_refptr<TaskQueueManagerDelegate> delegate_; |
248 internal::TaskQueueSelector selector_; | 227 internal::TaskQueueSelector selector_; |
249 | 228 |
250 base::Closure immediate_do_work_closure_; | 229 base::Closure from_main_thread_immediate_do_work_closure_; |
251 base::Closure delayed_do_work_closure_; | 230 base::Closure from_other_thread_immediate_do_work_closure_; |
252 | 231 |
253 bool task_was_run_on_quiescence_monitored_queue_; | 232 bool task_was_run_on_quiescence_monitored_queue_; |
254 | 233 |
255 struct AnyThread { | 234 // To reduce locking overhead we track pending calls to DoWork separately for |
256 AnyThread(); | 235 // the main thread and other threads. |
| 236 std::set<base::TimeTicks> main_thread_pending_wakeups_; |
257 | 237 |
258 int do_work_running_count; | 238 // Protects |other_thread_pending_wakeup_|. |
259 int immediate_do_work_posted_count; | 239 mutable base::Lock other_thread_lock_; |
260 std::set<internal::TaskQueueImpl*> has_incoming_immediate_work; | 240 bool other_thread_pending_wakeup_; |
261 bool is_nested; // Whether or not the message loop is currently nested. | |
262 }; | |
263 | |
264 mutable base::Lock any_thread_lock_; | |
265 AnyThread any_thread_; | |
266 struct AnyThread& any_thread() { | |
267 any_thread_lock_.AssertAcquired(); | |
268 return any_thread_; | |
269 } | |
270 const struct AnyThread& any_thread() const { | |
271 any_thread_lock_.AssertAcquired(); | |
272 return any_thread_; | |
273 } | |
274 | |
275 bool record_task_delay_histograms_; | |
276 | |
277 base::TimeTicks next_delayed_do_work_; | |
278 base::CancelableClosure cancelable_delayed_do_work_closure_; | |
279 | 241 |
280 int work_batch_size_; | 242 int work_batch_size_; |
281 size_t task_count_; | 243 size_t task_count_; |
282 | 244 |
283 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; | 245 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; |
284 | 246 |
285 base::ObserverList<TaskTimeObserver> task_time_observers_; | 247 base::ObserverList<TaskTimeObserver> task_time_observers_; |
286 | 248 |
287 const char* tracing_category_; | 249 const char* tracing_category_; |
288 const char* disabled_by_default_tracing_category_; | 250 const char* disabled_by_default_tracing_category_; |
289 const char* disabled_by_default_verbose_tracing_category_; | 251 const char* disabled_by_default_verbose_tracing_category_; |
290 | 252 |
291 internal::TaskQueueImpl* currently_executing_task_queue_; // NOT OWNED | 253 internal::TaskQueueImpl* currently_executing_task_queue_; // NOT OWNED |
292 | 254 |
293 Observer* observer_; // NOT OWNED | 255 Observer* observer_; // NOT OWNED |
294 scoped_refptr<DeletionSentinel> deletion_sentinel_; | 256 scoped_refptr<DeletionSentinel> deletion_sentinel_; |
295 base::WeakPtrFactory<TaskQueueManager> weak_factory_; | 257 base::WeakPtrFactory<TaskQueueManager> weak_factory_; |
296 | 258 |
297 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); | 259 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); |
298 }; | 260 }; |
299 | 261 |
300 } // namespace scheduler | 262 } // namespace scheduler |
301 } // namespace blink | 263 } // namespace blink |
302 | 264 |
303 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_
H_ | 265 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_
H_ |
OLD | NEW |