OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/child/scheduler/task_queue_manager.h" | 5 #include "content/child/scheduler/task_queue_manager.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
457 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, | 457 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, |
458 TaskQueueSelector* selector, | 458 TaskQueueSelector* selector, |
459 const char* disabled_by_default_tracing_category) | 459 const char* disabled_by_default_tracing_category) |
460 : main_task_runner_(main_task_runner), | 460 : main_task_runner_(main_task_runner), |
461 selector_(selector), | 461 selector_(selector), |
462 pending_dowork_count_(0), | 462 pending_dowork_count_(0), |
463 work_batch_size_(1), | 463 work_batch_size_(1), |
464 time_source_(nullptr), | 464 time_source_(nullptr), |
465 disabled_by_default_tracing_category_( | 465 disabled_by_default_tracing_category_( |
466 disabled_by_default_tracing_category), | 466 disabled_by_default_tracing_category), |
467 deletion_sentinel_(new DeletionSentinel()), | |
467 weak_factory_(this) { | 468 weak_factory_(this) { |
468 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); | 469 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); |
469 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, | 470 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, |
470 "TaskQueueManager", this); | 471 "TaskQueueManager", this); |
471 | 472 |
472 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); | 473 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); |
473 for (size_t i = 0; i < task_queue_count; i++) { | 474 for (size_t i = 0; i < task_queue_count; i++) { |
474 scoped_refptr<internal::TaskQueue> queue(make_scoped_refptr( | 475 scoped_refptr<internal::TaskQueue> queue(make_scoped_refptr( |
475 new internal::TaskQueue(this, disabled_by_default_tracing_category))); | 476 new internal::TaskQueue(this, disabled_by_default_tracing_category))); |
476 queues_.push_back(queue); | 477 queues_.push_back(queue); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
589 | 590 |
590 base::PendingTask previous_task((tracked_objects::Location()), | 591 base::PendingTask previous_task((tracked_objects::Location()), |
591 (base::Closure())); | 592 (base::Closure())); |
592 for (int i = 0; i < work_batch_size_; i++) { | 593 for (int i = 0; i < work_batch_size_; i++) { |
593 size_t queue_index; | 594 size_t queue_index; |
594 if (!SelectWorkQueueToService(&queue_index)) | 595 if (!SelectWorkQueueToService(&queue_index)) |
595 return; | 596 return; |
596 // Note that this function won't post another call to DoWork if one is | 597 // Note that this function won't post another call to DoWork if one is |
597 // already pending, so it is safe to call it in a loop. | 598 // already pending, so it is safe to call it in a loop. |
598 MaybePostDoWorkOnMainRunner(); | 599 MaybePostDoWorkOnMainRunner(); |
599 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); | 600 |
601 if (ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task)) | |
602 return; | |
600 | 603 |
601 if (!UpdateWorkQueues(&previous_task)) | 604 if (!UpdateWorkQueues(&previous_task)) |
602 return; | 605 return; |
603 } | 606 } |
604 } | 607 } |
605 | 608 |
606 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { | 609 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { |
607 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); | 610 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); |
608 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 611 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
609 disabled_by_default_tracing_category_, "TaskQueueManager", this, | 612 disabled_by_default_tracing_category_, "TaskQueueManager", this, |
610 AsValueWithSelectorResult(should_run, *out_queue_index)); | 613 AsValueWithSelectorResult(should_run, *out_queue_index)); |
611 return should_run; | 614 return should_run; |
612 } | 615 } |
613 | 616 |
614 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { | 617 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { |
615 pending_task->sequence_num = task_sequence_num_.GetNext(); | 618 pending_task->sequence_num = task_sequence_num_.GetNext(); |
616 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); | 619 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); |
617 } | 620 } |
618 | 621 |
619 void TaskQueueManager::ProcessTaskFromWorkQueue( | 622 bool TaskQueueManager::ProcessTaskFromWorkQueue( |
620 size_t queue_index, | 623 size_t queue_index, |
621 bool has_previous_task, | 624 bool has_previous_task, |
622 base::PendingTask* previous_task) { | 625 base::PendingTask* previous_task) { |
623 DCHECK(main_thread_checker_.CalledOnValidThread()); | 626 DCHECK(main_thread_checker_.CalledOnValidThread()); |
627 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); | |
624 internal::TaskQueue* queue = Queue(queue_index); | 628 internal::TaskQueue* queue = Queue(queue_index); |
625 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 629 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
626 if (!pending_task.nestable && main_task_runner_->IsNested()) { | 630 if (!pending_task.nestable && main_task_runner_->IsNested()) { |
627 // Defer non-nestable work to the main task runner. NOTE these tasks can be | 631 // Defer non-nestable work to the main task runner. NOTE these tasks can be |
628 // arbitrarily delayed so the additional delay should not be a problem. | 632 // arbitrarily delayed so the additional delay should not be a problem. |
629 main_task_runner_->PostNonNestableTask(pending_task.posted_from, | 633 main_task_runner_->PostNonNestableTask(pending_task.posted_from, |
630 pending_task.task); | 634 pending_task.task); |
631 } else { | 635 } else { |
632 // Suppress "will" task observer notifications for the first and "did" | 636 // Suppress "will" task observer notifications for the first and "did" |
633 // notifications for the last task in the batch to avoid duplicate | 637 // notifications for the last task in the batch to avoid duplicate |
634 // notifications. | 638 // notifications. |
635 if (has_previous_task) { | 639 if (has_previous_task) { |
636 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | 640 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
637 DidProcessTask(*previous_task)); | 641 DidProcessTask(*previous_task)); |
638 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | 642 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
639 WillProcessTask(pending_task)); | 643 WillProcessTask(pending_task)); |
640 } | 644 } |
641 task_annotator_.RunTask("TaskQueueManager::PostTask", | 645 task_annotator_.RunTask("TaskQueueManager::PostTask", |
642 "TaskQueueManager::RunTask", pending_task); | 646 "TaskQueueManager::RunTask", pending_task); |
647 | |
648 // Detect if the TaskQueueManager just got deleted. | |
Sami
2015/04/08 14:45:56
Could you add a note here that we mustn't access a
alex clarke (OOO till 29th)
2015/04/08 14:59:40
Done.
| |
649 if (protect->HasOneRef()) | |
650 return true; | |
651 | |
643 pending_task.task.Reset(); | 652 pending_task.task.Reset(); |
644 *previous_task = pending_task; | 653 *previous_task = pending_task; |
645 } | 654 } |
655 return false; | |
646 } | 656 } |
647 | 657 |
648 bool TaskQueueManager::RunsTasksOnCurrentThread() const { | 658 bool TaskQueueManager::RunsTasksOnCurrentThread() const { |
649 return main_task_runner_->RunsTasksOnCurrentThread(); | 659 return main_task_runner_->RunsTasksOnCurrentThread(); |
650 } | 660 } |
651 | 661 |
652 bool TaskQueueManager::PostDelayedTask( | 662 bool TaskQueueManager::PostDelayedTask( |
653 const tracked_objects::Location& from_here, | 663 const tracked_objects::Location& from_here, |
654 const base::Closure& task, | 664 const base::Closure& task, |
655 base::TimeDelta delay) { | 665 base::TimeDelta delay) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
705 state->EndArray(); | 715 state->EndArray(); |
706 state->BeginDictionary("selector"); | 716 state->BeginDictionary("selector"); |
707 selector_->AsValueInto(state.get()); | 717 selector_->AsValueInto(state.get()); |
708 state->EndDictionary(); | 718 state->EndDictionary(); |
709 if (should_run) | 719 if (should_run) |
710 state->SetInteger("selected_queue", selected_queue); | 720 state->SetInteger("selected_queue", selected_queue); |
711 return state; | 721 return state; |
712 } | 722 } |
713 | 723 |
714 } // namespace content | 724 } // namespace content |
OLD | NEW |