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" |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 PushOntoDelayedIncomingQueueLocked( | 209 PushOntoDelayedIncomingQueueLocked( |
| 210 Task(from_here, task, time_domain_delayed_run_time, sequence_number, | 210 Task(from_here, task, time_domain_delayed_run_time, sequence_number, |
| 211 task_type != TaskType::NON_NESTABLE)); | 211 task_type != TaskType::NON_NESTABLE)); |
| 212 } | 212 } |
| 213 return true; | 213 return true; |
| 214 } | 214 } |
| 215 | 215 |
| 216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
| 217 Task pending_task, base::TimeTicks now) { | 217 Task pending_task, base::TimeTicks now) { |
| 218 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 218 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
| 219 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | |
| 219 | 220 |
| 220 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. | 221 // If |pending_task| is at the head of the queue, then make sure a wakeup |
| 221 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 222 // is requested. |
| 222 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 223 if (pending_task.delayed_run_time == |
|
Sami
2016/09/22 11:20:54
Looks like a use-after-move.
alex clarke (OOO till 29th)
2016/09/22 16:24:20
Done.
| |
| 223 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 224 main_thread_only().delayed_incoming_queue.top().delayed_run_time) { |
| 224 now); | 225 main_thread_only().time_domain->ScheduleDelayedWork( |
| 226 this, pending_task.delayed_run_time, now); | |
| 227 } | |
| 228 | |
| 225 TraceQueueSize(false); | 229 TraceQueueSize(false); |
| 226 } | 230 } |
| 227 | 231 |
| 228 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 232 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 229 any_thread().task_queue_manager->DidQueueTask(pending_task); | 233 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 230 | 234 |
| 231 int thread_hop_task_sequence_number = | 235 int thread_hop_task_sequence_number = |
| 232 any_thread().task_queue_manager->GetNextSequenceNumber(); | 236 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 233 PushOntoImmediateIncomingQueueLocked( | 237 PushOntoImmediateIncomingQueueLocked( |
| 234 FROM_HERE, | 238 FROM_HERE, |
| 235 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 239 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| 236 base::Passed(&pending_task)), | 240 base::Passed(&pending_task)), |
| 237 base::TimeTicks(), | 241 base::TimeTicks(), |
| 238 thread_hop_task_sequence_number, | 242 thread_hop_task_sequence_number, |
| 239 false); | 243 false); |
| 240 } | 244 } |
| 241 | 245 |
| 246 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | |
| 247 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 248 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | |
| 249 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | |
| 250 if (delayed_run_time < time_domain_now) { | |
| 251 // If |delayed_run_time| is in the past then push it onto the work queue | |
| 252 // immediately. To ensure the right task ordering we need to temporarily | |
| 253 // push it onto the |delayed_incoming_queue|. | |
| 254 delayed_run_time = time_domain_now; | |
| 255 pending_task.delayed_run_time = time_domain_now; | |
| 256 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | |
| 257 LazyNow lazy_now(time_domain_now); | |
| 258 WakeUpForDelayedWork(&lazy_now); | |
| 259 } else { | |
| 260 // If |delayed_run_time| is in the future we can queue it as normal. | |
| 261 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), | |
| 262 time_domain_now); | |
| 263 } | |
| 264 TraceQueueSize(false); | |
| 265 } | |
| 266 | |
| 242 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 267 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( |
| 243 const tracked_objects::Location& posted_from, | 268 const tracked_objects::Location& posted_from, |
| 244 const base::Closure& task, | 269 const base::Closure& task, |
| 245 base::TimeTicks desired_run_time, | 270 base::TimeTicks desired_run_time, |
| 246 EnqueueOrder sequence_number, | 271 EnqueueOrder sequence_number, |
| 247 bool nestable) { | 272 bool nestable) { |
| 248 if (any_thread().immediate_incoming_queue.empty()) | 273 if (any_thread().immediate_incoming_queue.empty()) |
| 249 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 274 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
| 250 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 275 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 251 // it run. | 276 // it run. |
| 252 if (any_thread().immediate_incoming_queue.empty()) { | 277 if (any_thread().immediate_incoming_queue.empty()) { |
| 253 // There's no point posting a DoWork for a disabled queue, however we can | 278 // There's no point posting a DoWork for a disabled queue, however we can |
| 254 // only tell if it's disabled from the main thread. | 279 // only tell if it's disabled from the main thread. |
| 255 if (base::PlatformThread::CurrentId() == thread_id_) { | 280 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 256 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) | 281 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) |
| 257 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 282 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 258 } else { | 283 } else { |
| 259 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 284 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 260 } | 285 } |
| 261 } | 286 } |
| 262 any_thread().immediate_incoming_queue.emplace( | 287 any_thread().immediate_incoming_queue.emplace( |
| 263 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); | 288 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber); |
| 264 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); | 289 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back()); |
| 265 TraceQueueSize(true); | 290 TraceQueueSize(true); |
| 266 } | 291 } |
| 267 | 292 |
| 268 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | |
| 269 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 270 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | |
| 271 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | |
| 272 // Make sure |delayed_run_time| isn't in the past. | |
| 273 if (delayed_run_time < time_domain_now) { | |
| 274 delayed_run_time = time_domain_now; | |
| 275 pending_task.delayed_run_time = time_domain_now; | |
| 276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | |
| 277 LazyNow lazy_now(time_domain_now); | |
| 278 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); | |
| 279 } else { | |
| 280 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | |
| 281 main_thread_only().time_domain->ScheduleDelayedWork( | |
| 282 this, delayed_run_time, main_thread_only().time_domain->Now()); | |
| 283 } | |
| 284 TraceQueueSize(false); | |
| 285 } | |
| 286 | |
| 287 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 293 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
| 288 if (main_thread_only().is_enabled == enabled) | 294 if (main_thread_only().is_enabled == enabled) |
| 289 return; | 295 return; |
| 290 main_thread_only().is_enabled = enabled; | 296 main_thread_only().is_enabled = enabled; |
| 291 if (!main_thread_only().task_queue_manager) | 297 if (!main_thread_only().task_queue_manager) |
| 292 return; | 298 return; |
| 293 if (enabled) { | 299 if (enabled) { |
| 294 // Note it's the job of the selector to tell the TaskQueueManager if | 300 // Note it's the job of the selector to tell the TaskQueueManager if |
| 295 // a DoWork needs posting. | 301 // a DoWork needs posting. |
| 296 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 302 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 327 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 333 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= |
| 328 main_thread_only().time_domain->CreateLazyNow().Now()) { | 334 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 329 return true; | 335 return true; |
| 330 } | 336 } |
| 331 | 337 |
| 332 // Finally tasks on |immediate_incoming_queue| count as immediate work. | 338 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 333 base::AutoLock lock(any_thread_lock_); | 339 base::AutoLock lock(any_thread_lock_); |
| 334 return !any_thread().immediate_incoming_queue.empty(); | 340 return !any_thread().immediate_incoming_queue.empty(); |
| 335 } | 341 } |
| 336 | 342 |
| 337 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 343 void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) { |
| 338 // Enqueue all delayed tasks that should be running now, skipping any that | 344 // Enqueue all delayed tasks that should be running now, skipping any that |
| 339 // have been canceled. | 345 // have been canceled. |
| 340 while (!main_thread_only().delayed_incoming_queue.empty()) { | 346 while (!main_thread_only().delayed_incoming_queue.empty()) { |
| 341 // TODO(alexclarke): Use extract() when C++17 is allowed. | |
| 342 Task& task = | 347 Task& task = |
| 343 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); | 348 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); |
| 344 if (task.task.IsCancelled()) { | 349 if (task.task.IsCancelled()) { |
| 345 main_thread_only().delayed_incoming_queue.pop(); | 350 main_thread_only().delayed_incoming_queue.pop(); |
| 346 continue; | 351 continue; |
| 347 } | 352 } |
| 348 if (task.delayed_run_time > lazy_now->Now()) | 353 if (task.delayed_run_time > lazy_now->Now()) |
| 349 break; | 354 break; |
| 350 task.set_enqueue_order( | 355 task.set_enqueue_order( |
| 351 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 356 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
| 352 main_thread_only().delayed_work_queue->Push(std::move(task)); | 357 main_thread_only().delayed_work_queue->Push(std::move(task)); |
| 353 main_thread_only().delayed_incoming_queue.pop(); | 358 main_thread_only().delayed_incoming_queue.pop(); |
| 354 } | 359 } |
| 360 | |
| 361 // Make sure the next wake up is scheduled. | |
| 362 if (!main_thread_only().delayed_incoming_queue.empty()) { | |
| 363 main_thread_only().time_domain->ScheduleDelayedWork( | |
| 364 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time, | |
| 365 lazy_now->Now()); | |
| 366 } | |
| 355 } | 367 } |
| 356 | 368 |
| 357 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { | 369 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() { |
| 358 if (!main_thread_only().task_queue_manager) | 370 if (!main_thread_only().task_queue_manager) |
| 359 return false; | 371 return false; |
| 360 | 372 |
| 361 if (!main_thread_only().immediate_work_queue->Empty()) | 373 if (!main_thread_only().immediate_work_queue->Empty()) |
| 362 return true; | 374 return true; |
| 363 | 375 |
| 364 base::AutoLock lock(any_thread_lock_); | 376 base::AutoLock lock(any_thread_lock_); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 main_thread_only().immediate_work_queue->Size()); | 457 main_thread_only().immediate_work_queue->Size()); |
| 446 state->SetInteger("delayed_work_queue_size", | 458 state->SetInteger("delayed_work_queue_size", |
| 447 main_thread_only().delayed_work_queue->Size()); | 459 main_thread_only().delayed_work_queue->Size()); |
| 448 if (!main_thread_only().delayed_incoming_queue.empty()) { | 460 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 449 base::TimeDelta delay_to_next_task = | 461 base::TimeDelta delay_to_next_task = |
| 450 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 462 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - |
| 451 main_thread_only().time_domain->CreateLazyNow().Now()); | 463 main_thread_only().time_domain->CreateLazyNow().Now()); |
| 452 state->SetDouble("delay_to_next_task_ms", | 464 state->SetDouble("delay_to_next_task_ms", |
| 453 delay_to_next_task.InMillisecondsF()); | 465 delay_to_next_task.InMillisecondsF()); |
| 454 } | 466 } |
| 467 if (main_thread_only().current_fence) | |
| 468 state->SetInteger("current_fence", main_thread_only().current_fence); | |
| 455 if (verbose_tracing_enabled) { | 469 if (verbose_tracing_enabled) { |
| 456 state->BeginArray("immediate_incoming_queue"); | 470 state->BeginArray("immediate_incoming_queue"); |
| 457 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 471 QueueAsValueInto(any_thread().immediate_incoming_queue, state); |
| 458 state->EndArray(); | 472 state->EndArray(); |
| 459 state->BeginArray("delayed_work_queue"); | 473 state->BeginArray("delayed_work_queue"); |
| 460 main_thread_only().delayed_work_queue->AsValueInto(state); | 474 main_thread_only().delayed_work_queue->AsValueInto(state); |
| 461 state->EndArray(); | 475 state->EndArray(); |
| 462 state->BeginArray("immediate_work_queue"); | 476 state->BeginArray("immediate_work_queue"); |
| 463 main_thread_only().immediate_work_queue->AsValueInto(state); | 477 main_thread_only().immediate_work_queue->AsValueInto(state); |
| 464 state->EndArray(); | 478 state->EndArray(); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 670 state->SetBoolean("is_cancelled", task.task.IsCancelled()); | 684 state->SetBoolean("is_cancelled", task.task.IsCancelled()); |
| 671 state->SetDouble( | 685 state->SetDouble( |
| 672 "delayed_run_time", | 686 "delayed_run_time", |
| 673 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 687 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 674 state->EndDictionary(); | 688 state->EndDictionary(); |
| 675 } | 689 } |
| 676 | 690 |
| 677 } // namespace internal | 691 } // namespace internal |
| 678 } // namespace scheduler | 692 } // namespace scheduler |
| 679 } // namespace blink | 693 } // namespace blink |
| OLD | NEW |