| 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" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 namespace internal { | 44 namespace internal { |
| 45 | 45 |
| 46 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
| 47 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
| 48 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
| 49 const Spec& spec, | 49 const Spec& spec, |
| 50 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
| 51 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
| 52 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
| 53 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 53 any_thread_(task_queue_manager, time_domain), |
| 54 name_(spec.name), | 54 name_(spec.name), |
| 55 disabled_by_default_tracing_category_( | 55 disabled_by_default_tracing_category_( |
| 56 disabled_by_default_tracing_category), | 56 disabled_by_default_tracing_category), |
| 57 disabled_by_default_verbose_tracing_category_( | 57 disabled_by_default_verbose_tracing_category_( |
| 58 disabled_by_default_verbose_tracing_category), | 58 disabled_by_default_verbose_tracing_category), |
| 59 main_thread_only_(task_queue_manager, | 59 main_thread_only_(task_queue_manager, this, time_domain), |
| 60 spec.pump_policy, | |
| 61 this, | |
| 62 time_domain), | |
| 63 wakeup_policy_(spec.wakeup_policy), | |
| 64 should_monitor_quiescence_(spec.should_monitor_quiescence), | 60 should_monitor_quiescence_(spec.should_monitor_quiescence), |
| 65 should_notify_observers_(spec.should_notify_observers), | 61 should_notify_observers_(spec.should_notify_observers), |
| 66 should_report_when_execution_blocked_( | 62 should_report_when_execution_blocked_( |
| 67 spec.should_report_when_execution_blocked) { | 63 spec.should_report_when_execution_blocked) { |
| 68 DCHECK(time_domain); | 64 DCHECK(time_domain); |
| 69 time_domain->RegisterQueue(this); | 65 time_domain->RegisterQueue(this); |
| 70 } | 66 } |
| 71 | 67 |
| 72 TaskQueueImpl::~TaskQueueImpl() { | 68 TaskQueueImpl::~TaskQueueImpl() { |
| 73 #if DCHECK_IS_ON() | 69 #if DCHECK_IS_ON() |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 160 |
| 165 if (a.delayed_run_time > b.delayed_run_time) | 161 if (a.delayed_run_time > b.delayed_run_time) |
| 166 return false; | 162 return false; |
| 167 | 163 |
| 168 // If the times happen to match, then we use the sequence number to decide. | 164 // If the times happen to match, then we use the sequence number to decide. |
| 169 // Compare the difference to support integer roll-over. | 165 // Compare the difference to support integer roll-over. |
| 170 return (a.sequence_num - b.sequence_num) < 0; | 166 return (a.sequence_num - b.sequence_num) < 0; |
| 171 } | 167 } |
| 172 | 168 |
| 173 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 169 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 174 PumpPolicy pump_policy, | |
| 175 TimeDomain* time_domain) | 170 TimeDomain* time_domain) |
| 176 : task_queue_manager(task_queue_manager), | 171 : task_queue_manager(task_queue_manager), |
| 177 pump_policy(pump_policy), | |
| 178 time_domain(time_domain), | 172 time_domain(time_domain), |
| 179 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { | 173 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { |
| 180 } | 174 } |
| 181 | 175 |
| 182 TaskQueueImpl::AnyThread::~AnyThread() {} | 176 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 183 | 177 |
| 184 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 178 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| 185 TaskQueueManager* task_queue_manager, | 179 TaskQueueManager* task_queue_manager, |
| 186 PumpPolicy pump_policy, | |
| 187 TaskQueueImpl* task_queue, | 180 TaskQueueImpl* task_queue, |
| 188 TimeDomain* time_domain) | 181 TimeDomain* time_domain) |
| 189 : task_queue_manager(task_queue_manager), | 182 : task_queue_manager(task_queue_manager), |
| 190 pump_policy(pump_policy), | |
| 191 time_domain(time_domain), | 183 time_domain(time_domain), |
| 192 delayed_work_queue( | 184 delayed_work_queue( |
| 193 new WorkQueue(task_queue, | 185 new WorkQueue(task_queue, |
| 194 "delayed", | 186 "delayed", |
| 195 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), | 187 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), |
| 196 immediate_work_queue( | 188 immediate_work_queue( |
| 197 new WorkQueue(task_queue, | 189 new WorkQueue(task_queue, |
| 198 "immediate", | 190 "immediate", |
| 199 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), | 191 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), |
| 200 set_index(0), | 192 set_index(0), |
| (...skipping 30 matching lines...) Expand all Loading... |
| 231 const base::Closure& task, | 223 const base::Closure& task, |
| 232 base::TimeDelta delay) { | 224 base::TimeDelta delay) { |
| 233 if (!main_thread_only().task_queue_manager) | 225 if (!main_thread_only().task_queue_manager) |
| 234 return TaskHandle(); | 226 return TaskHandle(); |
| 235 | 227 |
| 236 EnqueueOrder sequence_number = | 228 EnqueueOrder sequence_number = |
| 237 main_thread_only().task_queue_manager->GetNextSequenceNumber(); | 229 main_thread_only().task_queue_manager->GetNextSequenceNumber(); |
| 238 | 230 |
| 239 if (delay.is_zero()) { | 231 if (delay.is_zero()) { |
| 240 base::AutoLock lock(any_thread_lock_); | 232 base::AutoLock lock(any_thread_lock_); |
| 233 // If the |immediate_incoming_queue| is empty and the queue is enabled then |
| 234 // we need a DoWork posted to make it run. |
| 235 if (any_thread().immediate_incoming_queue.empty() && |
| 236 main_thread_only().is_enabled && !BlockedByFence()) { |
| 237 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 238 } |
| 241 PushOntoImmediateIncomingQueueLocked( | 239 PushOntoImmediateIncomingQueueLocked( |
| 242 Task(from_here, task, base::TimeTicks(), sequence_number, true, | 240 Task(from_here, task, base::TimeTicks(), sequence_number, true, |
| 243 sequence_number)); | 241 sequence_number)); |
| 244 | 242 |
| 245 return TaskHandle(this, sequence_number); | 243 return TaskHandle(this, sequence_number); |
| 246 } else { | 244 } else { |
| 247 DCHECK_GT(delay, base::TimeDelta()); | 245 DCHECK_GT(delay, base::TimeDelta()); |
| 248 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 246 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 249 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 247 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 250 PushOntoDelayedIncomingQueueFromMainThread( | 248 PushOntoDelayedIncomingQueueFromMainThread( |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 const tracked_objects::Location& from_here, | 365 const tracked_objects::Location& from_here, |
| 368 const base::Closure& task, | 366 const base::Closure& task, |
| 369 TaskType task_type) { | 367 TaskType task_type) { |
| 370 base::AutoLock lock(any_thread_lock_); | 368 base::AutoLock lock(any_thread_lock_); |
| 371 if (!any_thread().task_queue_manager) | 369 if (!any_thread().task_queue_manager) |
| 372 return false; | 370 return false; |
| 373 | 371 |
| 374 EnqueueOrder sequence_number = | 372 EnqueueOrder sequence_number = |
| 375 any_thread().task_queue_manager->GetNextSequenceNumber(); | 373 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 376 | 374 |
| 375 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 376 // it run. |
| 377 if (any_thread().immediate_incoming_queue.empty()) { |
| 378 // There's no point posting a DoWork for a disabled queue, however we can |
| 379 // only tell if it's disabled from the main thread. |
| 380 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 381 if (main_thread_only().is_enabled && !BlockedByFence()) |
| 382 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 383 } else { |
| 384 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 385 } |
| 386 } |
| 387 |
| 377 PushOntoImmediateIncomingQueueLocked( | 388 PushOntoImmediateIncomingQueueLocked( |
| 378 Task(from_here, task, base::TimeTicks(), sequence_number, | 389 Task(from_here, task, base::TimeTicks(), sequence_number, |
| 379 task_type != TaskType::NON_NESTABLE, sequence_number)); | 390 task_type != TaskType::NON_NESTABLE, sequence_number)); |
| 380 return true; | 391 return true; |
| 381 } | 392 } |
| 382 | 393 |
| 383 bool TaskQueueImpl::PostDelayedTaskImpl( | 394 bool TaskQueueImpl::PostDelayedTaskImpl( |
| 384 const tracked_objects::Location& from_here, | 395 const tracked_objects::Location& from_here, |
| 385 const base::Closure& task, | 396 const base::Closure& task, |
| 386 base::TimeDelta delay, | 397 base::TimeDelta delay, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 443 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, |
| 433 now); | 444 now); |
| 434 TraceQueueSize(false); | 445 TraceQueueSize(false); |
| 435 } | 446 } |
| 436 | 447 |
| 437 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 448 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 438 any_thread().task_queue_manager->DidQueueTask(pending_task); | 449 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 439 | 450 |
| 440 int thread_hop_task_sequence_number = | 451 int thread_hop_task_sequence_number = |
| 441 any_thread().task_queue_manager->GetNextSequenceNumber(); | 452 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 453 |
| 454 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 455 // it run. |
| 456 if (any_thread().immediate_incoming_queue.empty()) |
| 457 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 458 |
| 442 PushOntoImmediateIncomingQueueLocked( | 459 PushOntoImmediateIncomingQueueLocked( |
| 443 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 460 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| 444 base::Passed(&pending_task)), | 461 base::Passed(&pending_task)), |
| 445 base::TimeTicks(), thread_hop_task_sequence_number, false, | 462 base::TimeTicks(), thread_hop_task_sequence_number, false, |
| 446 thread_hop_task_sequence_number)); | 463 thread_hop_task_sequence_number)); |
| 447 } | 464 } |
| 448 | 465 |
| 449 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 466 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
| 450 if (any_thread().immediate_incoming_queue.empty()) | 467 if (any_thread().immediate_incoming_queue.empty()) |
| 451 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 468 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
| 452 if (any_thread().pump_policy == PumpPolicy::AUTO && | |
| 453 any_thread().immediate_incoming_queue.empty()) { | |
| 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | |
| 455 } | |
| 456 any_thread().task_queue_manager->DidQueueTask(pending_task); | 469 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 457 // We expect |pending_task| to be inserted at the end. Amoritized O(1). | 470 // We expect |pending_task| to be inserted at the end. Amoritized O(1). |
| 458 any_thread().immediate_incoming_queue.insert( | 471 any_thread().immediate_incoming_queue.insert( |
| 459 any_thread().immediate_incoming_queue.end(), | 472 any_thread().immediate_incoming_queue.end(), |
| 460 std::move(pending_task)); | 473 std::move(pending_task)); |
| 461 DCHECK_EQ(pending_task.enqueue_order(), | 474 DCHECK_EQ(pending_task.enqueue_order(), |
| 462 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); | 475 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); |
| 463 TraceQueueSize(true); | 476 TraceQueueSize(true); |
| 464 } | 477 } |
| 465 | 478 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 482 TraceQueueSize(false); | 495 TraceQueueSize(false); |
| 483 } | 496 } |
| 484 | 497 |
| 485 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 498 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
| 486 if (main_thread_only().is_enabled == enabled) | 499 if (main_thread_only().is_enabled == enabled) |
| 487 return; | 500 return; |
| 488 main_thread_only().is_enabled = enabled; | 501 main_thread_only().is_enabled = enabled; |
| 489 if (!main_thread_only().task_queue_manager) | 502 if (!main_thread_only().task_queue_manager) |
| 490 return; | 503 return; |
| 491 if (enabled) { | 504 if (enabled) { |
| 505 // Note it's the job of the selector to tell the TaskQueueManager if |
| 506 // a DoWork needs posting. |
| 492 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 507 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| 493 } else { | 508 } else { |
| 494 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 509 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
| 495 } | 510 } |
| 496 } | 511 } |
| 497 | 512 |
| 498 bool TaskQueueImpl::IsQueueEnabled() const { | 513 bool TaskQueueImpl::IsQueueEnabled() const { |
| 499 return main_thread_only().is_enabled; | 514 return main_thread_only().is_enabled; |
| 500 } | 515 } |
| 501 | 516 |
| 502 bool TaskQueueImpl::IsEmpty() const { | 517 bool TaskQueueImpl::IsEmpty() const { |
| 503 if (!main_thread_only().delayed_work_queue->Empty() || | 518 if (!main_thread_only().delayed_work_queue->Empty() || |
| 504 !main_thread_only().immediate_work_queue->Empty()) { | 519 !main_thread_only().immediate_work_queue->Empty()) { |
| 505 return false; | 520 return false; |
| 506 } | 521 } |
| 507 | 522 |
| 508 base::AutoLock lock(any_thread_lock_); | 523 base::AutoLock lock(any_thread_lock_); |
| 509 return any_thread().immediate_incoming_queue.empty() && | 524 return any_thread().immediate_incoming_queue.empty() && |
| 510 main_thread_only().delayed_incoming_queue.empty(); | 525 main_thread_only().delayed_incoming_queue.empty(); |
| 511 } | 526 } |
| 512 | 527 |
| 513 bool TaskQueueImpl::HasPendingImmediateWork() const { | 528 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 529 // Any work queue tasks count as immediate work. |
| 514 if (!main_thread_only().delayed_work_queue->Empty() || | 530 if (!main_thread_only().delayed_work_queue->Empty() || |
| 515 !main_thread_only().immediate_work_queue->Empty()) { | 531 !main_thread_only().immediate_work_queue->Empty()) { |
| 516 return true; | 532 return true; |
| 517 } | 533 } |
| 518 | 534 |
| 519 return NeedsPumping(); | 535 // Tasks on |delayed_incoming_queue| that could run now, count as |
| 520 } | 536 // immediate work. |
| 521 | 537 if (!main_thread_only().delayed_incoming_queue.empty() && |
| 522 bool TaskQueueImpl::NeedsPumping() const { | 538 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
| 523 if (!main_thread_only().immediate_work_queue->Empty()) | 539 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 524 return false; | |
| 525 | |
| 526 base::AutoLock lock(any_thread_lock_); | |
| 527 if (!any_thread().immediate_incoming_queue.empty()) | |
| 528 return true; | |
| 529 | |
| 530 // If there's no immediate Incoming work then we only need pumping if there | |
| 531 // is a delayed task that should be running now. | |
| 532 if (main_thread_only().delayed_incoming_queue.empty()) | |
| 533 return false; | |
| 534 | |
| 535 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= | |
| 536 main_thread_only().time_domain->CreateLazyNow().Now(); | |
| 537 } | |
| 538 | |
| 539 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( | |
| 540 const Task* task) { | |
| 541 // A null task is passed when UpdateQueue is called before any task is run. | |
| 542 // In this case we don't want to pump an after_wakeup queue, so return true | |
| 543 // here. | |
| 544 if (!task) | |
| 545 return true; | |
| 546 | |
| 547 // Return false if task is newer than the oldest immediate task. | |
| 548 if (!any_thread().immediate_incoming_queue.empty() && | |
| 549 task->enqueue_order() > | |
| 550 any_thread().immediate_incoming_queue.begin()->enqueue_order()) { | |
| 551 return false; | |
| 552 } | |
| 553 return true; | |
| 554 } | |
| 555 | |
| 556 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { | |
| 557 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 558 // A null task is passed when UpdateQueue is called before any task is run. | |
| 559 // In this case we don't want to pump an after_wakeup queue, so return true | |
| 560 // here. | |
| 561 if (!task) | |
| 562 return true; | |
| 563 | |
| 564 EnqueueOrder enqueue_order; | |
| 565 if (!main_thread_only().delayed_work_queue->GetFrontTaskEnqueueOrder( | |
| 566 &enqueue_order)) { | |
| 567 return true; | 540 return true; |
| 568 } | 541 } |
| 569 | 542 |
| 570 return task->enqueue_order() < enqueue_order; | 543 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 571 } | 544 base::AutoLock lock(any_thread_lock_); |
| 572 | 545 return !any_thread().immediate_incoming_queue.empty(); |
| 573 bool TaskQueueImpl::ShouldAutoPumpImmediateQueueLocked( | |
| 574 bool should_trigger_wakeup, | |
| 575 const Task* previous_task) { | |
| 576 if (main_thread_only().pump_policy == PumpPolicy::MANUAL) | |
| 577 return false; | |
| 578 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | |
| 579 (!should_trigger_wakeup || | |
| 580 TaskIsOlderThanQueuedImmediateTasksLocked(previous_task))) | |
| 581 return false; | |
| 582 return true; | |
| 583 } | |
| 584 | |
| 585 bool TaskQueueImpl::ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup, | |
| 586 const Task* previous_task) { | |
| 587 if (main_thread_only().pump_policy == PumpPolicy::MANUAL) | |
| 588 return false; | |
| 589 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | |
| 590 (!should_trigger_wakeup || | |
| 591 TaskIsOlderThanQueuedDelayedTasks(previous_task))) | |
| 592 return false; | |
| 593 return true; | |
| 594 } | 546 } |
| 595 | 547 |
| 596 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 548 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
| 597 // Enqueue all delayed tasks that should be running now. | 549 // Enqueue all delayed tasks that should be running now. |
| 598 while (!main_thread_only().delayed_incoming_queue.empty()) { | 550 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 599 DelayedRunTimeQueue::iterator next_task = | 551 DelayedRunTimeQueue::iterator next_task = |
| 600 main_thread_only().delayed_incoming_queue.begin(); | 552 main_thread_only().delayed_incoming_queue.begin(); |
| 601 if (next_task->delayed_run_time > lazy_now->Now()) | 553 if (next_task->delayed_run_time > lazy_now->Now()) |
| 602 break; | 554 break; |
| 603 // TODO(alexclarke): Use extract() when C++17 is allowed. | 555 // TODO(alexclarke): Use extract() when C++17 is allowed. |
| 604 Task& task = const_cast<Task&>(*next_task); | 556 Task& task = const_cast<Task&>(*next_task); |
| 605 task.set_enqueue_order( | 557 task.set_enqueue_order( |
| 606 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 558 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
| 607 main_thread_only().delayed_work_queue->Push(std::move(task)); | 559 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 608 main_thread_only().delayed_incoming_queue.erase(next_task); | 560 main_thread_only().delayed_incoming_queue.erase(next_task); |
| 609 } | 561 } |
| 610 } | 562 } |
| 611 | 563 |
| 612 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 564 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { |
| 613 bool should_trigger_wakeup, | |
| 614 const Task* previous_task) { | |
| 615 if (!main_thread_only().task_queue_manager) | 565 if (!main_thread_only().task_queue_manager) |
| 616 return; | 566 return; |
| 617 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | |
| 618 return; | |
| 619 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 567 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
| 620 TraceQueueSize(false); | 568 TraceQueueSize(false); |
| 621 } | 569 } |
| 622 | 570 |
| 623 void TaskQueueImpl::UpdateImmediateWorkQueue(bool should_trigger_wakeup, | 571 void TaskQueueImpl::UpdateImmediateWorkQueue() { |
| 624 const Task* previous_task) { | |
| 625 DCHECK(main_thread_only().immediate_work_queue->Empty()); | 572 DCHECK(main_thread_only().immediate_work_queue->Empty()); |
| 626 base::AutoLock lock(any_thread_lock_); | 573 base::AutoLock lock(any_thread_lock_); |
| 627 if (!main_thread_only().task_queue_manager) | 574 if (!main_thread_only().task_queue_manager) |
| 628 return; | 575 return; |
| 629 if (!ShouldAutoPumpImmediateQueueLocked(should_trigger_wakeup, previous_task)) | |
| 630 return; | |
| 631 | 576 |
| 632 main_thread_only().immediate_work_queue->SwapLocked( | 577 main_thread_only().immediate_work_queue->SwapLocked( |
| 633 any_thread().immediate_incoming_queue); | 578 any_thread().immediate_incoming_queue); |
| 634 | 579 |
| 635 // |any_thread().immediate_incoming_queue| is now empty so | 580 // |any_thread().immediate_incoming_queue| is now empty so |
| 636 // TimeDomain::UpdateQueues no longer needs to consider this queue for | 581 // TimeDomain::UpdateQueues no longer needs to consider this queue for |
| 637 // reloading. | 582 // reloading. |
| 638 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 583 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
| 639 } | 584 } |
| 640 | 585 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 656 any_thread_lock_.AssertAcquired(); | 601 any_thread_lock_.AssertAcquired(); |
| 657 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), | 602 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), |
| 658 any_thread().immediate_incoming_queue.size() + | 603 any_thread().immediate_incoming_queue.size() + |
| 659 main_thread_only().immediate_work_queue->Size() + | 604 main_thread_only().immediate_work_queue->Size() + |
| 660 main_thread_only().delayed_work_queue->Size() + | 605 main_thread_only().delayed_work_queue->Size() + |
| 661 main_thread_only().delayed_incoming_queue.size()); | 606 main_thread_only().delayed_incoming_queue.size()); |
| 662 if (!is_locked) | 607 if (!is_locked) |
| 663 any_thread_lock_.Release(); | 608 any_thread_lock_.Release(); |
| 664 } | 609 } |
| 665 | 610 |
| 666 void TaskQueueImpl::SetPumpPolicy(PumpPolicy pump_policy) { | |
| 667 base::AutoLock lock(any_thread_lock_); | |
| 668 if (pump_policy == PumpPolicy::AUTO && | |
| 669 any_thread().pump_policy != PumpPolicy::AUTO) { | |
| 670 LazyNow lazy_now(main_thread_only().time_domain->CreateLazyNow()); | |
| 671 PumpQueueLocked(&lazy_now, true); | |
| 672 } | |
| 673 any_thread().pump_policy = pump_policy; | |
| 674 main_thread_only().pump_policy = pump_policy; | |
| 675 } | |
| 676 | |
| 677 TaskQueue::PumpPolicy TaskQueueImpl::GetPumpPolicy() const { | |
| 678 return main_thread_only().pump_policy; | |
| 679 } | |
| 680 | |
| 681 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { | |
| 682 TRACE_EVENT1(disabled_by_default_tracing_category_, | |
| 683 "TaskQueueImpl::PumpQueueLocked", "queue", name_); | |
| 684 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; | |
| 685 if (!task_queue_manager) | |
| 686 return; | |
| 687 | |
| 688 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | |
| 689 | |
| 690 while (!any_thread().immediate_incoming_queue.empty()) { | |
| 691 ComparatorQueue::iterator it = | |
| 692 any_thread().immediate_incoming_queue.begin(); | |
| 693 main_thread_only().immediate_work_queue->Push( | |
| 694 std::move(const_cast<Task&>(*it))); | |
| 695 any_thread().immediate_incoming_queue.erase(it); | |
| 696 } | |
| 697 | |
| 698 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no | |
| 699 // longer needs to consider this queue for reloading. | |
| 700 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | |
| 701 | |
| 702 if (main_thread_only().immediate_work_queue->Empty() && | |
| 703 main_thread_only().delayed_work_queue->Empty()) { | |
| 704 return; | |
| 705 } | |
| 706 | |
| 707 if (may_post_dowork) | |
| 708 task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | |
| 709 } | |
| 710 | |
| 711 void TaskQueueImpl::PumpQueue(LazyNow* lazy_now, bool may_post_dowork) { | |
| 712 base::AutoLock lock(any_thread_lock_); | |
| 713 PumpQueueLocked(lazy_now, may_post_dowork); | |
| 714 } | |
| 715 | |
| 716 const char* TaskQueueImpl::GetName() const { | 611 const char* TaskQueueImpl::GetName() const { |
| 717 return name_; | 612 return name_; |
| 718 } | 613 } |
| 719 | 614 |
| 720 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { | 615 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { |
| 721 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) | 616 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) |
| 722 return; | 617 return; |
| 723 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, | 618 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, |
| 724 priority); | 619 priority); |
| 725 } | 620 } |
| 726 | 621 |
| 727 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 622 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
| 728 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 623 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
| 729 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 624 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
| 730 return static_cast<TaskQueue::QueuePriority>(set_index); | 625 return static_cast<TaskQueue::QueuePriority>(set_index); |
| 731 } | 626 } |
| 732 | 627 |
| 733 // static | 628 // static |
| 734 const char* TaskQueueImpl::PumpPolicyToString( | |
| 735 TaskQueue::PumpPolicy pump_policy) { | |
| 736 switch (pump_policy) { | |
| 737 case TaskQueue::PumpPolicy::AUTO: | |
| 738 return "auto"; | |
| 739 case TaskQueue::PumpPolicy::AFTER_WAKEUP: | |
| 740 return "after_wakeup"; | |
| 741 case TaskQueue::PumpPolicy::MANUAL: | |
| 742 return "manual"; | |
| 743 default: | |
| 744 NOTREACHED(); | |
| 745 return nullptr; | |
| 746 } | |
| 747 } | |
| 748 | |
| 749 // static | |
| 750 const char* TaskQueueImpl::WakeupPolicyToString( | |
| 751 TaskQueue::WakeupPolicy wakeup_policy) { | |
| 752 switch (wakeup_policy) { | |
| 753 case TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES: | |
| 754 return "can_wake_other_queues"; | |
| 755 case TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES: | |
| 756 return "dont_wake_other_queues"; | |
| 757 default: | |
| 758 NOTREACHED(); | |
| 759 return nullptr; | |
| 760 } | |
| 761 } | |
| 762 | |
| 763 // static | |
| 764 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { | 629 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { |
| 765 switch (priority) { | 630 switch (priority) { |
| 766 case CONTROL_PRIORITY: | 631 case CONTROL_PRIORITY: |
| 767 return "control"; | 632 return "control"; |
| 768 case HIGH_PRIORITY: | 633 case HIGH_PRIORITY: |
| 769 return "high"; | 634 return "high"; |
| 770 case NORMAL_PRIORITY: | 635 case NORMAL_PRIORITY: |
| 771 return "normal"; | 636 return "normal"; |
| 772 case BEST_EFFORT_PRIORITY: | 637 case BEST_EFFORT_PRIORITY: |
| 773 return "best_effort"; | 638 return "best_effort"; |
| 774 default: | 639 default: |
| 775 NOTREACHED(); | 640 NOTREACHED(); |
| 776 return nullptr; | 641 return nullptr; |
| 777 } | 642 } |
| 778 } | 643 } |
| 779 | 644 |
| 780 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 645 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
| 781 base::AutoLock lock(any_thread_lock_); | 646 base::AutoLock lock(any_thread_lock_); |
| 782 state->BeginDictionary(); | 647 state->BeginDictionary(); |
| 783 state->SetString("name", GetName()); | 648 state->SetString("name", GetName()); |
| 784 state->SetBoolean("enabled", main_thread_only().is_enabled); | 649 state->SetBoolean("enabled", main_thread_only().is_enabled); |
| 785 state->SetString("time_domain_name", | 650 state->SetString("time_domain_name", |
| 786 main_thread_only().time_domain->GetName()); | 651 main_thread_only().time_domain->GetName()); |
| 787 state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy)); | |
| 788 state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_)); | |
| 789 bool verbose_tracing_enabled = false; | 652 bool verbose_tracing_enabled = false; |
| 790 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 653 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
| 791 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 654 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |
| 792 state->SetInteger("immediate_incoming_queue_size", | 655 state->SetInteger("immediate_incoming_queue_size", |
| 793 any_thread().immediate_incoming_queue.size()); | 656 any_thread().immediate_incoming_queue.size()); |
| 794 state->SetInteger("delayed_incoming_queue_size", | 657 state->SetInteger("delayed_incoming_queue_size", |
| 795 main_thread_only().delayed_incoming_queue.size()); | 658 main_thread_only().delayed_incoming_queue.size()); |
| 796 state->SetInteger("immediate_work_queue_size", | 659 state->SetInteger("immediate_work_queue_size", |
| 797 main_thread_only().immediate_work_queue->Size()); | 660 main_thread_only().immediate_work_queue->Size()); |
| 798 state->SetInteger("delayed_work_queue_size", | 661 state->SetInteger("delayed_work_queue_size", |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 | 740 |
| 878 base::AutoLock lock(any_thread_lock_); | 741 base::AutoLock lock(any_thread_lock_); |
| 879 return any_thread().time_domain; | 742 return any_thread().time_domain; |
| 880 } | 743 } |
| 881 | 744 |
| 882 void TaskQueueImpl::SetBlameContext( | 745 void TaskQueueImpl::SetBlameContext( |
| 883 base::trace_event::BlameContext* blame_context) { | 746 base::trace_event::BlameContext* blame_context) { |
| 884 main_thread_only().blame_context = blame_context; | 747 main_thread_only().blame_context = blame_context; |
| 885 } | 748 } |
| 886 | 749 |
| 750 EnqueueOrder TaskQueueImpl::GetNewestImmediateTaskEnqueueOrder() const { |
| 751 base::AutoLock lock(any_thread_lock_); |
| 752 if (!any_thread().immediate_incoming_queue.empty()) |
| 753 return any_thread().immediate_incoming_queue.rbegin()->enqueue_order(); |
| 754 const Task* task = main_thread_only().immediate_work_queue->GetBackTask(); |
| 755 if (task) |
| 756 return task->enqueue_order(); |
| 757 return 0; |
| 758 } |
| 759 |
| 760 EnqueueOrder TaskQueueImpl::GetNewestReadyDelayedTaskEnqueueOrder() { |
| 761 LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow(); |
| 762 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); |
| 763 const Task* task = main_thread_only().delayed_work_queue->GetBackTask(); |
| 764 if (task) |
| 765 return task->enqueue_order(); |
| 766 return 0; |
| 767 } |
| 768 |
| 769 void TaskQueueImpl::InsertFence() { |
| 770 if (!main_thread_only().task_queue_manager) |
| 771 return; |
| 772 |
| 773 EnqueueOrder next_immediate = GetNewestImmediateTaskEnqueueOrder(); |
| 774 EnqueueOrder next_delayed = GetNewestReadyDelayedTaskEnqueueOrder(); |
| 775 |
| 776 bool task_unblocked = |
| 777 main_thread_only().immediate_work_queue->InsertFence(next_immediate); |
| 778 task_unblocked |= |
| 779 main_thread_only().delayed_work_queue->InsertFence(next_delayed); |
| 780 |
| 781 if (!task_unblocked) |
| 782 task_unblocked |= HasPendingImmediateWork(); |
| 783 |
| 784 if (main_thread_only().is_enabled && task_unblocked) { |
| 785 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 786 FROM_HERE); |
| 787 } |
| 788 } |
| 789 |
| 790 void TaskQueueImpl::RemoveFence() { |
| 791 if (!main_thread_only().task_queue_manager) |
| 792 return; |
| 793 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 794 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 795 |
| 796 if (!task_unblocked) |
| 797 task_unblocked |= HasPendingImmediateWork(); |
| 798 |
| 799 if (main_thread_only().is_enabled && task_unblocked) { |
| 800 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 801 FROM_HERE); |
| 802 } |
| 803 } |
| 804 |
| 805 bool TaskQueueImpl::BlockedByFence() const { |
| 806 return main_thread_only().immediate_work_queue->fence_hit() && |
| 807 main_thread_only().delayed_work_queue->fence_hit(); |
| 808 } |
| 809 |
| 887 // static | 810 // static |
| 888 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, | 811 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
| 889 base::trace_event::TracedValue* state) { | 812 base::trace_event::TracedValue* state) { |
| 890 for (const Task& task : queue) { | 813 for (const Task& task : queue) { |
| 891 TaskAsValueInto(task, state); | 814 TaskAsValueInto(task, state); |
| 892 } | 815 } |
| 893 } | 816 } |
| 894 | 817 |
| 895 // static | 818 // static |
| 896 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, | 819 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 916 state->SetBoolean("is_high_res", task.is_high_res); | 839 state->SetBoolean("is_high_res", task.is_high_res); |
| 917 state->SetDouble( | 840 state->SetDouble( |
| 918 "delayed_run_time", | 841 "delayed_run_time", |
| 919 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 842 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 920 state->EndDictionary(); | 843 state->EndDictionary(); |
| 921 } | 844 } |
| 922 | 845 |
| 923 } // namespace internal | 846 } // namespace internal |
| 924 } // namespace scheduler | 847 } // namespace scheduler |
| 925 } // namespace blink | 848 } // namespace blink |
| OLD | NEW |