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/format_macros.h" | 7 #include "base/format_macros.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/trace_event/blame_context.h" | 10 #include "base/trace_event/blame_context.h" |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 set_index(0), | 162 set_index(0), |
| 163 is_enabled_refcount(0), | 163 is_enabled_refcount(0), |
| 164 voter_refcount(0), | 164 voter_refcount(0), |
| 165 blame_context(nullptr), | 165 blame_context(nullptr), |
| 166 current_fence(0) {} | 166 current_fence(0) {} |
| 167 | 167 |
| 168 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 168 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 169 | 169 |
| 170 void TaskQueueImpl::UnregisterTaskQueue() { | 170 void TaskQueueImpl::UnregisterTaskQueue() { |
| 171 base::AutoLock lock(any_thread_lock_); | 171 base::AutoLock lock(any_thread_lock_); |
| 172 base::AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); | |
| 172 if (main_thread_only().time_domain) | 173 if (main_thread_only().time_domain) |
| 173 main_thread_only().time_domain->UnregisterQueue(this); | 174 main_thread_only().time_domain->UnregisterQueue(this); |
| 174 if (!any_thread().task_queue_manager) | 175 if (!any_thread().task_queue_manager) |
| 175 return; | 176 return; |
| 176 any_thread().time_domain = nullptr; | 177 any_thread().time_domain = nullptr; |
| 177 main_thread_only().time_domain = nullptr; | 178 main_thread_only().time_domain = nullptr; |
| 178 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 179 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
| 179 | 180 |
| 180 any_thread().task_queue_manager = nullptr; | 181 any_thread().task_queue_manager = nullptr; |
| 181 main_thread_only().task_queue_manager = nullptr; | 182 main_thread_only().task_queue_manager = nullptr; |
| 182 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); | 183 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); |
| 183 any_thread().immediate_incoming_queue.clear(); | 184 immediate_incoming_queue().clear(); |
| 184 main_thread_only().immediate_work_queue.reset(); | 185 main_thread_only().immediate_work_queue.reset(); |
| 185 main_thread_only().delayed_work_queue.reset(); | 186 main_thread_only().delayed_work_queue.reset(); |
| 186 } | 187 } |
| 187 | 188 |
| 188 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 189 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
| 189 return base::PlatformThread::CurrentId() == thread_id_; | 190 return base::PlatformThread::CurrentId() == thread_id_; |
| 190 } | 191 } |
| 191 | 192 |
| 192 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 193 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
| 193 const base::Closure& task, | 194 const base::Closure& task, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 // is requested if the queue is enabled. Note we still want to schedule a | 280 // is requested if the queue is enabled. Note we still want to schedule a |
| 280 // wakeup even if blocked by a fence, because we'd break throttling logic | 281 // wakeup even if blocked by a fence, because we'd break throttling logic |
| 281 // otherwise. | 282 // otherwise. |
| 282 base::TimeTicks next_delayed_task = | 283 base::TimeTicks next_delayed_task = |
| 283 main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 284 main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 284 if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { | 285 if (next_delayed_task == delayed_run_time && IsQueueEnabled()) { |
| 285 main_thread_only().time_domain->ScheduleDelayedWork( | 286 main_thread_only().time_domain->ScheduleDelayedWork( |
| 286 this, {delayed_run_time, pending_task.sequence_num}, now); | 287 this, {delayed_run_time, pending_task.sequence_num}, now); |
| 287 } | 288 } |
| 288 | 289 |
| 289 TraceQueueSize(false); | 290 TraceQueueSize(); |
| 290 } | 291 } |
| 291 | 292 |
| 292 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 293 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
| 293 any_thread().task_queue_manager->DidQueueTask(pending_task); | 294 any_thread().task_queue_manager->DidQueueTask(pending_task); |
| 294 | 295 |
| 295 int thread_hop_task_sequence_number = | 296 int thread_hop_task_sequence_number = |
| 296 any_thread().task_queue_manager->GetNextSequenceNumber(); | 297 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 297 PushOntoImmediateIncomingQueueLocked( | 298 PushOntoImmediateIncomingQueueLocked( |
| 298 FROM_HERE, | 299 FROM_HERE, |
| 299 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 300 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 314 delayed_run_time = time_domain_now; | 315 delayed_run_time = time_domain_now; |
| 315 pending_task.delayed_run_time = time_domain_now; | 316 pending_task.delayed_run_time = time_domain_now; |
| 316 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 317 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); |
| 317 LazyNow lazy_now(time_domain_now); | 318 LazyNow lazy_now(time_domain_now); |
| 318 WakeUpForDelayedWork(&lazy_now); | 319 WakeUpForDelayedWork(&lazy_now); |
| 319 } else { | 320 } else { |
| 320 // If |delayed_run_time| is in the future we can queue it as normal. | 321 // If |delayed_run_time| is in the future we can queue it as normal. |
| 321 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), | 322 PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task), |
| 322 time_domain_now); | 323 time_domain_now); |
| 323 } | 324 } |
| 324 TraceQueueSize(false); | 325 TraceQueueSize(); |
| 325 } | 326 } |
| 326 | 327 |
| 327 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( | 328 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( |
| 328 const tracked_objects::Location& posted_from, | 329 const tracked_objects::Location& posted_from, |
| 329 const base::Closure& task, | 330 const base::Closure& task, |
| 330 base::TimeTicks desired_run_time, | 331 base::TimeTicks desired_run_time, |
| 331 EnqueueOrder sequence_number, | 332 EnqueueOrder sequence_number, |
| 332 bool nestable) { | 333 bool nestable) { |
| 333 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make | 334 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 334 // it run. | 335 // it run. |
| 335 if (any_thread().immediate_incoming_queue.empty()) { | 336 bool is_immediate_incoming_queue_empty; |
| 337 { | |
| 338 base::AutoLock lock(immediate_incoming_queue_lock_); | |
| 339 is_immediate_incoming_queue_empty = immediate_incoming_queue().empty(); | |
| 340 } | |
| 341 if (is_immediate_incoming_queue_empty) { | |
| 336 // However there's no point posting a DoWork for a blocked queue. NB we can | 342 // However there's no point posting a DoWork for a blocked queue. NB we can |
| 337 // only tell if it's disabled from the main thread. | 343 // only tell if it's disabled from the main thread. |
| 338 bool queue_is_blocked = | 344 bool queue_is_blocked = |
| 339 RunsTasksOnCurrentThread() && | 345 RunsTasksOnCurrentThread() && |
| 340 (!IsQueueEnabled() || main_thread_only().current_fence); | 346 (!IsQueueEnabled() || main_thread_only().current_fence); |
| 341 any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork( | 347 any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork( |
| 342 this, sequence_number, queue_is_blocked); | 348 this, sequence_number, queue_is_blocked); |
| 343 any_thread().time_domain->OnQueueHasImmediateWork(this); | 349 any_thread().time_domain->OnQueueHasImmediateWork(this); |
| 344 } | 350 } |
| 345 any_thread().immediate_incoming_queue.emplace_back( | 351 |
| 346 posted_from, task, desired_run_time, sequence_number, nestable, | 352 Task* queued_task; |
| 347 sequence_number); | 353 { |
| 348 any_thread().task_queue_manager->DidQueueTask( | 354 base::AutoLock lock(immediate_incoming_queue_lock_); |
|
alex clarke (OOO till 29th)
2017/03/30 13:23:46
Can we avoid locking this twice?
altimin
2017/03/30 14:04:36
Done.
| |
| 349 any_thread().immediate_incoming_queue.back()); | 355 immediate_incoming_queue().emplace_back(posted_from, task, desired_run_time, |
| 350 TraceQueueSize(true); | 356 sequence_number, nestable, |
| 357 sequence_number); | |
| 358 queued_task = &immediate_incoming_queue().back(); | |
| 359 } | |
| 360 any_thread().task_queue_manager->DidQueueTask(*queued_task); | |
| 361 TraceQueueSize(); | |
| 351 } | 362 } |
| 352 | 363 |
| 353 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { | 364 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { |
| 354 if (!main_thread_only().immediate_work_queue->Empty()) | 365 if (!main_thread_only().immediate_work_queue->Empty()) |
| 355 return; | 366 return; |
| 356 | 367 |
| 357 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); | 368 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); |
| 358 } | 369 } |
| 359 | 370 |
| 360 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { | 371 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { |
| 361 base::AutoLock lock(any_thread_lock_); | 372 base::AutoLock lock(any_thread_lock_); |
| 373 base::AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); | |
| 362 WTF::Deque<TaskQueueImpl::Task> queue; | 374 WTF::Deque<TaskQueueImpl::Task> queue; |
| 363 queue.swap(any_thread().immediate_incoming_queue); | 375 queue.swap(immediate_incoming_queue()); |
| 364 return queue; | 376 return queue; |
| 365 } | 377 } |
| 366 | 378 |
| 367 bool TaskQueueImpl::IsEmpty() const { | 379 bool TaskQueueImpl::IsEmpty() const { |
| 368 if (!main_thread_only().delayed_work_queue->Empty() || | 380 if (!main_thread_only().delayed_work_queue->Empty() || |
| 369 !main_thread_only().delayed_incoming_queue.empty() || | 381 !main_thread_only().delayed_incoming_queue.empty() || |
| 370 !main_thread_only().immediate_work_queue->Empty()) { | 382 !main_thread_only().immediate_work_queue->Empty()) { |
| 371 return false; | 383 return false; |
| 372 } | 384 } |
| 373 | 385 |
| 374 base::AutoLock lock(any_thread_lock_); | 386 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 375 return any_thread().immediate_incoming_queue.empty(); | 387 return immediate_incoming_queue().empty(); |
| 376 } | 388 } |
| 377 | 389 |
| 378 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { | 390 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { |
| 379 size_t task_count = 0; | 391 size_t task_count = 0; |
| 380 task_count += main_thread_only().delayed_work_queue->Size(); | 392 task_count += main_thread_only().delayed_work_queue->Size(); |
| 381 task_count += main_thread_only().delayed_incoming_queue.size(); | 393 task_count += main_thread_only().delayed_incoming_queue.size(); |
| 382 task_count += main_thread_only().immediate_work_queue->Size(); | 394 task_count += main_thread_only().immediate_work_queue->Size(); |
| 383 | 395 |
| 384 base::AutoLock lock(any_thread_lock_); | 396 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 385 task_count += any_thread().immediate_incoming_queue.size(); | 397 task_count += immediate_incoming_queue().size(); |
| 386 return task_count; | 398 return task_count; |
| 387 } | 399 } |
| 388 | 400 |
| 389 bool TaskQueueImpl::HasPendingImmediateWork() const { | 401 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 390 // Any work queue tasks count as immediate work. | 402 // Any work queue tasks count as immediate work. |
| 391 if (!main_thread_only().delayed_work_queue->Empty() || | 403 if (!main_thread_only().delayed_work_queue->Empty() || |
| 392 !main_thread_only().immediate_work_queue->Empty()) { | 404 !main_thread_only().immediate_work_queue->Empty()) { |
| 393 return true; | 405 return true; |
| 394 } | 406 } |
| 395 | 407 |
| 396 // Tasks on |delayed_incoming_queue| that could run now, count as | 408 // Tasks on |delayed_incoming_queue| that could run now, count as |
| 397 // immediate work. | 409 // immediate work. |
| 398 if (!main_thread_only().delayed_incoming_queue.empty() && | 410 if (!main_thread_only().delayed_incoming_queue.empty() && |
| 399 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 411 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= |
| 400 main_thread_only().time_domain->CreateLazyNow().Now()) { | 412 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 401 return true; | 413 return true; |
| 402 } | 414 } |
| 403 | 415 |
| 404 // Finally tasks on |immediate_incoming_queue| count as immediate work. | 416 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 405 base::AutoLock lock(any_thread_lock_); | 417 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 406 return !any_thread().immediate_incoming_queue.empty(); | 418 return !immediate_incoming_queue().empty(); |
| 407 } | 419 } |
| 408 | 420 |
| 409 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { | 421 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { |
| 410 // Note we don't scheduled a wakeup for disabled queues. | 422 // Note we don't scheduled a wakeup for disabled queues. |
| 411 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) | 423 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) |
| 412 return base::nullopt; | 424 return base::nullopt; |
| 413 | 425 |
| 414 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 426 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 415 } | 427 } |
| 416 | 428 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 436 // Make sure the next wake up is scheduled. | 448 // Make sure the next wake up is scheduled. |
| 437 if (!main_thread_only().delayed_incoming_queue.empty()) { | 449 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 438 return DelayedWakeUp{ | 450 return DelayedWakeUp{ |
| 439 main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 451 main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 440 main_thread_only().delayed_incoming_queue.top().sequence_num}; | 452 main_thread_only().delayed_incoming_queue.top().sequence_num}; |
| 441 } | 453 } |
| 442 | 454 |
| 443 return base::nullopt; | 455 return base::nullopt; |
| 444 } | 456 } |
| 445 | 457 |
| 446 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { | 458 void TaskQueueImpl::TraceQueueSize() const { |
| 447 bool is_tracing; | 459 bool is_tracing; |
| 448 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, | 460 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, |
| 449 &is_tracing); | 461 &is_tracing); |
| 450 if (!is_tracing) | 462 if (!is_tracing) |
| 451 return; | 463 return; |
| 452 | 464 |
| 453 // It's only safe to access the work queues from the main thread. | 465 // It's only safe to access the work queues from the main thread. |
| 454 // TODO(alexclarke): We should find another way of tracing this | 466 // TODO(alexclarke): We should find another way of tracing this |
| 455 if (base::PlatformThread::CurrentId() != thread_id_) | 467 if (base::PlatformThread::CurrentId() != thread_id_) |
| 456 return; | 468 return; |
| 457 | 469 |
| 458 if (!is_locked) | 470 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 459 any_thread_lock_.Acquire(); | |
| 460 else | |
| 461 any_thread_lock_.AssertAcquired(); | |
| 462 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), | 471 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), |
| 463 any_thread().immediate_incoming_queue.size() + | 472 immediate_incoming_queue().size() + |
| 464 main_thread_only().immediate_work_queue->Size() + | 473 main_thread_only().immediate_work_queue->Size() + |
| 465 main_thread_only().delayed_work_queue->Size() + | 474 main_thread_only().delayed_work_queue->Size() + |
| 466 main_thread_only().delayed_incoming_queue.size()); | 475 main_thread_only().delayed_incoming_queue.size()); |
| 467 if (!is_locked) | |
| 468 any_thread_lock_.Release(); | |
| 469 } | 476 } |
| 470 | 477 |
| 471 const char* TaskQueueImpl::GetName() const { | 478 const char* TaskQueueImpl::GetName() const { |
| 472 return name_; | 479 return name_; |
| 473 } | 480 } |
| 474 | 481 |
| 475 TaskQueue::QueueType TaskQueueImpl::GetQueueType() const { | 482 TaskQueue::QueueType TaskQueueImpl::GetQueueType() const { |
| 476 return type_; | 483 return type_; |
| 477 } | 484 } |
| 478 | 485 |
| 479 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { | 486 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { |
| 480 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) | 487 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) |
| 481 return; | 488 return; |
| 482 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, | 489 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, |
| 483 priority); | 490 priority); |
| 484 } | 491 } |
| 485 | 492 |
| 486 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 493 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
| 487 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 494 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
| 488 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 495 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
| 489 return static_cast<TaskQueue::QueuePriority>(set_index); | 496 return static_cast<TaskQueue::QueuePriority>(set_index); |
| 490 } | 497 } |
| 491 | 498 |
| 492 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 499 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
| 493 base::AutoLock lock(any_thread_lock_); | 500 base::AutoLock lock(any_thread_lock_); |
| 501 base::AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); | |
| 494 state->BeginDictionary(); | 502 state->BeginDictionary(); |
| 495 state->SetString("name", GetName()); | 503 state->SetString("name", GetName()); |
| 496 state->SetString( | 504 state->SetString( |
| 497 "task_queue_id", | 505 "task_queue_id", |
| 498 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( | 506 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( |
| 499 reinterpret_cast<uintptr_t>(this)))); | 507 reinterpret_cast<uintptr_t>(this)))); |
| 500 state->SetBoolean("enabled", IsQueueEnabled()); | 508 state->SetBoolean("enabled", IsQueueEnabled()); |
| 501 state->SetString("time_domain_name", | 509 state->SetString("time_domain_name", |
| 502 main_thread_only().time_domain->GetName()); | 510 main_thread_only().time_domain->GetName()); |
| 503 bool verbose_tracing_enabled = false; | 511 bool verbose_tracing_enabled = false; |
| 504 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 512 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
| 505 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 513 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |
| 506 state->SetInteger("immediate_incoming_queue_size", | 514 state->SetInteger("immediate_incoming_queue_size", |
| 507 any_thread().immediate_incoming_queue.size()); | 515 immediate_incoming_queue().size()); |
| 508 state->SetInteger("delayed_incoming_queue_size", | 516 state->SetInteger("delayed_incoming_queue_size", |
| 509 main_thread_only().delayed_incoming_queue.size()); | 517 main_thread_only().delayed_incoming_queue.size()); |
| 510 state->SetInteger("immediate_work_queue_size", | 518 state->SetInteger("immediate_work_queue_size", |
| 511 main_thread_only().immediate_work_queue->Size()); | 519 main_thread_only().immediate_work_queue->Size()); |
| 512 state->SetInteger("delayed_work_queue_size", | 520 state->SetInteger("delayed_work_queue_size", |
| 513 main_thread_only().delayed_work_queue->Size()); | 521 main_thread_only().delayed_work_queue->Size()); |
| 514 if (!main_thread_only().delayed_incoming_queue.empty()) { | 522 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 515 base::TimeDelta delay_to_next_task = | 523 base::TimeDelta delay_to_next_task = |
| 516 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 524 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - |
| 517 main_thread_only().time_domain->CreateLazyNow().Now()); | 525 main_thread_only().time_domain->CreateLazyNow().Now()); |
| 518 state->SetDouble("delay_to_next_task_ms", | 526 state->SetDouble("delay_to_next_task_ms", |
| 519 delay_to_next_task.InMillisecondsF()); | 527 delay_to_next_task.InMillisecondsF()); |
| 520 } | 528 } |
| 521 if (main_thread_only().current_fence) | 529 if (main_thread_only().current_fence) |
| 522 state->SetInteger("current_fence", main_thread_only().current_fence); | 530 state->SetInteger("current_fence", main_thread_only().current_fence); |
| 523 if (verbose_tracing_enabled) { | 531 if (verbose_tracing_enabled) { |
| 524 state->BeginArray("immediate_incoming_queue"); | 532 state->BeginArray("immediate_incoming_queue"); |
| 525 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 533 QueueAsValueInto(immediate_incoming_queue(), state); |
| 526 state->EndArray(); | 534 state->EndArray(); |
| 527 state->BeginArray("delayed_work_queue"); | 535 state->BeginArray("delayed_work_queue"); |
| 528 main_thread_only().delayed_work_queue->AsValueInto(state); | 536 main_thread_only().delayed_work_queue->AsValueInto(state); |
| 529 state->EndArray(); | 537 state->EndArray(); |
| 530 state->BeginArray("immediate_work_queue"); | 538 state->BeginArray("immediate_work_queue"); |
| 531 main_thread_only().immediate_work_queue->AsValueInto(state); | 539 main_thread_only().immediate_work_queue->AsValueInto(state); |
| 532 state->EndArray(); | 540 state->EndArray(); |
| 533 state->BeginArray("delayed_incoming_queue"); | 541 state->BeginArray("delayed_incoming_queue"); |
| 534 QueueAsValueInto(main_thread_only().delayed_incoming_queue, state); | 542 QueueAsValueInto(main_thread_only().delayed_incoming_queue, state); |
| 535 state->EndArray(); | 543 state->EndArray(); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 | 630 |
| 623 // Tasks posted after this point will have a strictly higher enqueue order | 631 // Tasks posted after this point will have a strictly higher enqueue order |
| 624 // and will be blocked from running. | 632 // and will be blocked from running. |
| 625 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( | 633 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 626 main_thread_only().current_fence); | 634 main_thread_only().current_fence); |
| 627 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( | 635 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 628 main_thread_only().current_fence); | 636 main_thread_only().current_fence); |
| 629 | 637 |
| 630 if (!task_unblocked && previous_fence && | 638 if (!task_unblocked && previous_fence && |
| 631 previous_fence < main_thread_only().current_fence) { | 639 previous_fence < main_thread_only().current_fence) { |
| 632 base::AutoLock lock(any_thread_lock_); | 640 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 633 if (!any_thread().immediate_incoming_queue.empty() && | 641 if (!immediate_incoming_queue().empty() && |
| 634 any_thread().immediate_incoming_queue.front().enqueue_order() > | 642 immediate_incoming_queue().front().enqueue_order() > previous_fence && |
| 635 previous_fence && | 643 immediate_incoming_queue().front().enqueue_order() < |
| 636 any_thread().immediate_incoming_queue.front().enqueue_order() < | |
| 637 main_thread_only().current_fence) { | 644 main_thread_only().current_fence) { |
| 638 task_unblocked = true; | 645 task_unblocked = true; |
| 639 } | 646 } |
| 640 } | 647 } |
| 641 | 648 |
| 642 if (IsQueueEnabled() && task_unblocked) { | 649 if (IsQueueEnabled() && task_unblocked) { |
| 643 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 650 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 644 FROM_HERE); | 651 FROM_HERE); |
| 645 } | 652 } |
| 646 } | 653 } |
| 647 | 654 |
| 648 void TaskQueueImpl::RemoveFence() { | 655 void TaskQueueImpl::RemoveFence() { |
| 649 if (!main_thread_only().task_queue_manager) | 656 if (!main_thread_only().task_queue_manager) |
| 650 return; | 657 return; |
| 651 | 658 |
| 652 EnqueueOrder previous_fence = main_thread_only().current_fence; | 659 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 653 main_thread_only().current_fence = 0; | 660 main_thread_only().current_fence = 0; |
| 654 | 661 |
| 655 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); | 662 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 656 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); | 663 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 657 | 664 |
| 658 if (!task_unblocked && previous_fence) { | 665 if (!task_unblocked && previous_fence) { |
| 659 base::AutoLock lock(any_thread_lock_); | 666 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 660 if (!any_thread().immediate_incoming_queue.empty() && | 667 if (!immediate_incoming_queue().empty() && |
| 661 any_thread().immediate_incoming_queue.front().enqueue_order() > | 668 immediate_incoming_queue().front().enqueue_order() > previous_fence) { |
| 662 previous_fence) { | |
| 663 task_unblocked = true; | 669 task_unblocked = true; |
| 664 } | 670 } |
| 665 } | 671 } |
| 666 | 672 |
| 667 if (IsQueueEnabled() && task_unblocked) { | 673 if (IsQueueEnabled() && task_unblocked) { |
| 668 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 674 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 669 FROM_HERE); | 675 FROM_HERE); |
| 670 } | 676 } |
| 671 } | 677 } |
| 672 | 678 |
| 673 bool TaskQueueImpl::BlockedByFence() const { | 679 bool TaskQueueImpl::BlockedByFence() const { |
| 674 if (!main_thread_only().current_fence) | 680 if (!main_thread_only().current_fence) |
| 675 return false; | 681 return false; |
| 676 | 682 |
| 677 if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 683 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 678 !main_thread_only().delayed_work_queue->BlockedByFence()) { | 684 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 679 return false; | 685 return false; |
| 680 } | 686 } |
| 681 | 687 |
| 682 base::AutoLock lock(any_thread_lock_); | 688 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 683 if (any_thread().immediate_incoming_queue.empty()) | 689 if (immediate_incoming_queue().empty()) |
| 684 return true; | 690 return true; |
| 685 | 691 |
| 686 return any_thread().immediate_incoming_queue.front().enqueue_order() > | 692 return immediate_incoming_queue().front().enqueue_order() > |
| 687 main_thread_only().current_fence; | 693 main_thread_only().current_fence; |
| 688 } | 694 } |
| 689 | 695 |
| 690 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { | 696 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { |
| 691 if (!IsQueueEnabled()) | 697 if (!IsQueueEnabled()) |
| 692 return false; | 698 return false; |
| 693 | 699 |
| 694 if (!main_thread_only().current_fence) | 700 if (!main_thread_only().current_fence) |
| 695 return true; | 701 return true; |
| 696 | 702 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 805 | 811 |
| 806 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { | 812 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { |
| 807 if (!main_thread_only().task_queue_manager) | 813 if (!main_thread_only().task_queue_manager) |
| 808 return; | 814 return; |
| 809 | 815 |
| 810 if (enable) { | 816 if (enable) { |
| 811 // Check if there's any immediate work on either queue. | 817 // Check if there's any immediate work on either queue. |
| 812 bool immediate_queues_empty = | 818 bool immediate_queues_empty = |
| 813 main_thread_only().immediate_work_queue->Empty(); | 819 main_thread_only().immediate_work_queue->Empty(); |
| 814 if (immediate_queues_empty) { | 820 if (immediate_queues_empty) { |
| 815 base::AutoLock lock(any_thread_lock_); | 821 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 816 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); | 822 immediate_queues_empty = immediate_incoming_queue().empty(); |
| 817 } | 823 } |
| 818 // Avoid holding the lock while we fire the notification. | 824 // Avoid holding the lock while we fire the notification. |
| 819 if (!immediate_queues_empty) | 825 if (!immediate_queues_empty) |
| 820 main_thread_only().time_domain->OnQueueHasImmediateWork(this); | 826 main_thread_only().time_domain->OnQueueHasImmediateWork(this); |
| 821 | 827 |
| 822 if (!main_thread_only().delayed_incoming_queue.empty()) { | 828 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 823 main_thread_only().time_domain->ScheduleDelayedWork( | 829 main_thread_only().time_domain->ScheduleDelayedWork( |
| 824 this, | 830 this, |
| 825 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 831 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 826 main_thread_only().delayed_incoming_queue.top().sequence_num}, | 832 main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 872 this, | 878 this, |
| 873 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 879 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 874 main_thread_only().delayed_incoming_queue.top().sequence_num}, | 880 main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| 875 main_thread_only().time_domain->Now()); | 881 main_thread_only().time_domain->Now()); |
| 876 } | 882 } |
| 877 } | 883 } |
| 878 } | 884 } |
| 879 | 885 |
| 880 void TaskQueueImpl::PushImmediateIncomingTaskForTest( | 886 void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
| 881 TaskQueueImpl::Task&& task) { | 887 TaskQueueImpl::Task&& task) { |
| 882 base::AutoLock lock(any_thread_lock_); | 888 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 883 any_thread().immediate_incoming_queue.push_back(std::move(task)); | 889 immediate_incoming_queue().push_back(std::move(task)); |
| 884 } | 890 } |
| 885 | 891 |
| 886 } // namespace internal | 892 } // namespace internal |
| 887 } // namespace scheduler | 893 } // namespace scheduler |
| 888 } // namespace blink | 894 } // namespace blink |
| OLD | NEW |