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" |
19 #include "platform/scheduler/base/task_queue_impl.h" | 20 #include "platform/scheduler/base/task_queue_impl.h" |
20 #include "platform/scheduler/base/task_queue_selector.h" | 21 #include "platform/scheduler/base/task_queue_selector.h" |
22 #include "wtf/SpinLock.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 { |
29 namespace scheduler { | 31 namespace scheduler { |
30 namespace internal { | 32 namespace internal { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
133 DCHECK(main_thread_checker_.CalledOnValidThread()); | 135 DCHECK(main_thread_checker_.CalledOnValidThread()); |
134 return currently_executing_task_queue_; | 136 return currently_executing_task_queue_; |
135 } | 137 } |
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 |
145 // There is a small overhead to recording task delay histograms. If you don't | |
146 // need them, you can turn them off. | |
Sami
2016/12/05 17:52:54
Or we could consider deleting them :) (Don't recal
alex clarke (OOO till 29th)
2016/12/06 17:37:54
Lets make that decision in a different patch?
Sami
2016/12/07 16:13:42
Sure, no problem.
| |
147 void SetRecordTaskDelayHistograms(bool record_task_delay_histograms); | |
148 | |
143 private: | 149 private: |
144 friend class LazyNow; | 150 friend class LazyNow; |
145 friend class internal::TaskQueueImpl; | 151 friend class internal::TaskQueueImpl; |
146 friend class TaskQueueManagerTest; | 152 friend class TaskQueueManagerTest; |
147 | 153 |
148 class DeletionSentinel : public base::RefCounted<DeletionSentinel> { | 154 class DeletionSentinel : public base::RefCounted<DeletionSentinel> { |
149 private: | 155 private: |
150 friend class base::RefCounted<DeletionSentinel>; | 156 friend class base::RefCounted<DeletionSentinel>; |
151 ~DeletionSentinel() {} | 157 ~DeletionSentinel() {} |
152 }; | 158 }; |
153 | 159 |
154 // Unregisters a TaskQueue previously created by |NewTaskQueue()|. | 160 // 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. | |
158 void UnregisterTaskQueue(scoped_refptr<internal::TaskQueueImpl> task_queue); | 161 void UnregisterTaskQueue(scoped_refptr<internal::TaskQueueImpl> task_queue); |
159 | 162 |
160 // TaskQueueSelector::Observer implementation: | 163 // TaskQueueSelector::Observer implementation: |
161 void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) override; | 164 void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) override; |
162 void OnTriedToSelectBlockedWorkQueue( | 165 void OnTriedToSelectBlockedWorkQueue( |
163 internal::WorkQueue* work_queue) override; | 166 internal::WorkQueue* work_queue) override; |
164 | 167 |
165 // base::MessageLoop::NestingObserver implementation: | 168 // base::MessageLoop::NestingObserver implementation: |
166 void OnBeginNestedMessageLoop() override; | 169 void OnBeginNestedMessageLoop() override; |
167 | 170 |
168 // Called by the task queue to register a new pending task. | 171 // Called by the task queue to register a new pending task. |
169 void DidQueueTask(const internal::TaskQueueImpl::Task& pending_task); | 172 void DidQueueTask(const internal::TaskQueueImpl::Task& pending_task); |
170 | 173 |
171 // Use the selector to choose a pending task and run it. | 174 // Use the selector to choose a pending task and run it. |
172 void DoWork(base::TimeTicks run_time, bool from_main_thread); | 175 void DoWork(bool delayed); |
173 | 176 |
174 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and | 177 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and |
175 // reloads any empty work queues. | 178 // reloads any empty work queues. |
176 void UpdateWorkQueues(LazyNow lazy_now); | 179 void UpdateWorkQueues(LazyNow* lazy_now); |
177 | 180 |
178 // Chooses the next work queue to service. Returns true if |out_queue| | 181 // Chooses the next work queue to service. Returns true if |out_queue| |
179 // indicates the queue from which the next task should be run, false to | 182 // indicates the queue from which the next task should be run, false to |
180 // avoid running any tasks. | 183 // avoid running any tasks. |
181 bool SelectWorkQueueToService(internal::WorkQueue** out_work_queue); | 184 bool SelectWorkQueueToService(internal::WorkQueue** out_work_queue); |
182 | 185 |
183 // Runs a single nestable task from the |queue|. On exit, |out_task| will | 186 // Runs a single nestable task from the |queue|. On exit, |out_task| will |
184 // contain the task which was executed. Non-nestable task are reposted on the | 187 // contain the task which was executed. Non-nestable task are reposted on the |
185 // run loop. The queue must not be empty. | 188 // run loop. The queue must not be empty. |
186 enum class ProcessTaskResult { | 189 enum class ProcessTaskResult { |
187 DEFERRED, | 190 DEFERRED, |
188 EXECUTED, | 191 EXECUTED, |
189 TASK_QUEUE_MANAGER_DELETED | 192 TASK_QUEUE_MANAGER_DELETED |
190 }; | 193 }; |
191 ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue); | 194 ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue); |
192 | 195 |
193 bool RunsTasksOnCurrentThread() const; | 196 bool RunsTasksOnCurrentThread() const; |
194 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 197 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
195 const base::Closure& task, | 198 const base::Closure& task, |
196 base::TimeDelta delay); | 199 base::TimeDelta delay); |
197 | 200 |
198 internal::EnqueueOrder GetNextSequenceNumber(); | 201 internal::EnqueueOrder GetNextSequenceNumber(); |
199 | 202 |
200 // Calls MaybeAdvanceTime on all time domains and returns true if one of them | 203 // Calls DelayTillNextTask on all time domains and returns the smallest delay |
201 // was able to advance. | 204 // requested if any. |
202 bool TryAdvanceTimeDomains(); | 205 base::Optional<base::TimeDelta> DelayTillNextTask(LazyNow* lazy_now); |
203 | 206 |
204 void MaybeRecordTaskDelayHistograms( | 207 void MaybeRecordTaskDelayHistograms( |
205 const internal::TaskQueueImpl::Task& pending_task, | 208 const internal::TaskQueueImpl::Task& pending_task, |
206 const internal::TaskQueueImpl* queue); | 209 const internal::TaskQueueImpl* queue); |
207 | 210 |
208 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> | 211 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> |
209 AsValueWithSelectorResult(bool should_run, | 212 AsValueWithSelectorResult(bool should_run, |
210 internal::WorkQueue* selected_work_queue) const; | 213 internal::WorkQueue* selected_work_queue) const; |
211 | 214 |
215 void MaybeScheduleImmediateWorkLocked( | |
216 const tracked_objects::Location& from_here); | |
217 | |
218 void MaybeScheduleDelayedWorkInternal( | |
219 const tracked_objects::Location& from_here, | |
220 base::TimeTicks now, | |
221 base::TimeDelta delay); | |
222 | |
223 void OnQueueHasImmediateWork(internal::TaskQueueImpl* queue); | |
224 void NotifyQueuesOfIncomingImmediateWorkOnMainThreadLocked(); | |
225 | |
212 std::set<TimeDomain*> time_domains_; | 226 std::set<TimeDomain*> time_domains_; |
213 std::unique_ptr<RealTimeDomain> real_time_domain_; | 227 std::unique_ptr<RealTimeDomain> real_time_domain_; |
214 | 228 |
215 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; | 229 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; |
216 | 230 |
217 // We have to be careful when deleting a queue because some of the code uses | 231 // We have to be careful when deleting a queue because some of the code uses |
218 // raw pointers and doesn't expect the rug to be pulled out from underneath. | 232 // raw pointers and doesn't expect the rug to be pulled out from underneath. |
219 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; | 233 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; |
220 | 234 |
221 internal::EnqueueOrderGenerator enqueue_order_generator_; | 235 internal::EnqueueOrderGenerator enqueue_order_generator_; |
222 base::debug::TaskAnnotator task_annotator_; | 236 base::debug::TaskAnnotator task_annotator_; |
223 | 237 |
224 base::ThreadChecker main_thread_checker_; | 238 base::ThreadChecker main_thread_checker_; |
225 scoped_refptr<TaskQueueManagerDelegate> delegate_; | 239 scoped_refptr<TaskQueueManagerDelegate> delegate_; |
226 internal::TaskQueueSelector selector_; | 240 internal::TaskQueueSelector selector_; |
227 | 241 |
228 base::Closure from_main_thread_immediate_do_work_closure_; | 242 base::Closure immediate_do_work_closure_; |
229 base::Closure from_other_thread_immediate_do_work_closure_; | 243 base::Closure delayed_do_work_closure_; |
230 | 244 |
231 bool task_was_run_on_quiescence_monitored_queue_; | 245 bool task_was_run_on_quiescence_monitored_queue_; |
232 | 246 |
233 // To reduce locking overhead we track pending calls to DoWork separately for | 247 // Protects |do_work_running_count_|, |immediate_do_work_posted_count_|, |
234 // the main thread and other threads. | 248 // |is_nested_| and |has_incomming_immediate_work_|. |
235 std::set<base::TimeTicks> main_thread_pending_wakeups_; | 249 mutable WTF::SpinLock do_work_pending_lock_; |
250 int do_work_running_count_; | |
251 int immediate_do_work_posted_count_; | |
252 std::set<internal::TaskQueueImpl*> has_incomming_immediate_work_; | |
Sami
2016/12/05 17:52:55
Does this need to be ordered by the way?
alex clarke (OOO till 29th)
2016/12/06 17:37:54
No. I expect this to be mostly empty, it would be
| |
253 bool is_nested_; // Whether or not the message loop is currently nested. | |
236 | 254 |
237 // Protects |other_thread_pending_wakeup_|. | 255 bool record_task_delay_histograms_; |
238 mutable base::Lock other_thread_lock_; | 256 |
239 bool other_thread_pending_wakeup_; | 257 base::TimeTicks next_delayed_do_work_; |
258 base::CancelableClosure cancelable_delayed_do_work_closure_; | |
240 | 259 |
241 int work_batch_size_; | 260 int work_batch_size_; |
242 size_t task_count_; | 261 size_t task_count_; |
243 | 262 |
244 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; | 263 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; |
245 | 264 |
246 base::ObserverList<TaskTimeObserver> task_time_observers_; | 265 base::ObserverList<TaskTimeObserver> task_time_observers_; |
247 | 266 |
248 const char* tracing_category_; | 267 const char* tracing_category_; |
249 const char* disabled_by_default_tracing_category_; | 268 const char* disabled_by_default_tracing_category_; |
250 const char* disabled_by_default_verbose_tracing_category_; | 269 const char* disabled_by_default_verbose_tracing_category_; |
251 | 270 |
252 internal::TaskQueueImpl* currently_executing_task_queue_; // NOT OWNED | 271 internal::TaskQueueImpl* currently_executing_task_queue_; // NOT OWNED |
253 | 272 |
254 Observer* observer_; // NOT OWNED | 273 Observer* observer_; // NOT OWNED |
255 scoped_refptr<DeletionSentinel> deletion_sentinel_; | 274 scoped_refptr<DeletionSentinel> deletion_sentinel_; |
256 base::WeakPtrFactory<TaskQueueManager> weak_factory_; | 275 base::WeakPtrFactory<TaskQueueManager> weak_factory_; |
257 | 276 |
258 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); | 277 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); |
259 }; | 278 }; |
260 | 279 |
261 } // namespace scheduler | 280 } // namespace scheduler |
262 } // namespace blink | 281 } // namespace blink |
263 | 282 |
264 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_ H_ | 283 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_ H_ |
OLD | NEW |