Chromium Code Reviews| 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 "components/scheduler/base/task_queue_impl.h" | 5 #include "components/scheduler/base/task_queue_impl.h" |
| 6 | 6 |
| 7 #include "components/scheduler/base/task_queue_manager.h" | 7 #include "components/scheduler/base/task_queue_manager.h" |
| 8 #include "components/scheduler/base/task_queue_manager_delegate.h" | 8 #include "components/scheduler/base/task_queue_manager_delegate.h" |
| 9 #include "components/scheduler/base/time_domain.h" | 9 #include "components/scheduler/base/time_domain.h" |
| 10 | 10 |
| 11 namespace scheduler { | 11 namespace scheduler { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 TaskQueueImpl::TaskQueueImpl( | 14 TaskQueueImpl::TaskQueueImpl( |
| 15 TaskQueueManager* task_queue_manager, | 15 TaskQueueManager* task_queue_manager, |
| 16 const scoped_refptr<TimeDomain>& time_domain, | 16 TimeDomain* time_domain, |
| 17 const Spec& spec, | 17 const Spec& spec, |
| 18 const char* disabled_by_default_tracing_category, | 18 const char* disabled_by_default_tracing_category, |
| 19 const char* disabled_by_default_verbose_tracing_category) | 19 const char* disabled_by_default_verbose_tracing_category) |
| 20 : thread_id_(base::PlatformThread::CurrentId()), | 20 : thread_id_(base::PlatformThread::CurrentId()), |
| 21 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 21 any_thread_(task_queue_manager, spec.pump_policy, time_domain), |
| 22 name_(spec.name), | 22 name_(spec.name), |
| 23 disabled_by_default_tracing_category_( | 23 disabled_by_default_tracing_category_( |
| 24 disabled_by_default_tracing_category), | 24 disabled_by_default_tracing_category), |
| 25 disabled_by_default_verbose_tracing_category_( | 25 disabled_by_default_verbose_tracing_category_( |
| 26 disabled_by_default_verbose_tracing_category), | 26 disabled_by_default_verbose_tracing_category), |
| 27 main_thread_only_(task_queue_manager), | 27 main_thread_only_(task_queue_manager), |
| 28 wakeup_policy_(spec.wakeup_policy), | 28 wakeup_policy_(spec.wakeup_policy), |
| 29 should_monitor_quiescence_(spec.should_monitor_quiescence), | 29 should_monitor_quiescence_(spec.should_monitor_quiescence), |
| 30 should_notify_observers_(spec.should_notify_observers) { | 30 should_notify_observers_(spec.should_notify_observers) { |
| 31 DCHECK(time_domain.get()); | 31 DCHECK(time_domain); |
| 32 time_domain->RegisterQueue(this); | |
| 32 } | 33 } |
| 33 | 34 |
| 34 TaskQueueImpl::~TaskQueueImpl() {} | 35 TaskQueueImpl::~TaskQueueImpl() {} |
|
Sami
2015/11/26 19:27:50
nit: DCHECK that we no longer have a time domain?
alex clarke (OOO till 29th)
2015/11/27 10:01:59
I added a de-register here too. It was needed in
| |
| 35 | 36 |
| 36 TaskQueueImpl::Task::Task() | 37 TaskQueueImpl::Task::Task() |
| 37 : PendingTask(tracked_objects::Location(), | 38 : PendingTask(tracked_objects::Location(), |
| 38 base::Closure(), | 39 base::Closure(), |
| 39 base::TimeTicks(), | 40 base::TimeTicks(), |
| 40 true), | 41 true), |
| 41 #ifndef NDEBUG | 42 #ifndef NDEBUG |
| 42 enqueue_order_set_(false), | 43 enqueue_order_set_(false), |
| 43 #endif | 44 #endif |
| 44 enqueue_order_(0) { | 45 enqueue_order_(0) { |
| 45 sequence_num = 0; | 46 sequence_num = 0; |
| 46 } | 47 } |
| 47 | 48 |
| 48 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, | 49 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, |
| 49 const base::Closure& task, | 50 const base::Closure& task, |
| 50 int sequence_number, | 51 int sequence_number, |
| 51 bool nestable) | 52 bool nestable) |
| 52 : PendingTask(posted_from, task, base::TimeTicks(), nestable), | 53 : PendingTask(posted_from, task, base::TimeTicks(), nestable), |
| 53 #ifndef NDEBUG | 54 #ifndef NDEBUG |
| 54 enqueue_order_set_(false), | 55 enqueue_order_set_(false), |
| 55 #endif | 56 #endif |
| 56 enqueue_order_(0) { | 57 enqueue_order_(0) { |
| 57 sequence_num = sequence_number; | 58 sequence_num = sequence_number; |
| 58 } | 59 } |
| 59 | 60 |
| 60 TaskQueueImpl::AnyThread::AnyThread( | 61 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 61 TaskQueueManager* task_queue_manager, | 62 PumpPolicy pump_policy, |
| 62 PumpPolicy pump_policy, | 63 TimeDomain* time_domain) |
| 63 const scoped_refptr<TimeDomain>& time_domain) | |
| 64 : task_queue_manager(task_queue_manager), | 64 : task_queue_manager(task_queue_manager), |
| 65 pump_policy(pump_policy), | 65 pump_policy(pump_policy), |
| 66 time_domain(time_domain) {} | 66 time_domain(time_domain) {} |
| 67 | 67 |
| 68 TaskQueueImpl::AnyThread::~AnyThread() {} | 68 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 69 | 69 |
| 70 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 70 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| 71 TaskQueueManager* task_queue_manager) | 71 TaskQueueManager* task_queue_manager) |
| 72 : task_queue_manager(task_queue_manager), | 72 : task_queue_manager(task_queue_manager), |
| 73 set_index(0) {} | 73 set_index(0) {} |
| 74 | 74 |
| 75 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 75 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 76 | 76 |
| 77 void TaskQueueImpl::UnregisterTaskQueue() { | 77 void TaskQueueImpl::UnregisterTaskQueue() { |
| 78 base::AutoLock lock(any_thread_lock_); | 78 base::AutoLock lock(any_thread_lock_); |
| 79 if (!any_thread().task_queue_manager) | 79 if (!any_thread().task_queue_manager) |
| 80 return; | 80 return; |
| 81 any_thread().time_domain->UnregisterQueue(this); | 81 if (any_thread().time_domain) |
| 82 any_thread().time_domain->UnregisterQueue(this); | |
| 82 any_thread().time_domain = nullptr; | 83 any_thread().time_domain = nullptr; |
| 83 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 84 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
| 84 | 85 |
| 85 any_thread().task_queue_manager = nullptr; | 86 any_thread().task_queue_manager = nullptr; |
| 86 main_thread_only().task_queue_manager = nullptr; | 87 main_thread_only().task_queue_manager = nullptr; |
| 87 any_thread().delayed_task_queue = std::priority_queue<Task>(); | 88 any_thread().delayed_task_queue = std::priority_queue<Task>(); |
| 88 any_thread().incoming_queue = std::queue<Task>(); | 89 any_thread().incoming_queue = std::queue<Task>(); |
| 89 main_thread_only().work_queue = std::queue<Task>(); | 90 main_thread_only().work_queue = std::queue<Task>(); |
| 90 } | 91 } |
| 91 | 92 |
| 92 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 93 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
| 93 base::AutoLock lock(any_thread_lock_); | 94 base::AutoLock lock(any_thread_lock_); |
| 94 return base::PlatformThread::CurrentId() == thread_id_; | 95 return base::PlatformThread::CurrentId() == thread_id_; |
| 95 } | 96 } |
| 96 | 97 |
| 97 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 98 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
| 98 const base::Closure& task, | 99 const base::Closure& task, |
| 99 base::TimeDelta delay) { | 100 base::TimeDelta delay) { |
| 100 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 101 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
| 101 } | 102 } |
| 102 | 103 |
| 103 bool TaskQueueImpl::PostNonNestableDelayedTask( | 104 bool TaskQueueImpl::PostNonNestableDelayedTask( |
| 104 const tracked_objects::Location& from_here, | 105 const tracked_objects::Location& from_here, |
| 105 const base::Closure& task, | 106 const base::Closure& task, |
| 106 base::TimeDelta delay) { | 107 base::TimeDelta delay) { |
| 107 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); | 108 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); |
| 108 } | 109 } |
| 109 | 110 |
| 110 bool TaskQueueImpl::PostDelayedTaskAt( | |
| 111 const tracked_objects::Location& from_here, | |
| 112 const base::Closure& task, | |
| 113 base::TimeTicks desired_run_time) { | |
| 114 base::AutoLock lock(any_thread_lock_); | |
| 115 if (!any_thread().task_queue_manager) | |
| 116 return false; | |
| 117 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); | |
| 118 return PostDelayedTaskLocked(&lazy_now, from_here, task, desired_run_time, | |
| 119 TaskType::NORMAL); | |
| 120 } | |
| 121 | |
| 122 bool TaskQueueImpl::PostDelayedTaskImpl( | 111 bool TaskQueueImpl::PostDelayedTaskImpl( |
| 123 const tracked_objects::Location& from_here, | 112 const tracked_objects::Location& from_here, |
| 124 const base::Closure& task, | 113 const base::Closure& task, |
| 125 base::TimeDelta delay, | 114 base::TimeDelta delay, |
| 126 TaskType task_type) { | 115 TaskType task_type) { |
| 127 base::AutoLock lock(any_thread_lock_); | 116 base::AutoLock lock(any_thread_lock_); |
| 128 if (!any_thread().task_queue_manager) | 117 if (!any_thread().task_queue_manager) |
| 129 return false; | 118 return false; |
| 130 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); | 119 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
| 131 base::TimeTicks desired_run_time; | 120 base::TimeTicks desired_run_time; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 any_thread().task_queue_manager->DidQueueTask(thread_hop_task); | 158 any_thread().task_queue_manager->DidQueueTask(thread_hop_task); |
| 170 EnqueueTaskLocked(thread_hop_task); | 159 EnqueueTaskLocked(thread_hop_task); |
| 171 } | 160 } |
| 172 return true; | 161 return true; |
| 173 } | 162 } |
| 174 pending_task.set_enqueue_order(pending_task.sequence_num); | 163 pending_task.set_enqueue_order(pending_task.sequence_num); |
| 175 EnqueueTaskLocked(pending_task); | 164 EnqueueTaskLocked(pending_task); |
| 176 return true; | 165 return true; |
| 177 } | 166 } |
| 178 | 167 |
| 179 void TaskQueueImpl::ScheduleDelayedWorkTask( | 168 void TaskQueueImpl::ScheduleDelayedWorkTask(TimeDomain* time_domain, |
| 180 const scoped_refptr<TimeDomain> time_domain, | 169 base::TimeTicks desired_run_time) { |
| 181 base::TimeTicks desired_run_time) { | |
| 182 DCHECK(main_thread_checker_.CalledOnValidThread()); | 170 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 183 LazyNow lazy_now(time_domain->CreateLazyNow()); | 171 LazyNow lazy_now(time_domain->CreateLazyNow()); |
| 184 time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); | 172 time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); |
| 185 } | 173 } |
| 186 | 174 |
| 187 void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { | 175 void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { |
| 188 base::AutoLock lock(any_thread_lock_); | 176 base::AutoLock lock(any_thread_lock_); |
| 189 if (!any_thread().task_queue_manager) | 177 if (!any_thread().task_queue_manager) |
| 190 return; | 178 return; |
| 191 | 179 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 212 return main_thread_only().task_queue_manager->selector_.IsQueueEnabled(this); | 200 return main_thread_only().task_queue_manager->selector_.IsQueueEnabled(this); |
| 213 } | 201 } |
| 214 | 202 |
| 215 TaskQueue::QueueState TaskQueueImpl::GetQueueState() const { | 203 TaskQueue::QueueState TaskQueueImpl::GetQueueState() const { |
| 216 if (!main_thread_only().work_queue.empty()) | 204 if (!main_thread_only().work_queue.empty()) |
| 217 return QueueState::HAS_WORK; | 205 return QueueState::HAS_WORK; |
| 218 | 206 |
| 219 { | 207 { |
| 220 base::AutoLock lock(any_thread_lock_); | 208 base::AutoLock lock(any_thread_lock_); |
| 221 if (any_thread().incoming_queue.empty()) { | 209 if (any_thread().incoming_queue.empty()) { |
| 222 return QueueState::EMPTY; | 210 if (any_thread().delayed_task_queue.empty()) |
| 211 return QueueState::EMPTY; | |
| 212 else | |
| 213 return QueueState::NO_IMMEDIATE_WORK; | |
| 223 } else { | 214 } else { |
| 224 return QueueState::NEEDS_PUMPING; | 215 return QueueState::NEEDS_PUMPING; |
| 225 } | 216 } |
| 226 } | 217 } |
| 227 } | 218 } |
| 228 | |
|
Sami
2015/11/26 19:27:50
Intentional?
alex clarke (OOO till 29th)
2015/11/27 10:01:59
Done.
| |
| 229 bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const Task* task) { | 219 bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const Task* task) { |
| 230 // A null task is passed when UpdateQueue is called before any task is run. | 220 // A null task is passed when UpdateQueue is called before any task is run. |
| 231 // In this case we don't want to pump an after_wakeup queue, so return true | 221 // In this case we don't want to pump an after_wakeup queue, so return true |
| 232 // here. | 222 // here. |
| 233 if (!task) | 223 if (!task) |
| 234 return true; | 224 return true; |
| 235 | 225 |
| 236 // Return false if there are no task in the incoming queue. | 226 // Return false if there are no task in the incoming queue. |
| 237 if (any_thread().incoming_queue.empty()) | 227 if (any_thread().incoming_queue.empty()) |
| 238 return false; | 228 return false; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 498 } | 488 } |
| 499 | 489 |
| 500 void TaskQueueImpl::NotifyDidProcessTask( | 490 void TaskQueueImpl::NotifyDidProcessTask( |
| 501 const base::PendingTask& pending_task) { | 491 const base::PendingTask& pending_task) { |
| 502 DCHECK(should_notify_observers_); | 492 DCHECK(should_notify_observers_); |
| 503 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, | 493 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, |
| 504 main_thread_only().task_observers, | 494 main_thread_only().task_observers, |
| 505 DidProcessTask(pending_task)); | 495 DidProcessTask(pending_task)); |
| 506 } | 496 } |
| 507 | 497 |
| 508 void TaskQueueImpl::SetTimeDomain( | 498 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { |
| 509 const scoped_refptr<TimeDomain>& time_domain) { | |
| 510 base::AutoLock lock(any_thread_lock_); | 499 base::AutoLock lock(any_thread_lock_); |
| 511 DCHECK(main_thread_checker_.CalledOnValidThread()); | 500 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 512 if (time_domain == any_thread().time_domain) | 501 if (time_domain == any_thread().time_domain) |
| 513 return; | 502 return; |
| 514 | 503 |
| 515 any_thread().time_domain->MigrateQueue(this, time_domain.get()); | 504 if (time_domain) |
| 505 any_thread().time_domain->MigrateQueue(this, time_domain); | |
| 516 any_thread().time_domain = time_domain; | 506 any_thread().time_domain = time_domain; |
| 517 } | 507 } |
| 518 | 508 |
| 519 // static | 509 // static |
| 520 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 510 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, |
| 521 base::trace_event::TracedValue* state) { | 511 base::trace_event::TracedValue* state) { |
| 522 std::queue<Task> queue_copy(queue); | 512 std::queue<Task> queue_copy(queue); |
| 523 while (!queue_copy.empty()) { | 513 while (!queue_copy.empty()) { |
| 524 TaskAsValueInto(queue_copy.front(), state); | 514 TaskAsValueInto(queue_copy.front(), state); |
| 525 queue_copy.pop(); | 515 queue_copy.pop(); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 551 state->EndDictionary(); | 541 state->EndDictionary(); |
| 552 } | 542 } |
| 553 | 543 |
| 554 size_t TaskQueueImpl::IncomingQueueSizeForTest() const { | 544 size_t TaskQueueImpl::IncomingQueueSizeForTest() const { |
| 555 base::AutoLock lock(any_thread_lock_); | 545 base::AutoLock lock(any_thread_lock_); |
| 556 return any_thread().incoming_queue.size(); | 546 return any_thread().incoming_queue.size(); |
| 557 } | 547 } |
| 558 | 548 |
| 559 } // namespace internal | 549 } // namespace internal |
| 560 } // namespace scheduler | 550 } // namespace scheduler |
| OLD | NEW |