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 #include "platform/scheduler/base/task_queue_impl.h" | 5 #include "platform/scheduler/base/task_queue_impl.h" |
6 | 6 |
7 #include "base/trace_event/blame_context.h" | 7 #include "base/trace_event/blame_context.h" |
8 #include "platform/scheduler/base/task_queue_manager.h" | 8 #include "platform/scheduler/base/task_queue_manager.h" |
9 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" |
10 #include "platform/scheduler/base/time_domain.h" | 10 #include "platform/scheduler/base/time_domain.h" |
11 #include "platform/scheduler/base/work_queue.h" | 11 #include "platform/scheduler/base/work_queue.h" |
12 | 12 |
13 namespace blink { | 13 namespace blink { |
14 namespace scheduler { | 14 namespace scheduler { |
| 15 |
| 16 TaskQueue::TaskHandle::TaskHandle() : enqueue_order_(0), sequence_number_(0) {} |
| 17 |
| 18 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, uint64_t enqueue_order) |
| 19 : enqueue_order_(enqueue_order), |
| 20 #if DCHECK_IS_ON() |
| 21 task_queue_(task_queue), |
| 22 #endif |
| 23 sequence_number_(0) { |
| 24 DCHECK_GT(enqueue_order, 0ull); |
| 25 } |
| 26 |
| 27 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, |
| 28 base::TimeTicks scheduled_run_time, |
| 29 int sequence_number) |
| 30 : enqueue_order_(0), |
| 31 scheduled_run_time_(scheduled_run_time), |
| 32 #if DCHECK_IS_ON() |
| 33 task_queue_(task_queue), |
| 34 #endif |
| 35 sequence_number_(sequence_number) { |
| 36 DCHECK(!scheduled_run_time.is_null()); |
| 37 } |
| 38 |
| 39 TaskQueue::TaskHandle::operator bool() const { |
| 40 return !scheduled_run_time_.is_null() || |
| 41 internal::EnqueueOrderGenerator::IsValidEnqueueOrder(enqueue_order_); |
| 42 } |
| 43 |
15 namespace internal { | 44 namespace internal { |
16 | 45 |
17 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
18 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
19 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
20 const Spec& spec, | 49 const Spec& spec, |
21 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
22 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
23 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
24 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 53 any_thread_(task_queue_manager, spec.pump_policy, time_domain), |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 bool nestable, | 113 bool nestable, |
85 EnqueueOrder enqueue_order) | 114 EnqueueOrder enqueue_order) |
86 : PendingTask(posted_from, task, desired_run_time, nestable), | 115 : PendingTask(posted_from, task, desired_run_time, nestable), |
87 #ifndef NDEBUG | 116 #ifndef NDEBUG |
88 enqueue_order_set_(true), | 117 enqueue_order_set_(true), |
89 #endif | 118 #endif |
90 enqueue_order_(enqueue_order) { | 119 enqueue_order_(enqueue_order) { |
91 sequence_num = sequence_number; | 120 sequence_num = sequence_number; |
92 } | 121 } |
93 | 122 |
| 123 // static |
| 124 TaskQueueImpl::Task TaskQueueImpl::Task::CreateFakeTaskFromHandle( |
| 125 const TaskHandle& handle) { |
| 126 if (handle.scheduled_run_time_.is_null()) { |
| 127 // It's an immediate task. |
| 128 return Task(tracked_objects::Location(), base::Closure(), |
| 129 handle.scheduled_run_time_, handle.sequence_number_, false, |
| 130 handle.enqueue_order_); |
| 131 } else { |
| 132 // It's a delayed task. |
| 133 DCHECK_EQ(0ull, handle.enqueue_order_); |
| 134 return Task(tracked_objects::Location(), base::Closure(), |
| 135 handle.scheduled_run_time_, handle.sequence_number_, false); |
| 136 } |
| 137 } |
| 138 |
| 139 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()( |
| 140 const Task& a, |
| 141 const Task& b) const { |
| 142 if (a.delayed_run_time < b.delayed_run_time) |
| 143 return true; |
| 144 |
| 145 if (a.delayed_run_time > b.delayed_run_time) |
| 146 return false; |
| 147 |
| 148 // If the times happen to match, then we use the sequence number to decide. |
| 149 // Compare the difference to support integer roll-over. |
| 150 return (a.sequence_num - b.sequence_num) < 0; |
| 151 } |
| 152 |
| 153 // static |
| 154 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a, |
| 155 const Task& b) { |
| 156 return a.enqueue_order() < b.enqueue_order(); |
| 157 } |
| 158 |
| 159 // static |
| 160 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a, |
| 161 const Task& b) { |
| 162 if (a.delayed_run_time < b.delayed_run_time) |
| 163 return true; |
| 164 |
| 165 if (a.delayed_run_time > b.delayed_run_time) |
| 166 return false; |
| 167 |
| 168 // If the times happen to match, then we use the sequence number to decide. |
| 169 // Compare the difference to support integer roll-over. |
| 170 return (a.sequence_num - b.sequence_num) < 0; |
| 171 } |
| 172 |
94 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 173 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
95 PumpPolicy pump_policy, | 174 PumpPolicy pump_policy, |
96 TimeDomain* time_domain) | 175 TimeDomain* time_domain) |
97 : task_queue_manager(task_queue_manager), | 176 : task_queue_manager(task_queue_manager), |
98 pump_policy(pump_policy), | 177 pump_policy(pump_policy), |
99 time_domain(time_domain) {} | 178 time_domain(time_domain), |
| 179 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { |
| 180 } |
100 | 181 |
101 TaskQueueImpl::AnyThread::~AnyThread() {} | 182 TaskQueueImpl::AnyThread::~AnyThread() {} |
102 | 183 |
103 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 184 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
104 TaskQueueManager* task_queue_manager, | 185 TaskQueueManager* task_queue_manager, |
105 PumpPolicy pump_policy, | 186 PumpPolicy pump_policy, |
106 TaskQueueImpl* task_queue, | 187 TaskQueueImpl* task_queue, |
107 TimeDomain* time_domain) | 188 TimeDomain* time_domain) |
108 : task_queue_manager(task_queue_manager), | 189 : task_queue_manager(task_queue_manager), |
109 pump_policy(pump_policy), | 190 pump_policy(pump_policy), |
110 time_domain(time_domain), | 191 time_domain(time_domain), |
111 delayed_work_queue(new WorkQueue(task_queue, "delayed")), | 192 delayed_work_queue( |
112 immediate_work_queue(new WorkQueue(task_queue, "immediate")), | 193 new WorkQueue(task_queue, |
| 194 "delayed", |
| 195 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), |
| 196 immediate_work_queue( |
| 197 new WorkQueue(task_queue, |
| 198 "immediate", |
| 199 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), |
113 set_index(0), | 200 set_index(0), |
114 is_enabled(true), | 201 is_enabled(true), |
115 blame_context(nullptr) {} | 202 blame_context(nullptr) {} |
116 | 203 |
117 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 204 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
118 | 205 |
119 void TaskQueueImpl::UnregisterTaskQueue() { | 206 void TaskQueueImpl::UnregisterTaskQueue() { |
120 base::AutoLock lock(any_thread_lock_); | 207 base::AutoLock lock(any_thread_lock_); |
121 if (main_thread_only().time_domain) | 208 if (main_thread_only().time_domain) |
122 main_thread_only().time_domain->UnregisterQueue(this); | 209 main_thread_only().time_domain->UnregisterQueue(this); |
123 if (!any_thread().task_queue_manager) | 210 if (!any_thread().task_queue_manager) |
124 return; | 211 return; |
125 any_thread().time_domain = nullptr; | 212 any_thread().time_domain = nullptr; |
126 main_thread_only().time_domain = nullptr; | 213 main_thread_only().time_domain = nullptr; |
127 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 214 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
128 | 215 |
129 any_thread().task_queue_manager = nullptr; | 216 any_thread().task_queue_manager = nullptr; |
130 main_thread_only().task_queue_manager = nullptr; | 217 main_thread_only().task_queue_manager = nullptr; |
131 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); | 218 main_thread_only().delayed_incoming_queue.clear(); |
132 any_thread().immediate_incoming_queue = std::queue<Task>(); | 219 any_thread().immediate_incoming_queue.clear(); |
133 main_thread_only().immediate_work_queue.reset(); | 220 main_thread_only().immediate_work_queue.reset(); |
134 main_thread_only().delayed_work_queue.reset(); | 221 main_thread_only().delayed_work_queue.reset(); |
135 } | 222 } |
136 | 223 |
137 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 224 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
138 base::AutoLock lock(any_thread_lock_); | 225 base::AutoLock lock(any_thread_lock_); |
139 return base::PlatformThread::CurrentId() == thread_id_; | 226 return base::PlatformThread::CurrentId() == thread_id_; |
140 } | 227 } |
141 | 228 |
| 229 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask( |
| 230 const tracked_objects::Location& from_here, |
| 231 const base::Closure& task, |
| 232 base::TimeDelta delay) { |
| 233 if (!main_thread_only().task_queue_manager) |
| 234 return TaskHandle(); |
| 235 |
| 236 EnqueueOrder sequence_number = |
| 237 main_thread_only().task_queue_manager->GetNextSequenceNumber(); |
| 238 |
| 239 if (delay.is_zero()) { |
| 240 base::AutoLock lock(any_thread_lock_); |
| 241 PushOntoImmediateIncomingQueueLocked( |
| 242 Task(from_here, task, base::TimeTicks(), sequence_number, true, |
| 243 sequence_number)); |
| 244 |
| 245 return TaskHandle(this, sequence_number); |
| 246 } else { |
| 247 DCHECK_GT(delay, base::TimeDelta()); |
| 248 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 249 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 250 PushOntoDelayedIncomingQueueFromMainThread( |
| 251 Task(from_here, task, time_domain_delayed_run_time, sequence_number, |
| 252 true), |
| 253 time_domain_now); |
| 254 |
| 255 return TaskHandle(this, time_domain_delayed_run_time, sequence_number); |
| 256 } |
| 257 } |
| 258 |
| 259 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) { |
| 260 if (!handle) |
| 261 return false; |
| 262 |
| 263 // If the TaskQueueManager has gone away, pretend we have canceled the task |
| 264 // because this simplifies logic in TimerBase::stop. |
| 265 if (!main_thread_only().task_queue_manager) |
| 266 return true; |
| 267 |
| 268 #if DCHECK_IS_ON() |
| 269 DCHECK_EQ(handle.task_queue_, this); |
| 270 #endif |
| 271 |
| 272 Task fake_task = Task::CreateFakeTaskFromHandle(handle); |
| 273 if (handle.scheduled_run_time_.is_null()) { |
| 274 // It's an immediate task. |
| 275 if (main_thread_only().immediate_work_queue->CancelTask(fake_task)) |
| 276 return true; |
| 277 |
| 278 base::AutoLock lock(any_thread_lock_); |
| 279 return any_thread().immediate_incoming_queue.erase(fake_task) > 0; |
| 280 } else { |
| 281 // It's a delayed task. |
| 282 DelayedRunTimeQueue::iterator it = |
| 283 main_thread_only().delayed_incoming_queue.find(fake_task); |
| 284 if (it != main_thread_only().delayed_incoming_queue.end()) { |
| 285 // It's safe to remove the wakeup from the TimeDomain only if this task's |
| 286 // scheduled run time was unique within the queue. |
| 287 bool can_cancel_timedomain_wakeup = true; |
| 288 if (it != main_thread_only().delayed_incoming_queue.begin()) { |
| 289 DelayedRunTimeQueue::iterator before = it; |
| 290 before--; |
| 291 if (before->delayed_run_time == handle.scheduled_run_time_) |
| 292 can_cancel_timedomain_wakeup = false; |
| 293 } |
| 294 if (can_cancel_timedomain_wakeup) { |
| 295 DelayedRunTimeQueue::iterator after = it; |
| 296 after++; |
| 297 if (after != main_thread_only().delayed_incoming_queue.end() && |
| 298 after->delayed_run_time == handle.scheduled_run_time_) { |
| 299 can_cancel_timedomain_wakeup = false; |
| 300 } |
| 301 } |
| 302 if (can_cancel_timedomain_wakeup) { |
| 303 main_thread_only().time_domain->CancelDelayedWork( |
| 304 this, handle.scheduled_run_time_); |
| 305 } |
| 306 |
| 307 main_thread_only().delayed_incoming_queue.erase(it); |
| 308 return true; |
| 309 } |
| 310 |
| 311 return main_thread_only().delayed_work_queue->CancelTask(fake_task); |
| 312 } |
| 313 } |
| 314 |
| 315 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const { |
| 316 if (!handle) |
| 317 return false; |
| 318 |
| 319 // If the TaskQueueManager has gone away the task got cancelled. |
| 320 if (!main_thread_only().task_queue_manager) |
| 321 return false; |
| 322 |
| 323 #if DCHECK_IS_ON() |
| 324 DCHECK_EQ(handle.task_queue_, this); |
| 325 #endif |
| 326 |
| 327 Task fake_task = Task::CreateFakeTaskFromHandle(handle); |
| 328 if (handle.scheduled_run_time_.is_null()) { |
| 329 // It's an immediate task. |
| 330 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task)) |
| 331 return true; |
| 332 |
| 333 base::AutoLock lock(any_thread_lock_); |
| 334 return any_thread().immediate_incoming_queue.find(fake_task) != |
| 335 any_thread().immediate_incoming_queue.end(); |
| 336 } else { |
| 337 // It's a delayed task. |
| 338 DelayedRunTimeQueue::iterator it = |
| 339 main_thread_only().delayed_incoming_queue.find(fake_task); |
| 340 if (it != main_thread_only().delayed_incoming_queue.end()) |
| 341 return true; |
| 342 |
| 343 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task); |
| 344 } |
| 345 } |
| 346 |
142 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 347 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
143 const base::Closure& task, | 348 const base::Closure& task, |
144 base::TimeDelta delay) { | 349 base::TimeDelta delay) { |
145 if (delay.is_zero()) | 350 if (delay.is_zero()) |
146 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); | 351 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); |
147 | 352 |
148 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 353 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
149 } | 354 } |
150 | 355 |
151 bool TaskQueueImpl::PostNonNestableDelayedTask( | 356 bool TaskQueueImpl::PostNonNestableDelayedTask( |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 return true; | 421 return true; |
217 } | 422 } |
218 | 423 |
219 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 424 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
220 Task pending_task, | 425 Task pending_task, |
221 base::TimeTicks now) { | 426 base::TimeTicks now) { |
222 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 427 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
223 | 428 |
224 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. | 429 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. |
225 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 430 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
226 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 431 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
227 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 432 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, |
228 now); | 433 now); |
229 TraceQueueSize(false); | 434 TraceQueueSize(false); |
230 } | 435 } |
231 | 436 |
232 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 437 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
233 any_thread().task_queue_manager->DidQueueTask(pending_task); | 438 any_thread().task_queue_manager->DidQueueTask(pending_task); |
234 | 439 |
235 int thread_hop_task_sequence_number = | 440 int thread_hop_task_sequence_number = |
236 any_thread().task_queue_manager->GetNextSequenceNumber(); | 441 any_thread().task_queue_manager->GetNextSequenceNumber(); |
237 PushOntoImmediateIncomingQueueLocked( | 442 PushOntoImmediateIncomingQueueLocked( |
238 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 443 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
239 base::Passed(&pending_task)), | 444 base::Passed(&pending_task)), |
240 base::TimeTicks(), thread_hop_task_sequence_number, false, | 445 base::TimeTicks(), thread_hop_task_sequence_number, false, |
241 thread_hop_task_sequence_number)); | 446 thread_hop_task_sequence_number)); |
242 } | 447 } |
243 | 448 |
244 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 449 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
245 if (any_thread().immediate_incoming_queue.empty()) | 450 if (any_thread().immediate_incoming_queue.empty()) |
246 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 451 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
247 if (any_thread().pump_policy == PumpPolicy::AUTO && | 452 if (any_thread().pump_policy == PumpPolicy::AUTO && |
248 any_thread().immediate_incoming_queue.empty()) { | 453 any_thread().immediate_incoming_queue.empty()) { |
249 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
250 } | 455 } |
251 any_thread().task_queue_manager->DidQueueTask(pending_task); | 456 any_thread().task_queue_manager->DidQueueTask(pending_task); |
252 any_thread().immediate_incoming_queue.push(std::move(pending_task)); | 457 // We expect |pending_task| to be inserted at the end. Amoritized O(1). |
| 458 any_thread().immediate_incoming_queue.insert( |
| 459 any_thread().immediate_incoming_queue.end(), |
| 460 std::move(pending_task)); |
| 461 DCHECK_EQ(pending_task.enqueue_order(), |
| 462 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); |
253 TraceQueueSize(true); | 463 TraceQueueSize(true); |
254 } | 464 } |
255 | 465 |
256 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | 466 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { |
257 DCHECK(main_thread_checker_.CalledOnValidThread()); | 467 DCHECK(main_thread_checker_.CalledOnValidThread()); |
258 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 468 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
259 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 469 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
260 main_thread_only().time_domain->ScheduleDelayedWork( | 470 // Make sure |delayed_run_time| isn't in the past. |
261 this, delayed_run_time, main_thread_only().time_domain->Now()); | 471 if (delayed_run_time < time_domain_now) { |
| 472 delayed_run_time = time_domain_now; |
| 473 pending_task.delayed_run_time = time_domain_now; |
| 474 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 475 LazyNow lazy_now(time_domain_now); |
| 476 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); |
| 477 } else { |
| 478 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 479 main_thread_only().time_domain->ScheduleDelayedWork( |
| 480 this, delayed_run_time, main_thread_only().time_domain->Now()); |
| 481 } |
| 482 TraceQueueSize(false); |
262 } | 483 } |
263 | 484 |
264 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 485 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
265 if (main_thread_only().is_enabled == enabled) | 486 if (main_thread_only().is_enabled == enabled) |
266 return; | 487 return; |
267 main_thread_only().is_enabled = enabled; | 488 main_thread_only().is_enabled = enabled; |
268 if (!main_thread_only().task_queue_manager) | 489 if (!main_thread_only().task_queue_manager) |
269 return; | 490 return; |
270 if (enabled) { | 491 if (enabled) { |
271 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 492 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 | 525 |
305 base::AutoLock lock(any_thread_lock_); | 526 base::AutoLock lock(any_thread_lock_); |
306 if (!any_thread().immediate_incoming_queue.empty()) | 527 if (!any_thread().immediate_incoming_queue.empty()) |
307 return true; | 528 return true; |
308 | 529 |
309 // If there's no immediate Incoming work then we only need pumping if there | 530 // If there's no immediate Incoming work then we only need pumping if there |
310 // is a delayed task that should be running now. | 531 // is a delayed task that should be running now. |
311 if (main_thread_only().delayed_incoming_queue.empty()) | 532 if (main_thread_only().delayed_incoming_queue.empty()) |
312 return false; | 533 return false; |
313 | 534 |
314 return main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 535 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
315 main_thread_only().time_domain->CreateLazyNow().Now(); | 536 main_thread_only().time_domain->CreateLazyNow().Now(); |
316 } | 537 } |
317 | 538 |
318 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( | 539 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( |
319 const Task* task) { | 540 const Task* task) { |
320 // A null task is passed when UpdateQueue is called before any task is run. | 541 // A null task is passed when UpdateQueue is called before any task is run. |
321 // In this case we don't want to pump an after_wakeup queue, so return true | 542 // In this case we don't want to pump an after_wakeup queue, so return true |
322 // here. | 543 // here. |
323 if (!task) | 544 if (!task) |
324 return true; | 545 return true; |
325 | 546 |
326 // Return false if task is newer than the oldest immediate task. | 547 // Return false if task is newer than the oldest immediate task. |
327 if (!any_thread().immediate_incoming_queue.empty() && | 548 if (!any_thread().immediate_incoming_queue.empty() && |
328 task->enqueue_order() > | 549 task->enqueue_order() > |
329 any_thread().immediate_incoming_queue.front().enqueue_order()) { | 550 any_thread().immediate_incoming_queue.begin()->enqueue_order()) { |
330 return false; | 551 return false; |
331 } | 552 } |
332 return true; | 553 return true; |
333 } | 554 } |
334 | 555 |
335 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { | 556 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { |
336 DCHECK(main_thread_checker_.CalledOnValidThread()); | 557 DCHECK(main_thread_checker_.CalledOnValidThread()); |
337 // A null task is passed when UpdateQueue is called before any task is run. | 558 // A null task is passed when UpdateQueue is called before any task is run. |
338 // In this case we don't want to pump an after_wakeup queue, so return true | 559 // In this case we don't want to pump an after_wakeup queue, so return true |
339 // here. | 560 // here. |
(...skipping 27 matching lines...) Expand all Loading... |
367 return false; | 588 return false; |
368 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | 589 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && |
369 (!should_trigger_wakeup || | 590 (!should_trigger_wakeup || |
370 TaskIsOlderThanQueuedDelayedTasks(previous_task))) | 591 TaskIsOlderThanQueuedDelayedTasks(previous_task))) |
371 return false; | 592 return false; |
372 return true; | 593 return true; |
373 } | 594 } |
374 | 595 |
375 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 596 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
376 // Enqueue all delayed tasks that should be running now. | 597 // Enqueue all delayed tasks that should be running now. |
377 while (!main_thread_only().delayed_incoming_queue.empty() && | 598 while (!main_thread_only().delayed_incoming_queue.empty()) { |
378 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 599 DelayedRunTimeQueue::iterator next_task = |
379 lazy_now->Now()) { | 600 main_thread_only().delayed_incoming_queue.begin(); |
380 // Note: the const_cast is needed because there is no direct way to move | 601 if (next_task->delayed_run_time > lazy_now->Now()) |
381 // elements out of a priority queue. The queue must not be modified between | 602 break; |
382 // the top() and the pop(). | 603 // TODO(alexclarke): Use extract() when C++17 is allowed. |
383 main_thread_only().delayed_work_queue->PushAndSetEnqueueOrder( | 604 Task& task = const_cast<Task&>(*next_task); |
384 std::move( | 605 task.set_enqueue_order( |
385 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())), | |
386 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 606 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
387 main_thread_only().delayed_incoming_queue.pop(); | 607 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 608 main_thread_only().delayed_incoming_queue.erase(next_task); |
388 } | 609 } |
389 } | 610 } |
390 | 611 |
391 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 612 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, |
392 bool should_trigger_wakeup, | 613 bool should_trigger_wakeup, |
393 const Task* previous_task) { | 614 const Task* previous_task) { |
394 if (!main_thread_only().task_queue_manager) | 615 if (!main_thread_only().task_queue_manager) |
395 return; | 616 return; |
396 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | 617 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) |
397 return; | 618 return; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { | 681 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { |
461 TRACE_EVENT1(disabled_by_default_tracing_category_, | 682 TRACE_EVENT1(disabled_by_default_tracing_category_, |
462 "TaskQueueImpl::PumpQueueLocked", "queue", name_); | 683 "TaskQueueImpl::PumpQueueLocked", "queue", name_); |
463 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; | 684 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; |
464 if (!task_queue_manager) | 685 if (!task_queue_manager) |
465 return; | 686 return; |
466 | 687 |
467 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 688 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
468 | 689 |
469 while (!any_thread().immediate_incoming_queue.empty()) { | 690 while (!any_thread().immediate_incoming_queue.empty()) { |
| 691 ComparatorQueue::iterator it = |
| 692 any_thread().immediate_incoming_queue.begin(); |
470 main_thread_only().immediate_work_queue->Push( | 693 main_thread_only().immediate_work_queue->Push( |
471 std::move(any_thread().immediate_incoming_queue.front())); | 694 std::move(const_cast<Task&>(*it))); |
472 any_thread().immediate_incoming_queue.pop(); | 695 any_thread().immediate_incoming_queue.erase(it); |
473 } | 696 } |
474 | 697 |
475 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no | 698 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no |
476 // longer needs to consider this queue for reloading. | 699 // longer needs to consider this queue for reloading. |
477 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 700 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
478 | 701 |
479 if (main_thread_only().immediate_work_queue->Empty() && | 702 if (main_thread_only().immediate_work_queue->Empty() && |
480 main_thread_only().delayed_work_queue->Empty()) { | 703 main_thread_only().delayed_work_queue->Empty()) { |
481 return; | 704 return; |
482 } | 705 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 state->SetInteger("immediate_incoming_queue_size", | 792 state->SetInteger("immediate_incoming_queue_size", |
570 any_thread().immediate_incoming_queue.size()); | 793 any_thread().immediate_incoming_queue.size()); |
571 state->SetInteger("delayed_incoming_queue_size", | 794 state->SetInteger("delayed_incoming_queue_size", |
572 main_thread_only().delayed_incoming_queue.size()); | 795 main_thread_only().delayed_incoming_queue.size()); |
573 state->SetInteger("immediate_work_queue_size", | 796 state->SetInteger("immediate_work_queue_size", |
574 main_thread_only().immediate_work_queue->Size()); | 797 main_thread_only().immediate_work_queue->Size()); |
575 state->SetInteger("delayed_work_queue_size", | 798 state->SetInteger("delayed_work_queue_size", |
576 main_thread_only().delayed_work_queue->Size()); | 799 main_thread_only().delayed_work_queue->Size()); |
577 if (!main_thread_only().delayed_incoming_queue.empty()) { | 800 if (!main_thread_only().delayed_incoming_queue.empty()) { |
578 base::TimeDelta delay_to_next_task = | 801 base::TimeDelta delay_to_next_task = |
579 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 802 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - |
580 main_thread_only().time_domain->CreateLazyNow().Now()); | 803 main_thread_only().time_domain->CreateLazyNow().Now()); |
581 state->SetDouble("delay_to_next_task_ms", | 804 state->SetDouble("delay_to_next_task_ms", |
582 delay_to_next_task.InMillisecondsF()); | 805 delay_to_next_task.InMillisecondsF()); |
583 } | 806 } |
584 if (verbose_tracing_enabled) { | 807 if (verbose_tracing_enabled) { |
585 state->BeginArray("immediate_incoming_queue"); | 808 state->BeginArray("immediate_incoming_queue"); |
586 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 809 QueueAsValueInto(any_thread().immediate_incoming_queue, state); |
587 state->EndArray(); | 810 state->EndArray(); |
588 state->BeginArray("delayed_work_queue"); | 811 state->BeginArray("delayed_work_queue"); |
589 main_thread_only().delayed_work_queue->AsValueInto(state); | 812 main_thread_only().delayed_work_queue->AsValueInto(state); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 base::AutoLock lock(any_thread_lock_); | 878 base::AutoLock lock(any_thread_lock_); |
656 return any_thread().time_domain; | 879 return any_thread().time_domain; |
657 } | 880 } |
658 | 881 |
659 void TaskQueueImpl::SetBlameContext( | 882 void TaskQueueImpl::SetBlameContext( |
660 base::trace_event::BlameContext* blame_context) { | 883 base::trace_event::BlameContext* blame_context) { |
661 main_thread_only().blame_context = blame_context; | 884 main_thread_only().blame_context = blame_context; |
662 } | 885 } |
663 | 886 |
664 // static | 887 // static |
665 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 888 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
666 base::trace_event::TracedValue* state) { | 889 base::trace_event::TracedValue* state) { |
667 // Remove const to search |queue| in the destructive manner. Restore the | 890 for (const Task& task : queue) { |
668 // content from |visited| later. | 891 TaskAsValueInto(task, state); |
669 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue); | |
670 std::queue<Task> visited; | |
671 while (!mutable_queue->empty()) { | |
672 TaskAsValueInto(mutable_queue->front(), state); | |
673 visited.push(std::move(mutable_queue->front())); | |
674 mutable_queue->pop(); | |
675 } | 892 } |
676 *mutable_queue = std::move(visited); | |
677 } | 893 } |
678 | 894 |
679 // static | 895 // static |
680 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, | 896 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
681 base::trace_event::TracedValue* state) { | 897 base::trace_event::TracedValue* state) { |
682 // Remove const to search |queue| in the destructive manner. Restore the | 898 for (const Task& task : queue) { |
683 // content from |visited| later. | 899 TaskAsValueInto(task, state); |
684 std::priority_queue<Task>* mutable_queue = | |
685 const_cast<std::priority_queue<Task>*>(&queue); | |
686 std::priority_queue<Task> visited; | |
687 while (!mutable_queue->empty()) { | |
688 TaskAsValueInto(mutable_queue->top(), state); | |
689 visited.push(std::move(const_cast<Task&>(mutable_queue->top()))); | |
690 mutable_queue->pop(); | |
691 } | 900 } |
692 *mutable_queue = std::move(visited); | |
693 } | 901 } |
694 | 902 |
695 // static | 903 // static |
696 void TaskQueueImpl::TaskAsValueInto(const Task& task, | 904 void TaskQueueImpl::TaskAsValueInto(const Task& task, |
697 base::trace_event::TracedValue* state) { | 905 base::trace_event::TracedValue* state) { |
698 state->BeginDictionary(); | 906 state->BeginDictionary(); |
699 state->SetString("posted_from", task.posted_from.ToString()); | 907 state->SetString("posted_from", task.posted_from.ToString()); |
700 #ifndef NDEBUG | 908 #ifndef NDEBUG |
701 if (task.enqueue_order_set()) | 909 if (task.enqueue_order_set()) |
702 state->SetInteger("enqueue_order", task.enqueue_order()); | 910 state->SetInteger("enqueue_order", task.enqueue_order()); |
703 #else | 911 #else |
704 state->SetInteger("enqueue_order", task.enqueue_order()); | 912 state->SetInteger("enqueue_order", task.enqueue_order()); |
705 #endif | 913 #endif |
706 state->SetInteger("sequence_num", task.sequence_num); | 914 state->SetInteger("sequence_num", task.sequence_num); |
707 state->SetBoolean("nestable", task.nestable); | 915 state->SetBoolean("nestable", task.nestable); |
708 state->SetBoolean("is_high_res", task.is_high_res); | 916 state->SetBoolean("is_high_res", task.is_high_res); |
709 state->SetDouble( | 917 state->SetDouble( |
710 "delayed_run_time", | 918 "delayed_run_time", |
711 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 919 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
712 state->EndDictionary(); | 920 state->EndDictionary(); |
713 } | 921 } |
714 | 922 |
715 } // namespace internal | 923 } // namespace internal |
716 } // namespace scheduler | 924 } // namespace scheduler |
717 } // namespace blink | 925 } // namespace blink |
OLD | NEW |