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