| 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 "components/scheduler/base/task_queue_manager.h" | 5 #include "components/scheduler/base/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" |
| 11 #include "components/scheduler/base/real_time_domain.h" | 11 #include "components/scheduler/base/real_time_domain.h" |
| 12 #include "components/scheduler/base/task_queue_impl.h" | 12 #include "components/scheduler/base/task_queue_impl.h" |
| 13 #include "components/scheduler/base/task_queue_manager_delegate.h" | 13 #include "components/scheduler/base/task_queue_manager_delegate.h" |
| 14 #include "components/scheduler/base/task_queue_selector.h" | 14 #include "components/scheduler/base/task_queue_selector.h" |
| 15 #include "components/scheduler/base/task_queue_sets.h" | 15 #include "components/scheduler/base/task_queue_sets.h" |
| 16 | 16 |
| 17 namespace scheduler { | 17 namespace scheduler { |
| 18 | 18 |
| 19 TaskQueueManager::TaskQueueManager( | 19 TaskQueueManager::TaskQueueManager( |
| 20 scoped_refptr<TaskQueueManagerDelegate> delegate, | 20 scoped_refptr<TaskQueueManagerDelegate> delegate, |
| 21 const char* tracing_category, | 21 const char* tracing_category, |
| 22 const char* disabled_by_default_tracing_category, | 22 const char* disabled_by_default_tracing_category, |
| 23 const char* disabled_by_default_verbose_tracing_category) | 23 const char* disabled_by_default_verbose_tracing_category) |
| 24 : delegate_(delegate), | 24 : real_time_domain_(new RealTimeDomain()), |
| 25 delegate_(delegate), |
| 25 task_was_run_on_quiescence_monitored_queue_(false), | 26 task_was_run_on_quiescence_monitored_queue_(false), |
| 26 pending_dowork_count_(0), | 27 pending_dowork_count_(0), |
| 27 work_batch_size_(1), | 28 work_batch_size_(1), |
| 28 tracing_category_(tracing_category), | 29 tracing_category_(tracing_category), |
| 29 disabled_by_default_tracing_category_( | 30 disabled_by_default_tracing_category_( |
| 30 disabled_by_default_tracing_category), | 31 disabled_by_default_tracing_category), |
| 31 disabled_by_default_verbose_tracing_category_( | 32 disabled_by_default_verbose_tracing_category_( |
| 32 disabled_by_default_verbose_tracing_category), | 33 disabled_by_default_verbose_tracing_category), |
| 33 observer_(nullptr), | 34 observer_(nullptr), |
| 34 deletion_sentinel_(new DeletionSentinel()), | 35 deletion_sentinel_(new DeletionSentinel()), |
| 35 weak_factory_(this) { | 36 weak_factory_(this) { |
| 36 DCHECK(delegate->RunsTasksOnCurrentThread()); | 37 DCHECK(delegate->RunsTasksOnCurrentThread()); |
| 37 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, | 38 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, |
| 38 "TaskQueueManager", this); | 39 "TaskQueueManager", this); |
| 39 selector_.SetTaskQueueSelectorObserver(this); | 40 selector_.SetTaskQueueSelectorObserver(this); |
| 40 | 41 |
| 41 decrement_pending_and_do_work_closure_ = | 42 decrement_pending_and_do_work_closure_ = |
| 42 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), true); | 43 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), true); |
| 43 do_work_closure_ = | 44 do_work_closure_ = |
| 44 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), false); | 45 base::Bind(&TaskQueueManager::DoWork, weak_factory_.GetWeakPtr(), false); |
| 45 | 46 |
| 46 // TODO(alexclarke): Change this to be a parameter that's passed in. | 47 // TODO(alexclarke): Change this to be a parameter that's passed in. |
| 47 real_time_domain_ = make_scoped_refptr(new RealTimeDomain()); | 48 RegisterTimeDomain(real_time_domain_.get()); |
| 48 RegisterTimeDomain(real_time_domain_); | |
| 49 } | 49 } |
| 50 | 50 |
| 51 TaskQueueManager::~TaskQueueManager() { | 51 TaskQueueManager::~TaskQueueManager() { |
| 52 TRACE_EVENT_OBJECT_DELETED_WITH_ID(disabled_by_default_tracing_category_, | 52 TRACE_EVENT_OBJECT_DELETED_WITH_ID(disabled_by_default_tracing_category_, |
| 53 "TaskQueueManager", this); | 53 "TaskQueueManager", this); |
| 54 | 54 |
| 55 while (!queues_.empty()) | 55 while (!queues_.empty()) |
| 56 (*queues_.begin())->UnregisterTaskQueue(); | 56 (*queues_.begin())->UnregisterTaskQueue(); |
| 57 | 57 |
| 58 selector_.SetTaskQueueSelectorObserver(nullptr); | 58 selector_.SetTaskQueueSelectorObserver(nullptr); |
| 59 } | 59 } |
| 60 | 60 |
| 61 void TaskQueueManager::RegisterTimeDomain( | 61 void TaskQueueManager::RegisterTimeDomain(TimeDomain* time_domain) { |
| 62 const scoped_refptr<TimeDomain>& time_domain) { | |
| 63 time_domains_.insert(time_domain); | 62 time_domains_.insert(time_domain); |
| 64 time_domain->OnRegisterWithTaskQueueManager(delegate_.get(), | 63 time_domain->OnRegisterWithTaskQueueManager(delegate_.get(), |
| 65 do_work_closure_); | 64 do_work_closure_); |
| 66 } | 65 } |
| 67 | 66 |
| 68 void TaskQueueManager::UnregisterTimeDomain( | 67 void TaskQueueManager::UnregisterTimeDomain(TimeDomain* time_domain) { |
| 69 const scoped_refptr<TimeDomain>& time_domain) { | |
| 70 time_domains_.erase(time_domain); | 68 time_domains_.erase(time_domain); |
| 71 } | 69 } |
| 72 | 70 |
| 73 scoped_refptr<internal::TaskQueueImpl> TaskQueueManager::NewTaskQueue( | 71 scoped_refptr<internal::TaskQueueImpl> TaskQueueManager::NewTaskQueue( |
| 74 const TaskQueue::Spec& spec) { | 72 const TaskQueue::Spec& spec) { |
| 75 TRACE_EVENT1(tracing_category_, | 73 TRACE_EVENT1(tracing_category_, |
| 76 "TaskQueueManager::NewTaskQueue", "queue_name", spec.name); | 74 "TaskQueueManager::NewTaskQueue", "queue_name", spec.name); |
| 77 DCHECK(main_thread_checker_.CalledOnValidThread()); | 75 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 78 TimeDomain* time_domain = | 76 TimeDomain* time_domain = |
| 79 spec.time_domain ? spec.time_domain : real_time_domain_.get(); | 77 spec.time_domain ? spec.time_domain : real_time_domain_.get(); |
| 80 DCHECK(time_domains_.find(make_scoped_refptr(time_domain)) != | 78 DCHECK(time_domains_.find(time_domain) != time_domains_.end()); |
| 81 time_domains_.end()); | |
| 82 scoped_refptr<internal::TaskQueueImpl> queue( | 79 scoped_refptr<internal::TaskQueueImpl> queue( |
| 83 make_scoped_refptr(new internal::TaskQueueImpl( | 80 make_scoped_refptr(new internal::TaskQueueImpl( |
| 84 this, time_domain, spec, disabled_by_default_tracing_category_, | 81 this, time_domain, spec, disabled_by_default_tracing_category_, |
| 85 disabled_by_default_verbose_tracing_category_))); | 82 disabled_by_default_verbose_tracing_category_))); |
| 86 queues_.insert(queue); | 83 queues_.insert(queue); |
| 87 selector_.AddQueue(queue.get()); | 84 selector_.AddQueue(queue.get()); |
| 88 return queue; | 85 return queue; |
| 89 } | 86 } |
| 90 | 87 |
| 91 void TaskQueueManager::SetObserver(Observer* observer) { | 88 void TaskQueueManager::SetObserver(Observer* observer) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 108 queues_.erase(task_queue); | 105 queues_.erase(task_queue); |
| 109 selector_.RemoveQueue(task_queue.get()); | 106 selector_.RemoveQueue(task_queue.get()); |
| 110 } | 107 } |
| 111 | 108 |
| 112 void TaskQueueManager::UpdateWorkQueues( | 109 void TaskQueueManager::UpdateWorkQueues( |
| 113 bool should_trigger_wakeup, | 110 bool should_trigger_wakeup, |
| 114 const internal::TaskQueueImpl::Task* previous_task) { | 111 const internal::TaskQueueImpl::Task* previous_task) { |
| 115 TRACE_EVENT0(disabled_by_default_tracing_category_, | 112 TRACE_EVENT0(disabled_by_default_tracing_category_, |
| 116 "TaskQueueManager::UpdateWorkQueues"); | 113 "TaskQueueManager::UpdateWorkQueues"); |
| 117 | 114 |
| 118 for (const scoped_refptr<TimeDomain>& time_domain : time_domains_) { | 115 for (TimeDomain* time_domain : time_domains_) { |
| 119 time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task); | 116 time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task); |
| 120 } | 117 } |
| 121 } | 118 } |
| 122 | 119 |
| 123 void TaskQueueManager::MaybePostDoWorkOnMainRunner() { | 120 void TaskQueueManager::MaybePostDoWorkOnMainRunner() { |
| 124 bool on_main_thread = delegate_->BelongsToCurrentThread(); | 121 bool on_main_thread = delegate_->BelongsToCurrentThread(); |
| 125 if (on_main_thread) { | 122 if (on_main_thread) { |
| 126 // We only want one pending DoWork posted from the main thread, or we risk | 123 // We only want one pending DoWork posted from the main thread, or we risk |
| 127 // an explosion of pending DoWorks which could starve out everything else. | 124 // an explosion of pending DoWorks which could starve out everything else. |
| 128 if (pending_dowork_count_ > 0) { | 125 if (pending_dowork_count_ > 0) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 if (!selector_.EnabledWorkQueuesEmpty() || TryAdvanceTimeDomains()) { | 179 if (!selector_.EnabledWorkQueuesEmpty() || TryAdvanceTimeDomains()) { |
| 183 MaybePostDoWorkOnMainRunner(); | 180 MaybePostDoWorkOnMainRunner(); |
| 184 } else { | 181 } else { |
| 185 // Tell the task runner we have no more work. | 182 // Tell the task runner we have no more work. |
| 186 delegate_->OnNoMoreImmediateWork(); | 183 delegate_->OnNoMoreImmediateWork(); |
| 187 } | 184 } |
| 188 } | 185 } |
| 189 | 186 |
| 190 bool TaskQueueManager::TryAdvanceTimeDomains() { | 187 bool TaskQueueManager::TryAdvanceTimeDomains() { |
| 191 bool can_advance = false; | 188 bool can_advance = false; |
| 192 for (const scoped_refptr<TimeDomain>& time_domain : time_domains_) { | 189 for (TimeDomain* time_domain : time_domains_) { |
| 193 can_advance |= time_domain->MaybeAdvanceTime(); | 190 can_advance |= time_domain->MaybeAdvanceTime(); |
| 194 } | 191 } |
| 195 return can_advance; | 192 return can_advance; |
| 196 } | 193 } |
| 197 | 194 |
| 198 bool TaskQueueManager::SelectQueueToService( | 195 bool TaskQueueManager::SelectQueueToService( |
| 199 internal::TaskQueueImpl** out_queue) { | 196 internal::TaskQueueImpl** out_queue) { |
| 200 bool should_run = selector_.SelectQueueToService(out_queue); | 197 bool should_run = selector_.SelectQueueToService(out_queue); |
| 201 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 198 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 202 disabled_by_default_tracing_category_, "TaskQueueManager", this, | 199 disabled_by_default_tracing_category_, "TaskQueueManager", this, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 } | 315 } |
| 319 | 316 |
| 320 void TaskQueueManager::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) { | 317 void TaskQueueManager::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) { |
| 321 DCHECK(main_thread_checker_.CalledOnValidThread()); | 318 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 322 // Only schedule DoWork if there's something to do. | 319 // Only schedule DoWork if there's something to do. |
| 323 if (!queue->work_queue().empty()) | 320 if (!queue->work_queue().empty()) |
| 324 MaybePostDoWorkOnMainRunner(); | 321 MaybePostDoWorkOnMainRunner(); |
| 325 } | 322 } |
| 326 | 323 |
| 327 } // namespace scheduler | 324 } // namespace scheduler |
| OLD | NEW |