| 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() { |
| 36 base::AutoLock lock(any_thread_lock_); |
| 37 if (any_thread().time_domain) |
| 38 any_thread().time_domain->UnregisterQueue(this); |
| 39 } |
| 35 | 40 |
| 36 TaskQueueImpl::Task::Task() | 41 TaskQueueImpl::Task::Task() |
| 37 : PendingTask(tracked_objects::Location(), | 42 : PendingTask(tracked_objects::Location(), |
| 38 base::Closure(), | 43 base::Closure(), |
| 39 base::TimeTicks(), | 44 base::TimeTicks(), |
| 40 true), | 45 true), |
| 41 #ifndef NDEBUG | 46 #ifndef NDEBUG |
| 42 enqueue_order_set_(false), | 47 enqueue_order_set_(false), |
| 43 #endif | 48 #endif |
| 44 enqueue_order_(0) { | 49 enqueue_order_(0) { |
| 45 sequence_num = 0; | 50 sequence_num = 0; |
| 46 } | 51 } |
| 47 | 52 |
| 48 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, | 53 TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from, |
| 49 const base::Closure& task, | 54 const base::Closure& task, |
| 50 int sequence_number, | 55 int sequence_number, |
| 51 bool nestable) | 56 bool nestable) |
| 52 : PendingTask(posted_from, task, base::TimeTicks(), nestable), | 57 : PendingTask(posted_from, task, base::TimeTicks(), nestable), |
| 53 #ifndef NDEBUG | 58 #ifndef NDEBUG |
| 54 enqueue_order_set_(false), | 59 enqueue_order_set_(false), |
| 55 #endif | 60 #endif |
| 56 enqueue_order_(0) { | 61 enqueue_order_(0) { |
| 57 sequence_num = sequence_number; | 62 sequence_num = sequence_number; |
| 58 } | 63 } |
| 59 | 64 |
| 60 TaskQueueImpl::AnyThread::AnyThread( | 65 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 61 TaskQueueManager* task_queue_manager, | 66 PumpPolicy pump_policy, |
| 62 PumpPolicy pump_policy, | 67 TimeDomain* time_domain) |
| 63 const scoped_refptr<TimeDomain>& time_domain) | |
| 64 : task_queue_manager(task_queue_manager), | 68 : task_queue_manager(task_queue_manager), |
| 65 pump_policy(pump_policy), | 69 pump_policy(pump_policy), |
| 66 time_domain(time_domain) {} | 70 time_domain(time_domain) {} |
| 67 | 71 |
| 68 TaskQueueImpl::AnyThread::~AnyThread() {} | 72 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 69 | 73 |
| 70 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 74 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| 71 TaskQueueManager* task_queue_manager) | 75 TaskQueueManager* task_queue_manager) |
| 72 : task_queue_manager(task_queue_manager), | 76 : task_queue_manager(task_queue_manager), |
| 73 set_index(0) {} | 77 set_index(0) {} |
| 74 | 78 |
| 75 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 79 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 76 | 80 |
| 77 void TaskQueueImpl::UnregisterTaskQueue() { | 81 void TaskQueueImpl::UnregisterTaskQueue() { |
| 78 base::AutoLock lock(any_thread_lock_); | 82 base::AutoLock lock(any_thread_lock_); |
| 79 if (!any_thread().task_queue_manager) | 83 if (!any_thread().task_queue_manager) |
| 80 return; | 84 return; |
| 81 any_thread().time_domain->UnregisterQueue(this); | 85 if (any_thread().time_domain) |
| 86 any_thread().time_domain->UnregisterQueue(this); |
| 82 any_thread().time_domain = nullptr; | 87 any_thread().time_domain = nullptr; |
| 83 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 88 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
| 84 | 89 |
| 85 any_thread().task_queue_manager = nullptr; | 90 any_thread().task_queue_manager = nullptr; |
| 86 main_thread_only().task_queue_manager = nullptr; | 91 main_thread_only().task_queue_manager = nullptr; |
| 87 any_thread().delayed_task_queue = std::priority_queue<Task>(); | 92 any_thread().delayed_task_queue = std::priority_queue<Task>(); |
| 88 any_thread().incoming_queue = std::queue<Task>(); | 93 any_thread().incoming_queue = std::queue<Task>(); |
| 89 main_thread_only().work_queue = std::queue<Task>(); | 94 main_thread_only().work_queue = std::queue<Task>(); |
| 90 } | 95 } |
| 91 | 96 |
| 92 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 97 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
| 93 base::AutoLock lock(any_thread_lock_); | 98 base::AutoLock lock(any_thread_lock_); |
| 94 return base::PlatformThread::CurrentId() == thread_id_; | 99 return base::PlatformThread::CurrentId() == thread_id_; |
| 95 } | 100 } |
| 96 | 101 |
| 97 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 102 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
| 98 const base::Closure& task, | 103 const base::Closure& task, |
| 99 base::TimeDelta delay) { | 104 base::TimeDelta delay) { |
| 100 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 105 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
| 101 } | 106 } |
| 102 | 107 |
| 103 bool TaskQueueImpl::PostNonNestableDelayedTask( | 108 bool TaskQueueImpl::PostNonNestableDelayedTask( |
| 104 const tracked_objects::Location& from_here, | 109 const tracked_objects::Location& from_here, |
| 105 const base::Closure& task, | 110 const base::Closure& task, |
| 106 base::TimeDelta delay) { | 111 base::TimeDelta delay) { |
| 107 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); | 112 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); |
| 108 } | 113 } |
| 109 | 114 |
| 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( | 115 bool TaskQueueImpl::PostDelayedTaskImpl( |
| 123 const tracked_objects::Location& from_here, | 116 const tracked_objects::Location& from_here, |
| 124 const base::Closure& task, | 117 const base::Closure& task, |
| 125 base::TimeDelta delay, | 118 base::TimeDelta delay, |
| 126 TaskType task_type) { | 119 TaskType task_type) { |
| 127 base::AutoLock lock(any_thread_lock_); | 120 base::AutoLock lock(any_thread_lock_); |
| 128 if (!any_thread().task_queue_manager) | 121 if (!any_thread().task_queue_manager) |
| 129 return false; | 122 return false; |
| 130 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); | 123 LazyNow lazy_now(any_thread().time_domain->CreateLazyNow()); |
| 131 base::TimeTicks desired_run_time; | 124 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); | 162 any_thread().task_queue_manager->DidQueueTask(thread_hop_task); |
| 170 EnqueueTaskLocked(thread_hop_task); | 163 EnqueueTaskLocked(thread_hop_task); |
| 171 } | 164 } |
| 172 return true; | 165 return true; |
| 173 } | 166 } |
| 174 pending_task.set_enqueue_order(pending_task.sequence_num); | 167 pending_task.set_enqueue_order(pending_task.sequence_num); |
| 175 EnqueueTaskLocked(pending_task); | 168 EnqueueTaskLocked(pending_task); |
| 176 return true; | 169 return true; |
| 177 } | 170 } |
| 178 | 171 |
| 179 void TaskQueueImpl::ScheduleDelayedWorkTask( | 172 void TaskQueueImpl::ScheduleDelayedWorkTask(TimeDomain* time_domain, |
| 180 const scoped_refptr<TimeDomain> time_domain, | 173 base::TimeTicks desired_run_time) { |
| 181 base::TimeTicks desired_run_time) { | |
| 182 DCHECK(main_thread_checker_.CalledOnValidThread()); | 174 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 183 LazyNow lazy_now(time_domain->CreateLazyNow()); | 175 LazyNow lazy_now(time_domain->CreateLazyNow()); |
| 184 time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); | 176 time_domain->ScheduleDelayedWork(this, desired_run_time, &lazy_now); |
| 185 } | 177 } |
| 186 | 178 |
| 187 void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { | 179 void TaskQueueImpl::MoveReadyDelayedTasksToIncomingQueue(LazyNow* lazy_now) { |
| 188 base::AutoLock lock(any_thread_lock_); | 180 base::AutoLock lock(any_thread_lock_); |
| 189 if (!any_thread().task_queue_manager) | 181 if (!any_thread().task_queue_manager) |
| 190 return; | 182 return; |
| 191 | 183 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 212 return main_thread_only().task_queue_manager->selector_.IsQueueEnabled(this); | 204 return main_thread_only().task_queue_manager->selector_.IsQueueEnabled(this); |
| 213 } | 205 } |
| 214 | 206 |
| 215 TaskQueue::QueueState TaskQueueImpl::GetQueueState() const { | 207 TaskQueue::QueueState TaskQueueImpl::GetQueueState() const { |
| 216 if (!main_thread_only().work_queue.empty()) | 208 if (!main_thread_only().work_queue.empty()) |
| 217 return QueueState::HAS_WORK; | 209 return QueueState::HAS_WORK; |
| 218 | 210 |
| 219 { | 211 { |
| 220 base::AutoLock lock(any_thread_lock_); | 212 base::AutoLock lock(any_thread_lock_); |
| 221 if (any_thread().incoming_queue.empty()) { | 213 if (any_thread().incoming_queue.empty()) { |
| 222 return QueueState::EMPTY; | 214 if (any_thread().delayed_task_queue.empty()) |
| 215 return QueueState::EMPTY; |
| 216 else |
| 217 return QueueState::NO_IMMEDIATE_WORK; |
| 223 } else { | 218 } else { |
| 224 return QueueState::NEEDS_PUMPING; | 219 return QueueState::NEEDS_PUMPING; |
| 225 } | 220 } |
| 226 } | 221 } |
| 227 } | 222 } |
| 228 | 223 |
| 229 bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const Task* task) { | 224 bool TaskQueueImpl::TaskIsOlderThanQueuedTasks(const Task* task) { |
| 230 // A null task is passed when UpdateQueue is called before any task is run. | 225 // 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 | 226 // In this case we don't want to pump an after_wakeup queue, so return true |
| 232 // here. | 227 // here. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 } | 493 } |
| 499 | 494 |
| 500 void TaskQueueImpl::NotifyDidProcessTask( | 495 void TaskQueueImpl::NotifyDidProcessTask( |
| 501 const base::PendingTask& pending_task) { | 496 const base::PendingTask& pending_task) { |
| 502 DCHECK(should_notify_observers_); | 497 DCHECK(should_notify_observers_); |
| 503 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, | 498 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, |
| 504 main_thread_only().task_observers, | 499 main_thread_only().task_observers, |
| 505 DidProcessTask(pending_task)); | 500 DidProcessTask(pending_task)); |
| 506 } | 501 } |
| 507 | 502 |
| 508 void TaskQueueImpl::SetTimeDomain( | 503 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { |
| 509 const scoped_refptr<TimeDomain>& time_domain) { | |
| 510 base::AutoLock lock(any_thread_lock_); | 504 base::AutoLock lock(any_thread_lock_); |
| 511 DCHECK(main_thread_checker_.CalledOnValidThread()); | 505 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 512 if (time_domain == any_thread().time_domain) | 506 if (time_domain == any_thread().time_domain) |
| 513 return; | 507 return; |
| 514 | 508 |
| 515 any_thread().time_domain->MigrateQueue(this, time_domain.get()); | 509 if (time_domain) |
| 510 any_thread().time_domain->MigrateQueue(this, time_domain); |
| 516 any_thread().time_domain = time_domain; | 511 any_thread().time_domain = time_domain; |
| 517 } | 512 } |
| 518 | 513 |
| 519 // static | 514 // static |
| 520 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 515 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, |
| 521 base::trace_event::TracedValue* state) { | 516 base::trace_event::TracedValue* state) { |
| 522 std::queue<Task> queue_copy(queue); | 517 std::queue<Task> queue_copy(queue); |
| 523 while (!queue_copy.empty()) { | 518 while (!queue_copy.empty()) { |
| 524 TaskAsValueInto(queue_copy.front(), state); | 519 TaskAsValueInto(queue_copy.front(), state); |
| 525 queue_copy.pop(); | 520 queue_copy.pop(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 551 state->EndDictionary(); | 546 state->EndDictionary(); |
| 552 } | 547 } |
| 553 | 548 |
| 554 size_t TaskQueueImpl::IncomingQueueSizeForTest() const { | 549 size_t TaskQueueImpl::IncomingQueueSizeForTest() const { |
| 555 base::AutoLock lock(any_thread_lock_); | 550 base::AutoLock lock(any_thread_lock_); |
| 556 return any_thread().incoming_queue.size(); | 551 return any_thread().incoming_queue.size(); |
| 557 } | 552 } |
| 558 | 553 |
| 559 } // namespace internal | 554 } // namespace internal |
| 560 } // namespace scheduler | 555 } // namespace scheduler |
| OLD | NEW |