Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: content/child/scheduler/task_queue_manager.cc

Issue 1072473002: Speculative patch: Make it safe to delete the TQM inside a Task (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: responding to feedback Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/child/scheduler/task_queue_manager.h ('k') | content/child/scheduler/task_queue_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698