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