Chromium Code Reviews| 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. | |
| 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); |
| 176 | |
| 177 // Post a DoWork continuation if |next_delay| is not empty. | |
| 178 void PostDoWorkContinuation(base::Optional<base::TimeDelta> next_delay, | |
| 179 LazyNow* lazy_now); | |
| 173 | 180 |
| 174 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and | 181 // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and |
| 175 // reloads any empty work queues. | 182 // reloads any empty work queues. |
| 176 void UpdateWorkQueues(LazyNow lazy_now); | 183 void UpdateWorkQueues(LazyNow* lazy_now); |
| 177 | 184 |
| 178 // Chooses the next work queue to service. Returns true if |out_queue| | 185 // 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 | 186 // indicates the queue from which the next task should be run, false to |
| 180 // avoid running any tasks. | 187 // avoid running any tasks. |
| 181 bool SelectWorkQueueToService(internal::WorkQueue** out_work_queue); | 188 bool SelectWorkQueueToService(internal::WorkQueue** out_work_queue); |
| 182 | 189 |
| 183 // Runs a single nestable task from the |queue|. On exit, |out_task| will | 190 // 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 | 191 // contain the task which was executed. Non-nestable task are reposted on the |
| 185 // run loop. The queue must not be empty. | 192 // run loop. The queue must not be empty. |
| 186 enum class ProcessTaskResult { | 193 enum class ProcessTaskResult { |
| 187 DEFERRED, | 194 DEFERRED, |
| 188 EXECUTED, | 195 EXECUTED, |
| 189 TASK_QUEUE_MANAGER_DELETED | 196 TASK_QUEUE_MANAGER_DELETED |
| 190 }; | 197 }; |
| 191 ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue, | 198 ProcessTaskResult ProcessTaskFromWorkQueue(internal::WorkQueue* work_queue, |
| 192 LazyNow*); | 199 LazyNow*); |
| 193 | 200 |
| 194 bool RunsTasksOnCurrentThread() const; | 201 bool RunsTasksOnCurrentThread() const; |
| 195 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 202 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| 196 const base::Closure& task, | 203 const base::Closure& task, |
| 197 base::TimeDelta delay); | 204 base::TimeDelta delay); |
| 198 | 205 |
| 199 internal::EnqueueOrder GetNextSequenceNumber(); | 206 internal::EnqueueOrder GetNextSequenceNumber(); |
| 200 | 207 |
| 201 // Calls MaybeAdvanceTime on all time domains and returns true if one of them | 208 // Calls DelayTillNextTask on all time domains and returns the smallest delay |
| 202 // was able to advance. | 209 // requested if any. |
| 203 bool TryAdvanceTimeDomains(); | 210 base::Optional<base::TimeDelta> DelayTillNextTask(LazyNow* lazy_now); |
| 204 | 211 |
| 205 void MaybeRecordTaskDelayHistograms( | 212 void MaybeRecordTaskDelayHistograms( |
| 206 const internal::TaskQueueImpl::Task& pending_task, | 213 const internal::TaskQueueImpl::Task& pending_task, |
| 207 const internal::TaskQueueImpl* queue); | 214 const internal::TaskQueueImpl* queue); |
| 208 | 215 |
| 209 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> | 216 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> |
| 210 AsValueWithSelectorResult(bool should_run, | 217 AsValueWithSelectorResult(bool should_run, |
| 211 internal::WorkQueue* selected_work_queue) const; | 218 internal::WorkQueue* selected_work_queue) const; |
| 212 | 219 |
| 220 void MaybeScheduleImmediateWorkLocked( | |
| 221 const tracked_objects::Location& from_here); | |
| 222 | |
| 223 void MaybeScheduleDelayedWorkInternal( | |
| 224 const tracked_objects::Location& from_here, | |
| 225 base::TimeTicks now, | |
| 226 base::TimeDelta delay); | |
| 227 | |
| 228 // Adds |queue| to |has_incomming_immediate_work_| and if | |
| 229 // |ensure_do_work_posted| is true it calls MaybeScheduleImmediateWorkLocked. | |
| 230 void OnQueueHasImmediateWork(internal::TaskQueueImpl* queue, | |
| 231 bool ensure_do_work_posted); | |
| 232 | |
| 233 void NotifyQueuesOfIncomingImmediateWorkOnMainThreadLocked(); | |
| 234 | |
| 213 std::set<TimeDomain*> time_domains_; | 235 std::set<TimeDomain*> time_domains_; |
| 214 std::unique_ptr<RealTimeDomain> real_time_domain_; | 236 std::unique_ptr<RealTimeDomain> real_time_domain_; |
| 215 | 237 |
| 216 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; | 238 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_; |
| 217 | 239 |
| 218 // We have to be careful when deleting a queue because some of the code uses | 240 // We have to be careful when deleting a queue because some of the code uses |
| 219 // raw pointers and doesn't expect the rug to be pulled out from underneath. | 241 // raw pointers and doesn't expect the rug to be pulled out from underneath. |
| 220 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; | 242 std::set<scoped_refptr<internal::TaskQueueImpl>> queues_to_delete_; |
| 221 | 243 |
| 222 internal::EnqueueOrderGenerator enqueue_order_generator_; | 244 internal::EnqueueOrderGenerator enqueue_order_generator_; |
| 223 base::debug::TaskAnnotator task_annotator_; | 245 base::debug::TaskAnnotator task_annotator_; |
| 224 | 246 |
| 225 base::ThreadChecker main_thread_checker_; | 247 base::ThreadChecker main_thread_checker_; |
| 226 scoped_refptr<TaskQueueManagerDelegate> delegate_; | 248 scoped_refptr<TaskQueueManagerDelegate> delegate_; |
| 227 internal::TaskQueueSelector selector_; | 249 internal::TaskQueueSelector selector_; |
| 228 | 250 |
| 229 base::Closure from_main_thread_immediate_do_work_closure_; | 251 base::Closure immediate_do_work_closure_; |
| 230 base::Closure from_other_thread_immediate_do_work_closure_; | 252 base::Closure delayed_do_work_closure_; |
| 231 | 253 |
| 232 bool task_was_run_on_quiescence_monitored_queue_; | 254 bool task_was_run_on_quiescence_monitored_queue_; |
| 233 | 255 |
| 234 // To reduce locking overhead we track pending calls to DoWork separately for | 256 // Protects |do_work_running_count_|, |immediate_do_work_posted_count_|, |
| 235 // the main thread and other threads. | 257 // |is_nested_| and |has_incomming_immediate_work_|. |
| 236 std::set<base::TimeTicks> main_thread_pending_wakeups_; | 258 mutable WTF::SpinLock do_work_pending_lock_; |
|
Sami
2016/12/07 16:13:42
nit: I think this could just be base::subtle::Spin
alex clarke (OOO till 29th)
2016/12/08 17:38:49
I'm actually thinking we should initially use a mu
| |
| 259 int do_work_running_count_; | |
|
Sami
2016/12/07 16:13:43
Should we wrap these into a struct like we do in t
alex clarke (OOO till 29th)
2016/12/08 17:38:48
Good idea. Done.
| |
| 260 int immediate_do_work_posted_count_; | |
| 261 std::set<internal::TaskQueueImpl*> has_incomming_immediate_work_; | |
|
Sami
2016/12/07 16:13:43
typo: incoming
alex clarke (OOO till 29th)
2016/12/08 17:38:48
Done.
| |
| 262 bool is_nested_; // Whether or not the message loop is currently nested. | |
| 237 | 263 |
| 238 // Protects |other_thread_pending_wakeup_|. | 264 bool record_task_delay_histograms_; |
| 239 mutable base::Lock other_thread_lock_; | 265 |
| 240 bool other_thread_pending_wakeup_; | 266 base::TimeTicks next_delayed_do_work_; |
| 267 base::CancelableClosure cancelable_delayed_do_work_closure_; | |
| 241 | 268 |
| 242 int work_batch_size_; | 269 int work_batch_size_; |
| 243 size_t task_count_; | 270 size_t task_count_; |
| 244 | 271 |
| 245 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; | 272 base::ObserverList<base::MessageLoop::TaskObserver> task_observers_; |
| 246 | 273 |
| 247 base::ObserverList<TaskTimeObserver> task_time_observers_; | 274 base::ObserverList<TaskTimeObserver> task_time_observers_; |
| 248 | 275 |
| 249 const char* tracing_category_; | 276 const char* tracing_category_; |
| 250 const char* disabled_by_default_tracing_category_; | 277 const char* disabled_by_default_tracing_category_; |
| 251 const char* disabled_by_default_verbose_tracing_category_; | 278 const char* disabled_by_default_verbose_tracing_category_; |
| 252 | 279 |
| 253 internal::TaskQueueImpl* currently_executing_task_queue_; // NOT OWNED | 280 internal::TaskQueueImpl* currently_executing_task_queue_; // NOT OWNED |
| 254 | 281 |
| 255 Observer* observer_; // NOT OWNED | 282 Observer* observer_; // NOT OWNED |
| 256 scoped_refptr<DeletionSentinel> deletion_sentinel_; | 283 scoped_refptr<DeletionSentinel> deletion_sentinel_; |
| 257 base::WeakPtrFactory<TaskQueueManager> weak_factory_; | 284 base::WeakPtrFactory<TaskQueueManager> weak_factory_; |
| 258 | 285 |
| 259 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); | 286 DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); |
| 260 }; | 287 }; |
| 261 | 288 |
| 262 } // namespace scheduler | 289 } // namespace scheduler |
| 263 } // namespace blink | 290 } // namespace blink |
| 264 | 291 |
| 265 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_ H_ | 292 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_ H_ |
| OLD | NEW |