| 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/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/trace_event/blame_context.h" | 10 #include "base/trace_event/blame_context.h" |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 275 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
| 276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); |
| 277 | 277 |
| 278 // If |pending_task| is at the head of the queue, then make sure a wakeup | 278 // If |pending_task| is at the head of the queue, then make sure a wakeup |
| 279 // is requested if the queue is enabled. Note we still want to schedule a | 279 // is requested if the queue is enabled. Note we still want to schedule a |
| 280 // wakeup even if blocked by a fence, because we'd break throttling logic | 280 // wakeup even if blocked by a fence, because we'd break throttling logic |
| 281 // otherwise. | 281 // otherwise. |
| 282 base::TimeTicks next_delayed_task = | 282 base::TimeTicks next_delayed_task = |
| 283 main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 283 main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 284 if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { | 284 if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { |
| 285 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 285 main_thread_only().time_domain->ScheduleDelayedWork( |
| 286 now); | 286 this, delayed_run_time, pending_task.sequence_num, now); |
| 287 } | 287 } |
| 288 | 288 |
| 289 TraceQueueSize(false); | 289 TraceQueueSize(false); |
| 290 } | 290 } |
| 291 | 291 |
| 292 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 292 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 293 any_thread().task_queue_manager->DidQueueTask(pending_task); | 293 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 294 | 294 |
| 295 int thread_hop_task_sequence_number = | 295 int thread_hop_task_sequence_number = |
| 296 any_thread().task_queue_manager->GetNextSequenceNumber(); | 296 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 308 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 308 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 309 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 309 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
| 310 if (delayed_run_time <= time_domain_now) { | 310 if (delayed_run_time <= time_domain_now) { |
| 311 // If |delayed_run_time| is in the past then push it onto the work queue | 311 // If |delayed_run_time| is in the past then push it onto the work queue |
| 312 // immediately. To ensure the right task ordering we need to temporarily | 312 // immediately. To ensure the right task ordering we need to temporarily |
| 313 // push it onto the |delayed_incoming_queue|. | 313 // push it onto the |delayed_incoming_queue|. |
| 314 delayed_run_time = time_domain_now; | 314 delayed_run_time = time_domain_now; |
| 315 pending_task.delayed_run_time = time_domain_now; | 315 pending_task.delayed_run_time = time_domain_now; |
| 316 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 316 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); |
| 317 LazyNow lazy_now(time_domain_now); | 317 LazyNow lazy_now(time_domain_now); |
| 318 WakeUpForDelayedWork(&lazy_now); | 318 base::TimeTicks ignored_next_wake_up_time; |
| 319 int ignored_next_wake_up_sequence_num; |
| 320 WakeUpForDelayedWork(&lazy_now, &ignored_next_wake_up_time, |
| 321 &ignored_next_wake_up_sequence_num); |
| 319 } else { | 322 } else { |
| 320 // If |delayed_run_time| is in the future we can queue it as normal. | 323 // If |delayed_run_time| is in the future we can queue it as normal. |
| 321 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), | 324 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), |
| 322 time_domain_now); | 325 time_domain_now); |
| 323 } | 326 } |
| 324 TraceQueueSize(false); | 327 TraceQueueSize(false); |
| 325 } | 328 } |
| 326 | 329 |
| 327 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 330 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( |
| 328 const tracked_objects::Location& posted_from, | 331 const tracked_objects::Location& posted_from, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 } | 410 } |
| 408 | 411 |
| 409 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { | 412 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { |
| 410 // Note we don't scheduled a wakeup for disabled queues. | 413 // Note we don't scheduled a wakeup for disabled queues. |
| 411 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) | 414 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) |
| 412 return base::nullopt; | 415 return base::nullopt; |
| 413 | 416 |
| 414 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 417 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 415 } | 418 } |
| 416 | 419 |
| 417 base::Optional<base::TimeTicks> TaskQueueImpl::WakeUpForDelayedWork( | 420 bool TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now, |
| 418 LazyNow* lazy_now) { | 421 base::TimeTicks* out_next_wake_up_time, |
| 422 int* out_next_wake_up_sequence_num) { |
| 419 // Enqueue all delayed tasks that should be running now, skipping any that | 423 // Enqueue all delayed tasks that should be running now, skipping any that |
| 420 // have been canceled. | 424 // have been canceled. |
| 421 while (!main_thread_only().delayed_incoming_queue.empty()) { | 425 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 422 Task& task = | 426 Task& task = |
| 423 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); | 427 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); |
| 424 if (task.task.IsCancelled()) { | 428 if (task.task.IsCancelled()) { |
| 425 main_thread_only().delayed_incoming_queue.pop(); | 429 main_thread_only().delayed_incoming_queue.pop(); |
| 426 continue; | 430 continue; |
| 427 } | 431 } |
| 428 if (task.delayed_run_time > lazy_now->Now()) | 432 if (task.delayed_run_time > lazy_now->Now()) |
| 429 break; | 433 break; |
| 430 task.set_enqueue_order( | 434 task.set_enqueue_order( |
| 431 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 435 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
| 432 main_thread_only().delayed_work_queue->Push(std::move(task)); | 436 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 433 main_thread_only().delayed_incoming_queue.pop(); | 437 main_thread_only().delayed_incoming_queue.pop(); |
| 434 } | 438 } |
| 435 | 439 |
| 436 // Make sure the next wake up is scheduled. | 440 // Make sure the next wake up is scheduled. |
| 437 if (!main_thread_only().delayed_incoming_queue.empty()) | 441 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 438 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 442 *out_next_wake_up_time = |
| 443 main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 444 *out_next_wake_up_sequence_num = |
| 445 main_thread_only().delayed_incoming_queue.top().sequence_num; |
| 446 return true; |
| 447 } |
| 439 | 448 |
| 440 return base::nullopt; | 449 return false; |
| 441 } | 450 } |
| 442 | 451 |
| 443 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { | 452 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { |
| 444 bool is_tracing; | 453 bool is_tracing; |
| 445 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, | 454 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, |
| 446 &is_tracing); | 455 &is_tracing); |
| 447 if (!is_tracing) | 456 if (!is_tracing) |
| 448 return; | 457 return; |
| 449 | 458 |
| 450 // It's only safe to access the work queues from the main thread. | 459 // It's only safe to access the work queues from the main thread. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 any_thread().time_domain = time_domain; | 590 any_thread().time_domain = time_domain; |
| 582 } | 591 } |
| 583 | 592 |
| 584 main_thread_only().time_domain->UnregisterQueue(this); | 593 main_thread_only().time_domain->UnregisterQueue(this); |
| 585 main_thread_only().time_domain = time_domain; | 594 main_thread_only().time_domain = time_domain; |
| 586 time_domain->RegisterQueue(this); | 595 time_domain->RegisterQueue(this); |
| 587 | 596 |
| 588 if (IsQueueEnabled() && !main_thread_only().delayed_incoming_queue.empty()) { | 597 if (IsQueueEnabled() && !main_thread_only().delayed_incoming_queue.empty()) { |
| 589 time_domain->ScheduleDelayedWork( | 598 time_domain->ScheduleDelayedWork( |
| 590 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 599 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 600 main_thread_only().delayed_incoming_queue.top().sequence_num, |
| 591 time_domain->Now()); | 601 time_domain->Now()); |
| 592 } | 602 } |
| 593 } | 603 } |
| 594 | 604 |
| 595 TimeDomain* TaskQueueImpl::GetTimeDomain() const { | 605 TimeDomain* TaskQueueImpl::GetTimeDomain() const { |
| 596 if (base::PlatformThread::CurrentId() == thread_id_) | 606 if (base::PlatformThread::CurrentId() == thread_id_) |
| 597 return main_thread_only().time_domain; | 607 return main_thread_only().time_domain; |
| 598 | 608 |
| 599 base::AutoLock lock(any_thread_lock_); | 609 base::AutoLock lock(any_thread_lock_); |
| 600 return any_thread().time_domain; | 610 return any_thread().time_domain; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); | 821 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); |
| 812 } | 822 } |
| 813 // Avoid holding the lock while we fire the notification. | 823 // Avoid holding the lock while we fire the notification. |
| 814 if (!immediate_queues_empty) | 824 if (!immediate_queues_empty) |
| 815 main_thread_only().time_domain->OnQueueHasImmediateWork(this); | 825 main_thread_only().time_domain->OnQueueHasImmediateWork(this); |
| 816 | 826 |
| 817 if (!main_thread_only().delayed_incoming_queue.empty()) { | 827 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 818 main_thread_only().time_domain->ScheduleDelayedWork( | 828 main_thread_only().time_domain->ScheduleDelayedWork( |
| 819 this, | 829 this, |
| 820 main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 830 main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 831 main_thread_only().delayed_incoming_queue.top().sequence_num, |
| 821 main_thread_only().time_domain->Now()); | 832 main_thread_only().time_domain->Now()); |
| 822 } | 833 } |
| 823 // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts | 834 // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts |
| 824 // a DoWork if needed. | 835 // a DoWork if needed. |
| 825 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 836 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| 826 } else { | 837 } else { |
| 827 if (!main_thread_only().delayed_incoming_queue.empty()) | 838 if (!main_thread_only().delayed_incoming_queue.empty()) |
| 828 main_thread_only().time_domain->CancelDelayedWork(this); | 839 main_thread_only().time_domain->CancelDelayedWork(this); |
| 829 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 840 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
| 830 } | 841 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 858 | 869 |
| 859 // Re-schedule delayed call to WakeUpForDelayedWork if needed. | 870 // Re-schedule delayed call to WakeUpForDelayedWork if needed. |
| 860 if (main_thread_only().delayed_incoming_queue.empty()) { | 871 if (main_thread_only().delayed_incoming_queue.empty()) { |
| 861 main_thread_only().time_domain->CancelDelayedWork(this); | 872 main_thread_only().time_domain->CancelDelayedWork(this); |
| 862 } else if (first_task_runtime != | 873 } else if (first_task_runtime != |
| 863 main_thread_only().delayed_incoming_queue.top().delayed_run_time) { | 874 main_thread_only().delayed_incoming_queue.top().delayed_run_time) { |
| 864 if (IsQueueEnabled()) { | 875 if (IsQueueEnabled()) { |
| 865 main_thread_only().time_domain->ScheduleDelayedWork( | 876 main_thread_only().time_domain->ScheduleDelayedWork( |
| 866 this, | 877 this, |
| 867 main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 878 main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 879 main_thread_only().delayed_incoming_queue.top().sequence_num, |
| 868 main_thread_only().time_domain->Now()); | 880 main_thread_only().time_domain->Now()); |
| 869 } | 881 } |
| 870 } | 882 } |
| 871 } | 883 } |
| 872 | 884 |
| 873 void TaskQueueImpl::PushImmediateIncomingTaskForTest( | 885 void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
| 874 TaskQueueImpl::Task&& task) { | 886 TaskQueueImpl::Task&& task) { |
| 875 base::AutoLock lock(any_thread_lock_); | 887 base::AutoLock lock(any_thread_lock_); |
| 876 any_thread().immediate_incoming_queue.push_back(std::move(task)); | 888 any_thread().immediate_incoming_queue.push_back(std::move(task)); |
| 877 } | 889 } |
| 878 | 890 |
| 879 } // namespace internal | 891 } // namespace internal |
| 880 } // namespace scheduler | 892 } // namespace scheduler |
| 881 } // namespace blink | 893 } // namespace blink |
| OLD | NEW |