OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_IMPL_H_ | 5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ |
6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ | 6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
(...skipping 28 matching lines...) Expand all Loading... |
39 // | 39 // |
40 // Delayed tasks | 40 // Delayed tasks |
41 // delayed_incoming_queue - PostDelayedTask enqueues tasks here | 41 // delayed_incoming_queue - PostDelayedTask enqueues tasks here |
42 // delayed_work_queue | 42 // delayed_work_queue |
43 // | 43 // |
44 // The immediate_incoming_queue can be accessed from any thread, the other | 44 // The immediate_incoming_queue can be accessed from any thread, the other |
45 // queues are main-thread only. To reduce the overhead of locking, | 45 // queues are main-thread only. To reduce the overhead of locking, |
46 // immediate_work_queue is swapped with immediate_incoming_queue when | 46 // immediate_work_queue is swapped with immediate_incoming_queue when |
47 // immediate_work_queue becomes empty. | 47 // immediate_work_queue becomes empty. |
48 // | 48 // |
49 // Delayed tasks are initially posted to delayed_incoming_queue and a wake-up | 49 // Delayed tasks are initially posted to delayed_incoming_queue and a wakeup |
50 // is scheduled with the TimeDomain. When the delay has elapsed, the TimeDomain | 50 // is scheduled with the TimeDomain. When the delay has elapsed, the TimeDomain |
51 // calls UpdateDelayedWorkQueue and ready delayed tasks are moved into the | 51 // calls UpdateDelayedWorkQueue and ready delayed tasks are moved into the |
52 // delayed_work_queue. Note the EnqueueOrder (used for ordering) for a delayed | 52 // delayed_work_queue. Note the EnqueueOrder (used for ordering) for a delayed |
53 // task is not set until it's moved into the delayed_work_queue. | 53 // task is not set until it's moved into the delayed_work_queue. |
54 // | 54 // |
55 // TaskQueueImpl uses the WorkQueueSets and the TaskQueueSelector to implement | 55 // TaskQueueImpl uses the WorkQueueSets and the TaskQueueSelector to implement |
56 // prioritization. Task selection is done by the TaskQueueSelector and when a | 56 // prioritization. Task selection is done by the TaskQueueSelector and when a |
57 // queue is selected, it round-robins between the immediate_work_queue and | 57 // queue is selected, it round-robins between the immediate_work_queue and |
58 // delayed_work_queue. The reason for this is we want to make sure delayed | 58 // delayed_work_queue. The reason for this is we want to make sure delayed |
59 // tasks (normally the most common type) don't starve out immediate work. | 59 // tasks (normally the most common type) don't starve out immediate work. |
60 class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue { | 60 class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue { |
61 public: | 61 public: |
62 TaskQueueImpl(TaskQueueManager* task_queue_manager, | 62 TaskQueueImpl(TaskQueueManager* task_queue_manager, |
63 TimeDomain* time_domain, | 63 TimeDomain* time_domain, |
64 const Spec& spec, | 64 const Spec& spec, |
65 const char* disabled_by_default_tracing_category, | 65 const char* disabled_by_default_tracing_category, |
66 const char* disabled_by_default_verbose_tracing_category); | 66 const char* disabled_by_default_verbose_tracing_category); |
67 | 67 |
68 // Represents a time at which a task wants to run. Tasks scheduled for the | |
69 // same point in time will be ordered by their sequence numbers. | |
70 struct DelayedWakeUp { | |
71 base::TimeTicks time; | |
72 int sequence_num; | |
73 | |
74 bool operator<=(const DelayedWakeUp& other) const { | |
75 if (time == other.time) { | |
76 DCHECK_NE(sequence_num, other.sequence_num); | |
77 return (sequence_num - other.sequence_num) < 0; | |
78 } | |
79 return time < other.time; | |
80 } | |
81 }; | |
82 | |
83 class BLINK_PLATFORM_EXPORT Task : public base::PendingTask { | 68 class BLINK_PLATFORM_EXPORT Task : public base::PendingTask { |
84 public: | 69 public: |
85 Task(); | 70 Task(); |
86 Task(const tracked_objects::Location& posted_from, | 71 Task(const tracked_objects::Location& posted_from, |
87 base::OnceClosure task, | 72 base::OnceClosure task, |
88 base::TimeTicks desired_run_time, | 73 base::TimeTicks desired_run_time, |
89 EnqueueOrder sequence_number, | 74 EnqueueOrder sequence_number, |
90 bool nestable); | 75 bool nestable); |
91 | 76 |
92 Task(const tracked_objects::Location& posted_from, | 77 Task(const tracked_objects::Location& posted_from, |
93 base::OnceClosure task, | 78 base::OnceClosure task, |
94 base::TimeTicks desired_run_time, | 79 base::TimeTicks desired_run_time, |
95 EnqueueOrder sequence_number, | 80 EnqueueOrder sequence_number, |
96 bool nestable, | 81 bool nestable, |
97 EnqueueOrder enqueue_order); | 82 EnqueueOrder enqueue_order); |
98 | 83 |
99 DelayedWakeUp delayed_wake_up() const { | |
100 return DelayedWakeUp{delayed_run_time, sequence_num}; | |
101 } | |
102 | |
103 EnqueueOrder enqueue_order() const { | 84 EnqueueOrder enqueue_order() const { |
104 #ifndef NDEBUG | 85 #ifndef NDEBUG |
105 DCHECK(enqueue_order_set_); | 86 DCHECK(enqueue_order_set_); |
106 #endif | 87 #endif |
107 return enqueue_order_; | 88 return enqueue_order_; |
108 } | 89 } |
109 | 90 |
110 void set_enqueue_order(EnqueueOrder enqueue_order) { | 91 void set_enqueue_order(EnqueueOrder enqueue_order) { |
111 #ifndef NDEBUG | 92 #ifndef NDEBUG |
112 DCHECK(!enqueue_order_set_); | 93 DCHECK(!enqueue_order_set_); |
(...skipping 11 matching lines...) Expand all Loading... |
124 bool enqueue_order_set_; | 105 bool enqueue_order_set_; |
125 #endif | 106 #endif |
126 // Similar to sequence number, but ultimately the |enqueue_order_| is what | 107 // Similar to sequence number, but ultimately the |enqueue_order_| is what |
127 // the scheduler uses for task ordering. For immediate tasks |enqueue_order| | 108 // the scheduler uses for task ordering. For immediate tasks |enqueue_order| |
128 // is set when posted, but for delayed tasks it's not defined until they are | 109 // is set when posted, but for delayed tasks it's not defined until they are |
129 // enqueued on the |delayed_work_queue_|. This is because otherwise delayed | 110 // enqueued on the |delayed_work_queue_|. This is because otherwise delayed |
130 // tasks could run before an immediate task posted after the delayed task. | 111 // tasks could run before an immediate task posted after the delayed task. |
131 EnqueueOrder enqueue_order_; | 112 EnqueueOrder enqueue_order_; |
132 }; | 113 }; |
133 | 114 |
| 115 // Represents a time at which a task wants to run. Tasks scheduled for the |
| 116 // same point in time will be ordered by their sequence numbers. |
| 117 struct DelayedWakeUp { |
| 118 base::TimeTicks time; |
| 119 int sequence_num; |
| 120 |
| 121 bool operator<=(const DelayedWakeUp& other) const { |
| 122 if (time == other.time) { |
| 123 DCHECK_NE(sequence_num, other.sequence_num); |
| 124 return (sequence_num - other.sequence_num) < 0; |
| 125 } |
| 126 return time < other.time; |
| 127 } |
| 128 }; |
| 129 |
134 // TaskQueue implementation. | 130 // TaskQueue implementation. |
135 void UnregisterTaskQueue() override; | 131 void UnregisterTaskQueue() override; |
136 bool RunsTasksOnCurrentThread() const override; | 132 bool RunsTasksOnCurrentThread() const override; |
137 bool PostDelayedTask(const tracked_objects::Location& from_here, | 133 bool PostDelayedTask(const tracked_objects::Location& from_here, |
138 base::OnceClosure task, | 134 base::OnceClosure task, |
139 base::TimeDelta delay) override; | 135 base::TimeDelta delay) override; |
140 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 136 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
141 base::OnceClosure task, | 137 base::OnceClosure task, |
142 base::TimeDelta delay) override; | 138 base::TimeDelta delay) override; |
143 std::unique_ptr<QueueEnabledVoter> CreateQueueEnabledVoter() override; | 139 std::unique_ptr<QueueEnabledVoter> CreateQueueEnabledVoter() override; |
144 bool IsQueueEnabled() const override; | 140 bool IsQueueEnabled() const override; |
145 bool IsEmpty() const override; | 141 bool IsEmpty() const override; |
146 size_t GetNumberOfPendingTasks() const override; | 142 size_t GetNumberOfPendingTasks() const override; |
147 bool HasPendingImmediateWork() const override; | 143 bool HasPendingImmediateWork() const override; |
148 base::Optional<base::TimeTicks> GetNextScheduledWakeUp() override; | 144 base::Optional<base::TimeTicks> GetNextScheduledWakeUp() override; |
149 void SetQueuePriority(QueuePriority priority) override; | 145 void SetQueuePriority(QueuePriority priority) override; |
150 QueuePriority GetQueuePriority() const override; | 146 QueuePriority GetQueuePriority() const override; |
151 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override; | 147 void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override; |
152 void RemoveTaskObserver( | 148 void RemoveTaskObserver( |
153 base::MessageLoop::TaskObserver* task_observer) override; | 149 base::MessageLoop::TaskObserver* task_observer) override; |
154 void SetTimeDomain(TimeDomain* time_domain) override; | 150 void SetTimeDomain(TimeDomain* time_domain) override; |
155 TimeDomain* GetTimeDomain() const override; | 151 TimeDomain* GetTimeDomain() const override; |
156 void SetBlameContext(base::trace_event::BlameContext* blame_context) override; | 152 void SetBlameContext(base::trace_event::BlameContext* blame_context) override; |
157 void InsertFence(InsertFencePosition position) override; | 153 void InsertFence(InsertFencePosition position) override; |
158 void RemoveFence() override; | 154 void RemoveFence() override; |
159 bool BlockedByFence() const override; | 155 bool BlockedByFence() const override; |
160 const char* GetName() const override; | 156 const char* GetName() const override; |
161 QueueType GetQueueType() const override; | 157 QueueType GetQueueType() const override; |
162 void SetObserver(Observer* observer) override; | |
163 | 158 |
164 // Returns true if a (potentially hypothetical) task with the specified | 159 // Returns true if a (potentially hypothetical) task with the specified |
165 // |enqueue_order| could run on the queue. Must be called from the main | 160 // |enqueue_order| could run on the queue. Must be called from the main |
166 // thread. | 161 // thread. |
167 bool CouldTaskRun(EnqueueOrder enqueue_order) const; | 162 bool CouldTaskRun(EnqueueOrder enqueue_order) const; |
168 | 163 |
169 // Must only be called from the thread this task queue was created on. | 164 // Must only be called from the thread this task queue was created on. |
170 void ReloadImmediateWorkQueueIfEmpty(); | 165 void ReloadImmediateWorkQueueIfEmpty(); |
171 | 166 |
172 void AsValueInto(base::trace_event::TracedValue* state) const; | 167 void AsValueInto(base::trace_event::TracedValue* state) const; |
(...skipping 18 matching lines...) Expand all Loading... |
191 | 186 |
192 const WorkQueue* immediate_work_queue() const { | 187 const WorkQueue* immediate_work_queue() const { |
193 return main_thread_only().immediate_work_queue.get(); | 188 return main_thread_only().immediate_work_queue.get(); |
194 } | 189 } |
195 | 190 |
196 bool should_report_when_execution_blocked() const { | 191 bool should_report_when_execution_blocked() const { |
197 return should_report_when_execution_blocked_; | 192 return should_report_when_execution_blocked_; |
198 } | 193 } |
199 | 194 |
200 // Enqueues any delayed tasks which should be run now on the | 195 // Enqueues any delayed tasks which should be run now on the |
201 // |delayed_work_queue|. Returns the subsequent wake-up that is required, if | 196 // |delayed_work_queue|. Returns the subsequent wakeup that is required, if |
202 // any. Must be called from the main thread. | 197 // any. Must be called from the main thread. |
203 base::Optional<DelayedWakeUp> WakeUpForDelayedWork(LazyNow* lazy_now); | 198 base::Optional<DelayedWakeUp> WakeUpForDelayedWork(LazyNow* lazy_now); |
204 | 199 |
205 base::TimeTicks scheduled_time_domain_wake_up() const { | 200 base::TimeTicks scheduled_time_domain_wakeup() const { |
206 return main_thread_only().scheduled_time_domain_wake_up; | 201 return main_thread_only().scheduled_time_domain_wakeup; |
207 } | 202 } |
208 | 203 |
209 void set_scheduled_time_domain_wake_up( | 204 void set_scheduled_time_domain_wakeup( |
210 base::TimeTicks scheduled_time_domain_wake_up) { | 205 base::TimeTicks scheduled_time_domain_wakeup) { |
211 main_thread_only().scheduled_time_domain_wake_up = | 206 main_thread_only().scheduled_time_domain_wakeup = |
212 scheduled_time_domain_wake_up; | 207 scheduled_time_domain_wakeup; |
213 } | 208 } |
214 | 209 |
215 HeapHandle heap_handle() const { return main_thread_only().heap_handle; } | 210 HeapHandle heap_handle() const { return main_thread_only().heap_handle; } |
216 | 211 |
217 void set_heap_handle(HeapHandle heap_handle) { | 212 void set_heap_handle(HeapHandle heap_handle) { |
218 main_thread_only().heap_handle = heap_handle; | 213 main_thread_only().heap_handle = heap_handle; |
219 } | 214 } |
220 | 215 |
221 void PushImmediateIncomingTaskForTest(TaskQueueImpl::Task&& task); | 216 void PushImmediateIncomingTaskForTest(TaskQueueImpl::Task&& task); |
222 EnqueueOrder GetFenceForTest() const; | 217 EnqueueOrder GetFenceForTest() const; |
(...skipping 24 matching lines...) Expand all Loading... |
247 | 242 |
248 enum class TaskType { | 243 enum class TaskType { |
249 NORMAL, | 244 NORMAL, |
250 NON_NESTABLE, | 245 NON_NESTABLE, |
251 }; | 246 }; |
252 | 247 |
253 struct AnyThread { | 248 struct AnyThread { |
254 AnyThread(TaskQueueManager* task_queue_manager, TimeDomain* time_domain); | 249 AnyThread(TaskQueueManager* task_queue_manager, TimeDomain* time_domain); |
255 ~AnyThread(); | 250 ~AnyThread(); |
256 | 251 |
257 // TaskQueueManager, TimeDomain and Observer are maintained in two copies: | 252 // TaskQueueManager and TimeDomain are maintained in two copies: |
258 // inside AnyThread and inside MainThreadOnly. They can be changed only from | 253 // inside AnyThread and inside MainThreadOnly. They can be changed only from |
259 // main thread, so it should be locked before accessing from other threads. | 254 // main thread, so it should be locked before accessing from other threads. |
260 TaskQueueManager* task_queue_manager; | 255 TaskQueueManager* task_queue_manager; |
261 TimeDomain* time_domain; | 256 TimeDomain* time_domain; |
262 Observer* observer; | |
263 }; | 257 }; |
264 | 258 |
265 struct MainThreadOnly { | 259 struct MainThreadOnly { |
266 MainThreadOnly(TaskQueueManager* task_queue_manager, | 260 MainThreadOnly(TaskQueueManager* task_queue_manager, |
267 TaskQueueImpl* task_queue, | 261 TaskQueueImpl* task_queue, |
268 TimeDomain* time_domain); | 262 TimeDomain* time_domain); |
269 ~MainThreadOnly(); | 263 ~MainThreadOnly(); |
270 | 264 |
271 // Another copy of TaskQueueManager, TimeDomain and Observer | 265 // Another copy of TaskQueueManager and TimeDomain for lock-free access from |
272 // for lock-free access from the main thread. | 266 // the main thread. See description inside struct AnyThread for details. |
273 // See description inside struct AnyThread for details. | |
274 TaskQueueManager* task_queue_manager; | 267 TaskQueueManager* task_queue_manager; |
275 TimeDomain* time_domain; | 268 TimeDomain* time_domain; |
276 Observer* observer; | |
277 | 269 |
278 std::unique_ptr<WorkQueue> delayed_work_queue; | 270 std::unique_ptr<WorkQueue> delayed_work_queue; |
279 std::unique_ptr<WorkQueue> immediate_work_queue; | 271 std::unique_ptr<WorkQueue> immediate_work_queue; |
280 std::priority_queue<Task> delayed_incoming_queue; | 272 std::priority_queue<Task> delayed_incoming_queue; |
281 base::ObserverList<base::MessageLoop::TaskObserver> task_observers; | 273 base::ObserverList<base::MessageLoop::TaskObserver> task_observers; |
282 size_t set_index; | 274 size_t set_index; |
283 HeapHandle heap_handle; | 275 HeapHandle heap_handle; |
284 int is_enabled_refcount; | 276 int is_enabled_refcount; |
285 int voter_refcount; | 277 int voter_refcount; |
286 base::trace_event::BlameContext* blame_context; // Not owned. | 278 base::trace_event::BlameContext* blame_context; // Not owned. |
287 EnqueueOrder current_fence; | 279 EnqueueOrder current_fence; |
288 base::TimeTicks scheduled_time_domain_wake_up; | 280 base::TimeTicks scheduled_time_domain_wakeup; |
289 }; | 281 }; |
290 | 282 |
291 ~TaskQueueImpl() override; | 283 ~TaskQueueImpl() override; |
292 | 284 |
293 bool PostImmediateTaskImpl(const tracked_objects::Location& from_here, | 285 bool PostImmediateTaskImpl(const tracked_objects::Location& from_here, |
294 base::OnceClosure task, | 286 base::OnceClosure task, |
295 TaskType task_type); | 287 TaskType task_type); |
296 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, | 288 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, |
297 base::OnceClosure task, | 289 base::OnceClosure task, |
298 base::TimeDelta delay, | 290 base::TimeDelta delay, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 base::trace_event::TracedValue* state); | 322 base::trace_event::TracedValue* state); |
331 static void QueueAsValueInto(const std::priority_queue<Task>& queue, | 323 static void QueueAsValueInto(const std::priority_queue<Task>& queue, |
332 base::trace_event::TracedValue* state); | 324 base::trace_event::TracedValue* state); |
333 static void TaskAsValueInto(const Task& task, | 325 static void TaskAsValueInto(const Task& task, |
334 base::trace_event::TracedValue* state); | 326 base::trace_event::TracedValue* state); |
335 | 327 |
336 void RemoveQueueEnabledVoter(const QueueEnabledVoterImpl* voter); | 328 void RemoveQueueEnabledVoter(const QueueEnabledVoterImpl* voter); |
337 void OnQueueEnabledVoteChanged(bool enabled); | 329 void OnQueueEnabledVoteChanged(bool enabled); |
338 void EnableOrDisableWithSelector(bool enable); | 330 void EnableOrDisableWithSelector(bool enable); |
339 | 331 |
340 // Schedules delayed work on time domain and calls the observer. | |
341 void ScheduleDelayedWorkInTimeDomain(base::TimeTicks now); | |
342 | |
343 void NotifyWakeUpChangedOnMainThread(base::TimeTicks wake_up); | |
344 | |
345 const base::PlatformThreadId thread_id_; | 332 const base::PlatformThreadId thread_id_; |
346 | 333 |
347 mutable base::Lock any_thread_lock_; | 334 mutable base::Lock any_thread_lock_; |
348 AnyThread any_thread_; | 335 AnyThread any_thread_; |
349 struct AnyThread& any_thread() { | 336 struct AnyThread& any_thread() { |
350 any_thread_lock_.AssertAcquired(); | 337 any_thread_lock_.AssertAcquired(); |
351 return any_thread_; | 338 return any_thread_; |
352 } | 339 } |
353 const struct AnyThread& any_thread() const { | 340 const struct AnyThread& any_thread() const { |
354 any_thread_lock_.AssertAcquired(); | 341 any_thread_lock_.AssertAcquired(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 const bool should_report_when_execution_blocked_; | 374 const bool should_report_when_execution_blocked_; |
388 | 375 |
389 DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl); | 376 DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl); |
390 }; | 377 }; |
391 | 378 |
392 } // namespace internal | 379 } // namespace internal |
393 } // namespace scheduler | 380 } // namespace scheduler |
394 } // namespace blink | 381 } // namespace blink |
395 | 382 |
396 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ | 383 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_ |
OLD | NEW |