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 "platform/scheduler/base/task_queue_impl.h" | 5 #include "platform/scheduler/base/task_queue_impl.h" |
| 6 | 6 |
| 7 #include "base/trace_event/blame_context.h" | 7 #include "base/trace_event/blame_context.h" |
| 8 #include "platform/scheduler/base/task_queue_manager.h" | 8 #include "platform/scheduler/base/task_queue_manager.h" |
| 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" |
| 10 #include "platform/scheduler/base/time_domain.h" | 10 #include "platform/scheduler/base/time_domain.h" |
| 11 #include "platform/scheduler/base/work_queue.h" | 11 #include "platform/scheduler/base/work_queue.h" |
| 12 | 12 |
| 13 namespace blink { | 13 namespace blink { |
| 14 namespace scheduler { | 14 namespace scheduler { |
| 15 | |
| 16 TaskQueue::TaskHandle::TaskHandle() : enqueue_order_(0), sequence_number_(0) {} | |
| 17 | |
| 18 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, uint64_t enqueue_order) | |
| 19 : enqueue_order_(enqueue_order), | |
| 20 #if DCHECK_IS_ON() | |
| 21 task_queue_(task_queue), | |
| 22 #endif | |
| 23 sequence_number_(0) { | |
| 24 DCHECK_GT(enqueue_order, 0ull); | |
| 25 } | |
| 26 | |
| 27 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, | |
| 28 base::TimeTicks scheduled_run_time, | |
| 29 int sequence_number) | |
| 30 : enqueue_order_(0), | |
| 31 scheduled_run_time_(scheduled_run_time), | |
| 32 #if DCHECK_IS_ON() | |
| 33 task_queue_(task_queue), | |
| 34 #endif | |
| 35 sequence_number_(sequence_number) { | |
| 36 DCHECK(!scheduled_run_time.is_null()); | |
| 37 } | |
| 38 | |
| 39 TaskQueue::TaskHandle::operator bool() const { | |
| 40 return !scheduled_run_time_.is_null() || | |
| 41 internal::EnqueueOrderGenerator::isValidEnqueueOrder(enqueue_order_); | |
| 42 } | |
| 43 | |
| 15 namespace internal { | 44 namespace internal { |
| 16 | 45 |
| 17 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
| 18 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
| 19 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
| 20 const Spec& spec, | 49 const Spec& spec, |
| 21 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
| 22 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
| 23 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
| 24 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 53 any_thread_(task_queue_manager, spec.pump_policy, time_domain), |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 bool nestable, | 113 bool nestable, |
| 85 EnqueueOrder enqueue_order) | 114 EnqueueOrder enqueue_order) |
| 86 : PendingTask(posted_from, task, desired_run_time, nestable), | 115 : PendingTask(posted_from, task, desired_run_time, nestable), |
| 87 #ifndef NDEBUG | 116 #ifndef NDEBUG |
| 88 enqueue_order_set_(true), | 117 enqueue_order_set_(true), |
| 89 #endif | 118 #endif |
| 90 enqueue_order_(enqueue_order) { | 119 enqueue_order_(enqueue_order) { |
| 91 sequence_num = sequence_number; | 120 sequence_num = sequence_number; |
| 92 } | 121 } |
| 93 | 122 |
| 123 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()( | |
| 124 const Task& a, | |
| 125 const Task& b) const { | |
| 126 if (a.delayed_run_time < b.delayed_run_time) | |
| 127 return true; | |
| 128 | |
| 129 if (a.delayed_run_time > b.delayed_run_time) | |
| 130 return false; | |
| 131 | |
| 132 // If the times happen to match, then we use the sequence number to decide. | |
| 133 // Compare the difference to support integer roll-over. | |
| 134 return (a.sequence_num - b.sequence_num) < 0; | |
| 135 } | |
| 136 | |
| 137 // static | |
| 138 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a, | |
| 139 const Task& b) { | |
| 140 return a.enqueue_order() < b.enqueue_order(); | |
| 141 } | |
| 142 | |
| 143 // static | |
| 144 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a, | |
| 145 const Task& b) { | |
| 146 if (a.delayed_run_time < b.delayed_run_time) | |
| 147 return true; | |
| 148 | |
| 149 if (a.delayed_run_time > b.delayed_run_time) | |
| 150 return false; | |
| 151 | |
| 152 // If the times happen to match, then we use the sequence number to decide. | |
| 153 // Compare the difference to support integer roll-over. | |
| 154 return (a.sequence_num - b.sequence_num) < 0; | |
| 155 } | |
| 156 | |
| 94 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 157 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
| 95 PumpPolicy pump_policy, | 158 PumpPolicy pump_policy, |
| 96 TimeDomain* time_domain) | 159 TimeDomain* time_domain) |
| 97 : task_queue_manager(task_queue_manager), | 160 : task_queue_manager(task_queue_manager), |
| 98 pump_policy(pump_policy), | 161 pump_policy(pump_policy), |
| 99 time_domain(time_domain) {} | 162 time_domain(time_domain), |
| 163 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { | |
| 164 } | |
| 100 | 165 |
| 101 TaskQueueImpl::AnyThread::~AnyThread() {} | 166 TaskQueueImpl::AnyThread::~AnyThread() {} |
| 102 | 167 |
| 103 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 168 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
| 104 TaskQueueManager* task_queue_manager, | 169 TaskQueueManager* task_queue_manager, |
| 105 PumpPolicy pump_policy, | 170 PumpPolicy pump_policy, |
| 106 TaskQueueImpl* task_queue, | 171 TaskQueueImpl* task_queue, |
| 107 TimeDomain* time_domain) | 172 TimeDomain* time_domain) |
| 108 : task_queue_manager(task_queue_manager), | 173 : task_queue_manager(task_queue_manager), |
| 109 pump_policy(pump_policy), | 174 pump_policy(pump_policy), |
| 110 time_domain(time_domain), | 175 time_domain(time_domain), |
| 111 delayed_work_queue(new WorkQueue(task_queue, "delayed")), | 176 delayed_work_queue( |
| 112 immediate_work_queue(new WorkQueue(task_queue, "immediate")), | 177 new WorkQueue(task_queue, |
| 178 "delayed", | |
| 179 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), | |
| 180 immediate_work_queue( | |
| 181 new WorkQueue(task_queue, | |
| 182 "immediate", | |
| 183 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), | |
| 113 set_index(0), | 184 set_index(0), |
| 114 is_enabled(true), | 185 is_enabled(true), |
| 115 blame_context(nullptr) {} | 186 blame_context(nullptr) {} |
| 116 | 187 |
| 117 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 188 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 118 | 189 |
| 119 void TaskQueueImpl::UnregisterTaskQueue() { | 190 void TaskQueueImpl::UnregisterTaskQueue() { |
| 120 base::AutoLock lock(any_thread_lock_); | 191 base::AutoLock lock(any_thread_lock_); |
| 121 if (main_thread_only().time_domain) | 192 if (main_thread_only().time_domain) |
| 122 main_thread_only().time_domain->UnregisterQueue(this); | 193 main_thread_only().time_domain->UnregisterQueue(this); |
| 123 if (!any_thread().task_queue_manager) | 194 if (!any_thread().task_queue_manager) |
| 124 return; | 195 return; |
| 125 any_thread().time_domain = nullptr; | 196 any_thread().time_domain = nullptr; |
| 126 main_thread_only().time_domain = nullptr; | 197 main_thread_only().time_domain = nullptr; |
| 127 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 198 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
| 128 | 199 |
| 129 any_thread().task_queue_manager = nullptr; | 200 any_thread().task_queue_manager = nullptr; |
| 130 main_thread_only().task_queue_manager = nullptr; | 201 main_thread_only().task_queue_manager = nullptr; |
| 131 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); | 202 main_thread_only().delayed_incoming_queue.clear(); |
| 132 any_thread().immediate_incoming_queue = std::queue<Task>(); | 203 any_thread().immediate_incoming_queue.clear(); |
| 133 main_thread_only().immediate_work_queue.reset(); | 204 main_thread_only().immediate_work_queue.reset(); |
| 134 main_thread_only().delayed_work_queue.reset(); | 205 main_thread_only().delayed_work_queue.reset(); |
| 135 } | 206 } |
| 136 | 207 |
| 137 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 208 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
| 138 base::AutoLock lock(any_thread_lock_); | 209 base::AutoLock lock(any_thread_lock_); |
| 139 return base::PlatformThread::CurrentId() == thread_id_; | 210 return base::PlatformThread::CurrentId() == thread_id_; |
| 140 } | 211 } |
| 141 | 212 |
| 213 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask( | |
| 214 const tracked_objects::Location& from_here, | |
| 215 const base::Closure& task, | |
| 216 base::TimeDelta delay) { | |
| 217 if (!main_thread_only().task_queue_manager) | |
| 218 return TaskHandle(); | |
| 219 | |
| 220 EnqueueOrder sequence_number = | |
| 221 main_thread_only().task_queue_manager->GetNextSequenceNumber(); | |
| 222 | |
| 223 if (delay.is_zero()) { | |
| 224 base::AutoLock lock(any_thread_lock_); | |
| 225 PushOntoImmediateIncomingQueueLocked( | |
| 226 Task(from_here, task, base::TimeTicks(), sequence_number, true, | |
| 227 sequence_number)); | |
| 228 | |
| 229 return TaskHandle(this, sequence_number); | |
| 230 } else { | |
| 231 DCHECK_GT(delay, base::TimeDelta()); | |
| 232 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | |
| 233 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | |
| 234 PushOntoDelayedIncomingQueueFromMainThread( | |
| 235 Task(from_here, task, time_domain_delayed_run_time, sequence_number, | |
| 236 true), | |
| 237 time_domain_now); | |
| 238 | |
| 239 return TaskHandle(this, time_domain_delayed_run_time, sequence_number); | |
| 240 } | |
| 241 } | |
| 242 | |
| 243 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) { | |
| 244 if (!handle) | |
| 245 return false; | |
| 246 | |
| 247 // If the TaskQueueManager has gone away, pretend we have canceled the task | |
| 248 // because this simplifies logic in TimerBase::stop. | |
| 249 if (!main_thread_only().task_queue_manager) | |
|
Sami
2016/08/18 15:53:43
We don't seem to need TQM below anymore, so maybe
alex clarke (OOO till 29th)
2016/08/18 16:51:41
Right but we do need the immediate_work_queue & de
| |
| 250 return true; | |
| 251 | |
| 252 #if DCHECK_IS_ON() | |
| 253 DCHECK_EQ(handle.task_queue_, this); | |
| 254 #endif | |
| 255 | |
| 256 if (handle.scheduled_run_time_.is_null()) { | |
| 257 // It's an immediate task. | |
| 258 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
|
Sami
2016/08/18 15:53:43
nit: not sure if the compiler is smart enough to e
alex clarke (OOO till 29th)
2016/08/18 16:51:41
Done.
| |
| 259 handle.sequence_number_, false, handle.enqueue_order_); | |
| 260 if (main_thread_only().immediate_work_queue->CancelTask(fake_task)) | |
| 261 return true; | |
| 262 | |
| 263 base::AutoLock lock(any_thread_lock_); | |
| 264 return any_thread().immediate_incoming_queue.erase(fake_task) > 0; | |
| 265 } else { | |
| 266 // It's a delayed task. | |
| 267 DCHECK_EQ(0ull, handle.enqueue_order_); | |
| 268 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
|
Sami
2016/08/18 15:53:43
Readability suggestion -- feel free to ignore: Sho
alex clarke (OOO till 29th)
2016/08/18 16:51:41
Done.
| |
| 269 handle.sequence_number_, false); | |
| 270 DelayedRunTimeQueue::iterator it = | |
| 271 main_thread_only().delayed_incoming_queue.find(fake_task); | |
| 272 if (it != main_thread_only().delayed_incoming_queue.end()) { | |
| 273 // It's safe to remove the wakeup from the TimeDomain only if this task's | |
| 274 // scheduled run time was unique within the queue. | |
| 275 bool can_cancel_timedomain_wakeup = true; | |
| 276 if (it != main_thread_only().delayed_incoming_queue.begin()) { | |
| 277 DelayedRunTimeQueue::iterator before = it; | |
| 278 before--; | |
| 279 if (before->delayed_run_time == handle.scheduled_run_time_) | |
| 280 can_cancel_timedomain_wakeup = false; | |
| 281 } | |
| 282 if (can_cancel_timedomain_wakeup) { | |
| 283 DelayedRunTimeQueue::iterator after = it; | |
| 284 after++; | |
| 285 if (after != main_thread_only().delayed_incoming_queue.end() && | |
| 286 after->delayed_run_time == handle.scheduled_run_time_) { | |
| 287 can_cancel_timedomain_wakeup = false; | |
| 288 } | |
| 289 } | |
| 290 if (can_cancel_timedomain_wakeup) { | |
| 291 main_thread_only().time_domain->CancelDelayedWork( | |
| 292 this, handle.scheduled_run_time_); | |
| 293 } | |
| 294 | |
| 295 main_thread_only().delayed_incoming_queue.erase(it); | |
| 296 return true; | |
| 297 } | |
| 298 | |
| 299 return main_thread_only().delayed_work_queue->CancelTask(fake_task); | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const { | |
| 304 if (!handle) | |
| 305 return false; | |
| 306 | |
| 307 // If the TaskQueueManager has gone away the task got cancelled. | |
| 308 if (!main_thread_only().task_queue_manager) | |
| 309 return false; | |
| 310 | |
| 311 #if DCHECK_IS_ON() | |
| 312 DCHECK_EQ(handle.task_queue_, this); | |
| 313 #endif | |
| 314 | |
| 315 if (handle.scheduled_run_time_.is_null()) { | |
| 316 // It's an immediate task. | |
| 317 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
| 318 handle.sequence_number_, false, handle.enqueue_order_); | |
| 319 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task)) | |
| 320 return true; | |
| 321 | |
| 322 base::AutoLock lock(any_thread_lock_); | |
| 323 return any_thread().immediate_incoming_queue.find(fake_task) != | |
| 324 any_thread().immediate_incoming_queue.end(); | |
| 325 } else { | |
| 326 // It's a delayed task. | |
| 327 DCHECK_EQ(0ull, handle.enqueue_order_); | |
| 328 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
| 329 handle.sequence_number_, false); | |
| 330 DelayedRunTimeQueue::iterator it = | |
| 331 main_thread_only().delayed_incoming_queue.find(fake_task); | |
| 332 if (it != main_thread_only().delayed_incoming_queue.end()) | |
| 333 return true; | |
| 334 | |
| 335 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task); | |
| 336 } | |
| 337 } | |
| 338 | |
| 142 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 339 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
| 143 const base::Closure& task, | 340 const base::Closure& task, |
| 144 base::TimeDelta delay) { | 341 base::TimeDelta delay) { |
| 145 if (delay.is_zero()) | 342 if (delay.is_zero()) |
| 146 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); | 343 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); |
| 147 | 344 |
| 148 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 345 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
| 149 } | 346 } |
| 150 | 347 |
| 151 bool TaskQueueImpl::PostNonNestableDelayedTask( | 348 bool TaskQueueImpl::PostNonNestableDelayedTask( |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 return true; | 413 return true; |
| 217 } | 414 } |
| 218 | 415 |
| 219 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 416 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
| 220 Task pending_task, | 417 Task pending_task, |
| 221 base::TimeTicks now) { | 418 base::TimeTicks now) { |
| 222 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 419 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
| 223 | 420 |
| 224 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. | 421 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. |
| 225 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 422 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 226 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 423 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 227 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 424 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, |
| 228 now); | 425 now); |
| 229 TraceQueueSize(false); | 426 TraceQueueSize(false); |
| 230 } | 427 } |
| 231 | 428 |
| 232 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 429 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 233 any_thread().task_queue_manager->DidQueueTask(pending_task); | 430 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 234 | 431 |
| 235 int thread_hop_task_sequence_number = | 432 int thread_hop_task_sequence_number = |
| 236 any_thread().task_queue_manager->GetNextSequenceNumber(); | 433 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 237 PushOntoImmediateIncomingQueueLocked( | 434 PushOntoImmediateIncomingQueueLocked( |
| 238 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 435 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| 239 base::Passed(&pending_task)), | 436 base::Passed(&pending_task)), |
| 240 base::TimeTicks(), thread_hop_task_sequence_number, false, | 437 base::TimeTicks(), thread_hop_task_sequence_number, false, |
| 241 thread_hop_task_sequence_number)); | 438 thread_hop_task_sequence_number)); |
| 242 } | 439 } |
| 243 | 440 |
| 244 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 441 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
| 245 if (any_thread().immediate_incoming_queue.empty()) | 442 if (any_thread().immediate_incoming_queue.empty()) |
| 246 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 443 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
| 247 if (any_thread().pump_policy == PumpPolicy::AUTO && | 444 if (any_thread().pump_policy == PumpPolicy::AUTO && |
| 248 any_thread().immediate_incoming_queue.empty()) { | 445 any_thread().immediate_incoming_queue.empty()) { |
| 249 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 446 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 250 } | 447 } |
| 251 any_thread().task_queue_manager->DidQueueTask(pending_task); | 448 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 252 any_thread().immediate_incoming_queue.push(std::move(pending_task)); | 449 any_thread().immediate_incoming_queue.insert(std::move(pending_task)); |
| 253 TraceQueueSize(true); | 450 TraceQueueSize(true); |
| 254 } | 451 } |
| 255 | 452 |
| 256 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | 453 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { |
| 257 DCHECK(main_thread_checker_.CalledOnValidThread()); | 454 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 258 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 455 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 259 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 456 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
| 260 main_thread_only().time_domain->ScheduleDelayedWork( | 457 main_thread_only().time_domain->ScheduleDelayedWork( |
| 261 this, delayed_run_time, main_thread_only().time_domain->Now()); | 458 this, delayed_run_time, main_thread_only().time_domain->Now()); |
| 262 } | 459 } |
| 263 | 460 |
| 264 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 461 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
| 265 if (main_thread_only().is_enabled == enabled) | 462 if (main_thread_only().is_enabled == enabled) |
| 266 return; | 463 return; |
| 267 main_thread_only().is_enabled = enabled; | 464 main_thread_only().is_enabled = enabled; |
| 268 if (!main_thread_only().task_queue_manager) | 465 if (!main_thread_only().task_queue_manager) |
| 269 return; | 466 return; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 | 501 |
| 305 base::AutoLock lock(any_thread_lock_); | 502 base::AutoLock lock(any_thread_lock_); |
| 306 if (!any_thread().immediate_incoming_queue.empty()) | 503 if (!any_thread().immediate_incoming_queue.empty()) |
| 307 return true; | 504 return true; |
| 308 | 505 |
| 309 // If there's no immediate Incoming work then we only need pumping if there | 506 // If there's no immediate Incoming work then we only need pumping if there |
| 310 // is a delayed task that should be running now. | 507 // is a delayed task that should be running now. |
| 311 if (main_thread_only().delayed_incoming_queue.empty()) | 508 if (main_thread_only().delayed_incoming_queue.empty()) |
| 312 return false; | 509 return false; |
| 313 | 510 |
| 314 return main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 511 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
| 315 main_thread_only().time_domain->CreateLazyNow().Now(); | 512 main_thread_only().time_domain->CreateLazyNow().Now(); |
| 316 } | 513 } |
| 317 | 514 |
| 318 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( | 515 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( |
| 319 const Task* task) { | 516 const Task* task) { |
| 320 // A null task is passed when UpdateQueue is called before any task is run. | 517 // A null task is passed when UpdateQueue is called before any task is run. |
| 321 // In this case we don't want to pump an after_wakeup queue, so return true | 518 // In this case we don't want to pump an after_wakeup queue, so return true |
| 322 // here. | 519 // here. |
| 323 if (!task) | 520 if (!task) |
| 324 return true; | 521 return true; |
| 325 | 522 |
| 326 // Return false if task is newer than the oldest immediate task. | 523 // Return false if task is newer than the oldest immediate task. |
| 327 if (!any_thread().immediate_incoming_queue.empty() && | 524 if (!any_thread().immediate_incoming_queue.empty() && |
| 328 task->enqueue_order() > | 525 task->enqueue_order() > |
| 329 any_thread().immediate_incoming_queue.front().enqueue_order()) { | 526 any_thread().immediate_incoming_queue.begin()->enqueue_order()) { |
| 330 return false; | 527 return false; |
| 331 } | 528 } |
| 332 return true; | 529 return true; |
| 333 } | 530 } |
| 334 | 531 |
| 335 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { | 532 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { |
| 336 DCHECK(main_thread_checker_.CalledOnValidThread()); | 533 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 337 // A null task is passed when UpdateQueue is called before any task is run. | 534 // A null task is passed when UpdateQueue is called before any task is run. |
| 338 // In this case we don't want to pump an after_wakeup queue, so return true | 535 // In this case we don't want to pump an after_wakeup queue, so return true |
| 339 // here. | 536 // here. |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 367 return false; | 564 return false; |
| 368 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | 565 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && |
| 369 (!should_trigger_wakeup || | 566 (!should_trigger_wakeup || |
| 370 TaskIsOlderThanQueuedDelayedTasks(previous_task))) | 567 TaskIsOlderThanQueuedDelayedTasks(previous_task))) |
| 371 return false; | 568 return false; |
| 372 return true; | 569 return true; |
| 373 } | 570 } |
| 374 | 571 |
| 375 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 572 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
| 376 // Enqueue all delayed tasks that should be running now. | 573 // Enqueue all delayed tasks that should be running now. |
| 377 while (!main_thread_only().delayed_incoming_queue.empty() && | 574 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 378 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 575 DelayedRunTimeQueue::iterator next_task = |
| 379 lazy_now->Now()) { | 576 main_thread_only().delayed_incoming_queue.begin(); |
| 380 // Note: the const_cast is needed because there is no direct way to move | 577 if (next_task->delayed_run_time > lazy_now->Now()) |
| 381 // elements out of a priority queue. The queue must not be modified between | 578 break; |
| 382 // the top() and the pop(). | 579 // TODO(alexclarke): Use extract() when C++17 is allowed. |
| 383 main_thread_only().delayed_work_queue->PushAndSetEnqueueOrder( | 580 Task& task = const_cast<Task&>(*next_task); |
| 384 std::move( | 581 task.set_enqueue_order( |
| 385 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())), | |
| 386 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 582 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
| 387 main_thread_only().delayed_incoming_queue.pop(); | 583 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 584 main_thread_only().delayed_incoming_queue.erase(next_task); | |
| 388 } | 585 } |
| 389 } | 586 } |
| 390 | 587 |
| 391 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 588 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, |
| 392 bool should_trigger_wakeup, | 589 bool should_trigger_wakeup, |
| 393 const Task* previous_task) { | 590 const Task* previous_task) { |
| 394 if (!main_thread_only().task_queue_manager) | 591 if (!main_thread_only().task_queue_manager) |
| 395 return; | 592 return; |
| 396 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | 593 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) |
| 397 return; | 594 return; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 460 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { | 657 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { |
| 461 TRACE_EVENT1(disabled_by_default_tracing_category_, | 658 TRACE_EVENT1(disabled_by_default_tracing_category_, |
| 462 "TaskQueueImpl::PumpQueueLocked", "queue", name_); | 659 "TaskQueueImpl::PumpQueueLocked", "queue", name_); |
| 463 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; | 660 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; |
| 464 if (!task_queue_manager) | 661 if (!task_queue_manager) |
| 465 return; | 662 return; |
| 466 | 663 |
| 467 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 664 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
| 468 | 665 |
| 469 while (!any_thread().immediate_incoming_queue.empty()) { | 666 while (!any_thread().immediate_incoming_queue.empty()) { |
| 667 ComparatorQueue::iterator it = | |
| 668 any_thread().immediate_incoming_queue.begin(); | |
| 470 main_thread_only().immediate_work_queue->Push( | 669 main_thread_only().immediate_work_queue->Push( |
| 471 std::move(any_thread().immediate_incoming_queue.front())); | 670 std::move(const_cast<Task&>(*it))); |
| 472 any_thread().immediate_incoming_queue.pop(); | 671 any_thread().immediate_incoming_queue.erase(it); |
| 473 } | 672 } |
| 474 | 673 |
| 475 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no | 674 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no |
| 476 // longer needs to consider this queue for reloading. | 675 // longer needs to consider this queue for reloading. |
| 477 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 676 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
| 478 | 677 |
| 479 if (main_thread_only().immediate_work_queue->Empty() && | 678 if (main_thread_only().immediate_work_queue->Empty() && |
| 480 main_thread_only().delayed_work_queue->Empty()) { | 679 main_thread_only().delayed_work_queue->Empty()) { |
| 481 return; | 680 return; |
| 482 } | 681 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 569 state->SetInteger("immediate_incoming_queue_size", | 768 state->SetInteger("immediate_incoming_queue_size", |
| 570 any_thread().immediate_incoming_queue.size()); | 769 any_thread().immediate_incoming_queue.size()); |
| 571 state->SetInteger("delayed_incoming_queue_size", | 770 state->SetInteger("delayed_incoming_queue_size", |
| 572 main_thread_only().delayed_incoming_queue.size()); | 771 main_thread_only().delayed_incoming_queue.size()); |
| 573 state->SetInteger("immediate_work_queue_size", | 772 state->SetInteger("immediate_work_queue_size", |
| 574 main_thread_only().immediate_work_queue->Size()); | 773 main_thread_only().immediate_work_queue->Size()); |
| 575 state->SetInteger("delayed_work_queue_size", | 774 state->SetInteger("delayed_work_queue_size", |
| 576 main_thread_only().delayed_work_queue->Size()); | 775 main_thread_only().delayed_work_queue->Size()); |
| 577 if (!main_thread_only().delayed_incoming_queue.empty()) { | 776 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 578 base::TimeDelta delay_to_next_task = | 777 base::TimeDelta delay_to_next_task = |
| 579 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 778 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - |
| 580 main_thread_only().time_domain->CreateLazyNow().Now()); | 779 main_thread_only().time_domain->CreateLazyNow().Now()); |
| 581 state->SetDouble("delay_to_next_task_ms", | 780 state->SetDouble("delay_to_next_task_ms", |
| 582 delay_to_next_task.InMillisecondsF()); | 781 delay_to_next_task.InMillisecondsF()); |
| 583 } | 782 } |
| 584 if (verbose_tracing_enabled) { | 783 if (verbose_tracing_enabled) { |
| 585 state->BeginArray("immediate_incoming_queue"); | 784 state->BeginArray("immediate_incoming_queue"); |
| 586 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 785 QueueAsValueInto(any_thread().immediate_incoming_queue, state); |
| 587 state->EndArray(); | 786 state->EndArray(); |
| 588 state->BeginArray("delayed_work_queue"); | 787 state->BeginArray("delayed_work_queue"); |
| 589 main_thread_only().delayed_work_queue->AsValueInto(state); | 788 main_thread_only().delayed_work_queue->AsValueInto(state); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 655 base::AutoLock lock(any_thread_lock_); | 854 base::AutoLock lock(any_thread_lock_); |
| 656 return any_thread().time_domain; | 855 return any_thread().time_domain; |
| 657 } | 856 } |
| 658 | 857 |
| 659 void TaskQueueImpl::SetBlameContext( | 858 void TaskQueueImpl::SetBlameContext( |
| 660 base::trace_event::BlameContext* blame_context) { | 859 base::trace_event::BlameContext* blame_context) { |
| 661 main_thread_only().blame_context = blame_context; | 860 main_thread_only().blame_context = blame_context; |
| 662 } | 861 } |
| 663 | 862 |
| 664 // static | 863 // static |
| 665 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 864 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
| 666 base::trace_event::TracedValue* state) { | 865 base::trace_event::TracedValue* state) { |
| 667 // Remove const to search |queue| in the destructive manner. Restore the | 866 for (const Task& task : queue) { |
| 668 // content from |visited| later. | 867 TaskAsValueInto(task, state); |
| 669 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue); | |
| 670 std::queue<Task> visited; | |
| 671 while (!mutable_queue->empty()) { | |
| 672 TaskAsValueInto(mutable_queue->front(), state); | |
| 673 visited.push(std::move(mutable_queue->front())); | |
| 674 mutable_queue->pop(); | |
| 675 } | 868 } |
| 676 *mutable_queue = std::move(visited); | |
| 677 } | 869 } |
| 678 | 870 |
| 679 // static | 871 // static |
| 680 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, | 872 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
| 681 base::trace_event::TracedValue* state) { | 873 base::trace_event::TracedValue* state) { |
| 682 // Remove const to search |queue| in the destructive manner. Restore the | 874 for (const Task& task : queue) { |
| 683 // content from |visited| later. | 875 TaskAsValueInto(task, state); |
| 684 std::priority_queue<Task>* mutable_queue = | |
| 685 const_cast<std::priority_queue<Task>*>(&queue); | |
| 686 std::priority_queue<Task> visited; | |
| 687 while (!mutable_queue->empty()) { | |
| 688 TaskAsValueInto(mutable_queue->top(), state); | |
| 689 visited.push(std::move(const_cast<Task&>(mutable_queue->top()))); | |
| 690 mutable_queue->pop(); | |
| 691 } | 876 } |
| 692 *mutable_queue = std::move(visited); | |
| 693 } | 877 } |
| 694 | 878 |
| 695 // static | 879 // static |
| 696 void TaskQueueImpl::TaskAsValueInto(const Task& task, | 880 void TaskQueueImpl::TaskAsValueInto(const Task& task, |
| 697 base::trace_event::TracedValue* state) { | 881 base::trace_event::TracedValue* state) { |
| 698 state->BeginDictionary(); | 882 state->BeginDictionary(); |
| 699 state->SetString("posted_from", task.posted_from.ToString()); | 883 state->SetString("posted_from", task.posted_from.ToString()); |
| 700 #ifndef NDEBUG | 884 #ifndef NDEBUG |
| 701 if (task.enqueue_order_set()) | 885 if (task.enqueue_order_set()) |
| 702 state->SetInteger("enqueue_order", task.enqueue_order()); | 886 state->SetInteger("enqueue_order", task.enqueue_order()); |
| 703 #else | 887 #else |
| 704 state->SetInteger("enqueue_order", task.enqueue_order()); | 888 state->SetInteger("enqueue_order", task.enqueue_order()); |
| 705 #endif | 889 #endif |
| 706 state->SetInteger("sequence_num", task.sequence_num); | 890 state->SetInteger("sequence_num", task.sequence_num); |
| 707 state->SetBoolean("nestable", task.nestable); | 891 state->SetBoolean("nestable", task.nestable); |
| 708 state->SetBoolean("is_high_res", task.is_high_res); | 892 state->SetBoolean("is_high_res", task.is_high_res); |
| 709 state->SetDouble( | 893 state->SetDouble( |
| 710 "delayed_run_time", | 894 "delayed_run_time", |
| 711 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 895 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 712 state->EndDictionary(); | 896 state->EndDictionary(); |
| 713 } | 897 } |
| 714 | 898 |
| 715 } // namespace internal | 899 } // namespace internal |
| 716 } // namespace scheduler | 900 } // namespace scheduler |
| 717 } // namespace blink | 901 } // namespace blink |
| OLD | NEW |