| 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 was_immediate_incoming_queue_empty; |
| 340 |
| 341 { |
| 342 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 343 was_immediate_incoming_queue_empty = immediate_incoming_queue().empty(); |
| 344 immediate_incoming_queue().emplace_back(posted_from, std::move(task), |
| 345 desired_run_time, sequence_number, |
| 346 nestable, sequence_number); |
| 347 any_thread().task_queue_manager->DidQueueTask( |
| 348 immediate_incoming_queue().back()); |
| 349 } |
| 350 |
| 351 if (was_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 TraceQueueSize(); |
| 350 sequence_number); | |
| 351 any_thread().task_queue_manager->DidQueueTask( | |
| 352 any_thread().immediate_incoming_queue.back()); | |
| 353 TraceQueueSize(true); | |
| 354 } | 363 } |
| 355 | 364 |
| 356 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { | 365 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { |
| 357 if (!main_thread_only().immediate_work_queue->Empty()) | 366 if (!main_thread_only().immediate_work_queue->Empty()) |
| 358 return; | 367 return; |
| 359 | 368 |
| 360 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); | 369 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); |
| 361 } | 370 } |
| 362 | 371 |
| 363 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { | 372 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { |
| 364 base::AutoLock lock(any_thread_lock_); | 373 base::AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); |
| 365 WTF::Deque<TaskQueueImpl::Task> queue; | 374 WTF::Deque<TaskQueueImpl::Task> queue; |
| 366 queue.swap(any_thread().immediate_incoming_queue); | 375 queue.swap(immediate_incoming_queue()); |
| 367 return queue; | 376 return queue; |
| 368 } | 377 } |
| 369 | 378 |
| 370 bool TaskQueueImpl::IsEmpty() const { | 379 bool TaskQueueImpl::IsEmpty() const { |
| 371 if (!main_thread_only().delayed_work_queue->Empty() || | 380 if (!main_thread_only().delayed_work_queue->Empty() || |
| 372 !main_thread_only().delayed_incoming_queue.empty() || | 381 !main_thread_only().delayed_incoming_queue.empty() || |
| 373 !main_thread_only().immediate_work_queue->Empty()) { | 382 !main_thread_only().immediate_work_queue->Empty()) { |
| 374 return false; | 383 return false; |
| 375 } | 384 } |
| 376 | 385 |
| 377 base::AutoLock lock(any_thread_lock_); | 386 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 378 return any_thread().immediate_incoming_queue.empty(); | 387 return immediate_incoming_queue().empty(); |
| 379 } | 388 } |
| 380 | 389 |
| 381 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { | 390 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { |
| 382 size_t task_count = 0; | 391 size_t task_count = 0; |
| 383 task_count += main_thread_only().delayed_work_queue->Size(); | 392 task_count += main_thread_only().delayed_work_queue->Size(); |
| 384 task_count += main_thread_only().delayed_incoming_queue.size(); | 393 task_count += main_thread_only().delayed_incoming_queue.size(); |
| 385 task_count += main_thread_only().immediate_work_queue->Size(); | 394 task_count += main_thread_only().immediate_work_queue->Size(); |
| 386 | 395 |
| 387 base::AutoLock lock(any_thread_lock_); | 396 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 388 task_count += any_thread().immediate_incoming_queue.size(); | 397 task_count += immediate_incoming_queue().size(); |
| 389 return task_count; | 398 return task_count; |
| 390 } | 399 } |
| 391 | 400 |
| 392 bool TaskQueueImpl::HasPendingImmediateWork() const { | 401 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 393 // Any work queue tasks count as immediate work. | 402 // Any work queue tasks count as immediate work. |
| 394 if (!main_thread_only().delayed_work_queue->Empty() || | 403 if (!main_thread_only().delayed_work_queue->Empty() || |
| 395 !main_thread_only().immediate_work_queue->Empty()) { | 404 !main_thread_only().immediate_work_queue->Empty()) { |
| 396 return true; | 405 return true; |
| 397 } | 406 } |
| 398 | 407 |
| 399 // Tasks on |delayed_incoming_queue| that could run now, count as | 408 // Tasks on |delayed_incoming_queue| that could run now, count as |
| 400 // immediate work. | 409 // immediate work. |
| 401 if (!main_thread_only().delayed_incoming_queue.empty() && | 410 if (!main_thread_only().delayed_incoming_queue.empty() && |
| 402 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 411 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= |
| 403 main_thread_only().time_domain->CreateLazyNow().Now()) { | 412 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 404 return true; | 413 return true; |
| 405 } | 414 } |
| 406 | 415 |
| 407 // Finally tasks on |immediate_incoming_queue| count as immediate work. | 416 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 408 base::AutoLock lock(any_thread_lock_); | 417 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 409 return !any_thread().immediate_incoming_queue.empty(); | 418 return !immediate_incoming_queue().empty(); |
| 410 } | 419 } |
| 411 | 420 |
| 412 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { | 421 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { |
| 413 // Note we don't scheduled a wakeup for disabled queues. | 422 // Note we don't scheduled a wakeup for disabled queues. |
| 414 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) | 423 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) |
| 415 return base::nullopt; | 424 return base::nullopt; |
| 416 | 425 |
| 417 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 426 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 418 } | 427 } |
| 419 | 428 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 439 // Make sure the next wake up is scheduled. | 448 // Make sure the next wake up is scheduled. |
| 440 if (!main_thread_only().delayed_incoming_queue.empty()) { | 449 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 441 return DelayedWakeUp{ | 450 return DelayedWakeUp{ |
| 442 main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 451 main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 443 main_thread_only().delayed_incoming_queue.top().sequence_num}; | 452 main_thread_only().delayed_incoming_queue.top().sequence_num}; |
| 444 } | 453 } |
| 445 | 454 |
| 446 return base::nullopt; | 455 return base::nullopt; |
| 447 } | 456 } |
| 448 | 457 |
| 449 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { | 458 void TaskQueueImpl::TraceQueueSize() const { |
| 450 bool is_tracing; | 459 bool is_tracing; |
| 451 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, | 460 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, |
| 452 &is_tracing); | 461 &is_tracing); |
| 453 if (!is_tracing) | 462 if (!is_tracing) |
| 454 return; | 463 return; |
| 455 | 464 |
| 456 // 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. |
| 457 // TODO(alexclarke): We should find another way of tracing this | 466 // TODO(alexclarke): We should find another way of tracing this |
| 458 if (base::PlatformThread::CurrentId() != thread_id_) | 467 if (base::PlatformThread::CurrentId() != thread_id_) |
| 459 return; | 468 return; |
| 460 | 469 |
| 461 if (!is_locked) | 470 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(), | 471 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), |
| 466 any_thread().immediate_incoming_queue.size() + | 472 immediate_incoming_queue().size() + |
| 467 main_thread_only().immediate_work_queue->Size() + | 473 main_thread_only().immediate_work_queue->Size() + |
| 468 main_thread_only().delayed_work_queue->Size() + | 474 main_thread_only().delayed_work_queue->Size() + |
| 469 main_thread_only().delayed_incoming_queue.size()); | 475 main_thread_only().delayed_incoming_queue.size()); |
| 470 if (!is_locked) | |
| 471 any_thread_lock_.Release(); | |
| 472 } | 476 } |
| 473 | 477 |
| 474 const char* TaskQueueImpl::GetName() const { | 478 const char* TaskQueueImpl::GetName() const { |
| 475 return name_; | 479 return name_; |
| 476 } | 480 } |
| 477 | 481 |
| 478 TaskQueue::QueueType TaskQueueImpl::GetQueueType() const { | 482 TaskQueue::QueueType TaskQueueImpl::GetQueueType() const { |
| 479 return type_; | 483 return type_; |
| 480 } | 484 } |
| 481 | 485 |
| 482 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { | 486 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { |
| 483 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) | 487 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) |
| 484 return; | 488 return; |
| 485 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, | 489 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, |
| 486 priority); | 490 priority); |
| 487 } | 491 } |
| 488 | 492 |
| 489 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 493 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
| 490 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 494 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
| 491 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 495 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
| 492 return static_cast<TaskQueue::QueuePriority>(set_index); | 496 return static_cast<TaskQueue::QueuePriority>(set_index); |
| 493 } | 497 } |
| 494 | 498 |
| 495 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 499 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
| 496 base::AutoLock lock(any_thread_lock_); | 500 base::AutoLock lock(any_thread_lock_); |
| 501 base::AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_); |
| 497 state->BeginDictionary(); | 502 state->BeginDictionary(); |
| 498 state->SetString("name", GetName()); | 503 state->SetString("name", GetName()); |
| 499 state->SetString( | 504 state->SetString( |
| 500 "task_queue_id", | 505 "task_queue_id", |
| 501 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( | 506 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( |
| 502 reinterpret_cast<uintptr_t>(this)))); | 507 reinterpret_cast<uintptr_t>(this)))); |
| 503 state->SetBoolean("enabled", IsQueueEnabled()); | 508 state->SetBoolean("enabled", IsQueueEnabled()); |
| 504 state->SetString("time_domain_name", | 509 state->SetString("time_domain_name", |
| 505 main_thread_only().time_domain->GetName()); | 510 main_thread_only().time_domain->GetName()); |
| 506 bool verbose_tracing_enabled = false; | 511 bool verbose_tracing_enabled = false; |
| 507 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 512 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
| 508 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 513 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |
| 509 state->SetInteger("immediate_incoming_queue_size", | 514 state->SetInteger("immediate_incoming_queue_size", |
| 510 any_thread().immediate_incoming_queue.size()); | 515 immediate_incoming_queue().size()); |
| 511 state->SetInteger("delayed_incoming_queue_size", | 516 state->SetInteger("delayed_incoming_queue_size", |
| 512 main_thread_only().delayed_incoming_queue.size()); | 517 main_thread_only().delayed_incoming_queue.size()); |
| 513 state->SetInteger("immediate_work_queue_size", | 518 state->SetInteger("immediate_work_queue_size", |
| 514 main_thread_only().immediate_work_queue->Size()); | 519 main_thread_only().immediate_work_queue->Size()); |
| 515 state->SetInteger("delayed_work_queue_size", | 520 state->SetInteger("delayed_work_queue_size", |
| 516 main_thread_only().delayed_work_queue->Size()); | 521 main_thread_only().delayed_work_queue->Size()); |
| 517 if (!main_thread_only().delayed_incoming_queue.empty()) { | 522 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 518 base::TimeDelta delay_to_next_task = | 523 base::TimeDelta delay_to_next_task = |
| 519 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 524 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - |
| 520 main_thread_only().time_domain->CreateLazyNow().Now()); | 525 main_thread_only().time_domain->CreateLazyNow().Now()); |
| 521 state->SetDouble("delay_to_next_task_ms", | 526 state->SetDouble("delay_to_next_task_ms", |
| 522 delay_to_next_task.InMillisecondsF()); | 527 delay_to_next_task.InMillisecondsF()); |
| 523 } | 528 } |
| 524 if (main_thread_only().current_fence) | 529 if (main_thread_only().current_fence) |
| 525 state->SetInteger("current_fence", main_thread_only().current_fence); | 530 state->SetInteger("current_fence", main_thread_only().current_fence); |
| 526 if (verbose_tracing_enabled) { | 531 if (verbose_tracing_enabled) { |
| 527 state->BeginArray("immediate_incoming_queue"); | 532 state->BeginArray("immediate_incoming_queue"); |
| 528 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 533 QueueAsValueInto(immediate_incoming_queue(), state); |
| 529 state->EndArray(); | 534 state->EndArray(); |
| 530 state->BeginArray("delayed_work_queue"); | 535 state->BeginArray("delayed_work_queue"); |
| 531 main_thread_only().delayed_work_queue->AsValueInto(state); | 536 main_thread_only().delayed_work_queue->AsValueInto(state); |
| 532 state->EndArray(); | 537 state->EndArray(); |
| 533 state->BeginArray("immediate_work_queue"); | 538 state->BeginArray("immediate_work_queue"); |
| 534 main_thread_only().immediate_work_queue->AsValueInto(state); | 539 main_thread_only().immediate_work_queue->AsValueInto(state); |
| 535 state->EndArray(); | 540 state->EndArray(); |
| 536 state->BeginArray("delayed_incoming_queue"); | 541 state->BeginArray("delayed_incoming_queue"); |
| 537 QueueAsValueInto(main_thread_only().delayed_incoming_queue, state); | 542 QueueAsValueInto(main_thread_only().delayed_incoming_queue, state); |
| 538 state->EndArray(); | 543 state->EndArray(); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 | 630 |
| 626 // 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 |
| 627 // and will be blocked from running. | 632 // and will be blocked from running. |
| 628 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( | 633 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 629 main_thread_only().current_fence); | 634 main_thread_only().current_fence); |
| 630 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( | 635 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 631 main_thread_only().current_fence); | 636 main_thread_only().current_fence); |
| 632 | 637 |
| 633 if (!task_unblocked && previous_fence && | 638 if (!task_unblocked && previous_fence && |
| 634 previous_fence < main_thread_only().current_fence) { | 639 previous_fence < main_thread_only().current_fence) { |
| 635 base::AutoLock lock(any_thread_lock_); | 640 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 636 if (!any_thread().immediate_incoming_queue.empty() && | 641 if (!immediate_incoming_queue().empty() && |
| 637 any_thread().immediate_incoming_queue.front().enqueue_order() > | 642 immediate_incoming_queue().front().enqueue_order() > previous_fence && |
| 638 previous_fence && | 643 immediate_incoming_queue().front().enqueue_order() < |
| 639 any_thread().immediate_incoming_queue.front().enqueue_order() < | |
| 640 main_thread_only().current_fence) { | 644 main_thread_only().current_fence) { |
| 641 task_unblocked = true; | 645 task_unblocked = true; |
| 642 } | 646 } |
| 643 } | 647 } |
| 644 | 648 |
| 645 if (IsQueueEnabled() && task_unblocked) { | 649 if (IsQueueEnabled() && task_unblocked) { |
| 646 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 650 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 647 FROM_HERE); | 651 FROM_HERE); |
| 648 } | 652 } |
| 649 } | 653 } |
| 650 | 654 |
| 651 void TaskQueueImpl::RemoveFence() { | 655 void TaskQueueImpl::RemoveFence() { |
| 652 if (!main_thread_only().task_queue_manager) | 656 if (!main_thread_only().task_queue_manager) |
| 653 return; | 657 return; |
| 654 | 658 |
| 655 EnqueueOrder previous_fence = main_thread_only().current_fence; | 659 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 656 main_thread_only().current_fence = 0; | 660 main_thread_only().current_fence = 0; |
| 657 | 661 |
| 658 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); | 662 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 659 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); | 663 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 660 | 664 |
| 661 if (!task_unblocked && previous_fence) { | 665 if (!task_unblocked && previous_fence) { |
| 662 base::AutoLock lock(any_thread_lock_); | 666 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 663 if (!any_thread().immediate_incoming_queue.empty() && | 667 if (!immediate_incoming_queue().empty() && |
| 664 any_thread().immediate_incoming_queue.front().enqueue_order() > | 668 immediate_incoming_queue().front().enqueue_order() > previous_fence) { |
| 665 previous_fence) { | |
| 666 task_unblocked = true; | 669 task_unblocked = true; |
| 667 } | 670 } |
| 668 } | 671 } |
| 669 | 672 |
| 670 if (IsQueueEnabled() && task_unblocked) { | 673 if (IsQueueEnabled() && task_unblocked) { |
| 671 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 674 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 672 FROM_HERE); | 675 FROM_HERE); |
| 673 } | 676 } |
| 674 } | 677 } |
| 675 | 678 |
| 676 bool TaskQueueImpl::BlockedByFence() const { | 679 bool TaskQueueImpl::BlockedByFence() const { |
| 677 if (!main_thread_only().current_fence) | 680 if (!main_thread_only().current_fence) |
| 678 return false; | 681 return false; |
| 679 | 682 |
| 680 if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 683 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 681 !main_thread_only().delayed_work_queue->BlockedByFence()) { | 684 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 682 return false; | 685 return false; |
| 683 } | 686 } |
| 684 | 687 |
| 685 base::AutoLock lock(any_thread_lock_); | 688 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 686 if (any_thread().immediate_incoming_queue.empty()) | 689 if (immediate_incoming_queue().empty()) |
| 687 return true; | 690 return true; |
| 688 | 691 |
| 689 return any_thread().immediate_incoming_queue.front().enqueue_order() > | 692 return immediate_incoming_queue().front().enqueue_order() > |
| 690 main_thread_only().current_fence; | 693 main_thread_only().current_fence; |
| 691 } | 694 } |
| 692 | 695 |
| 693 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { | 696 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { |
| 694 if (!IsQueueEnabled()) | 697 if (!IsQueueEnabled()) |
| 695 return false; | 698 return false; |
| 696 | 699 |
| 697 if (!main_thread_only().current_fence) | 700 if (!main_thread_only().current_fence) |
| 698 return true; | 701 return true; |
| 699 | 702 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 808 | 811 |
| 809 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { | 812 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { |
| 810 if (!main_thread_only().task_queue_manager) | 813 if (!main_thread_only().task_queue_manager) |
| 811 return; | 814 return; |
| 812 | 815 |
| 813 if (enable) { | 816 if (enable) { |
| 814 // Check if there's any immediate work on either queue. | 817 // Check if there's any immediate work on either queue. |
| 815 bool immediate_queues_empty = | 818 bool immediate_queues_empty = |
| 816 main_thread_only().immediate_work_queue->Empty(); | 819 main_thread_only().immediate_work_queue->Empty(); |
| 817 if (immediate_queues_empty) { | 820 if (immediate_queues_empty) { |
| 818 base::AutoLock lock(any_thread_lock_); | 821 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 819 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); | 822 immediate_queues_empty = immediate_incoming_queue().empty(); |
| 820 } | 823 } |
| 821 // Avoid holding the lock while we fire the notification. | 824 // Avoid holding the lock while we fire the notification. |
| 822 if (!immediate_queues_empty) | 825 if (!immediate_queues_empty) |
| 823 main_thread_only().time_domain->OnQueueHasImmediateWork(this); | 826 main_thread_only().time_domain->OnQueueHasImmediateWork(this); |
| 824 | 827 |
| 825 if (!main_thread_only().delayed_incoming_queue.empty()) { | 828 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 826 main_thread_only().time_domain->ScheduleDelayedWork( | 829 main_thread_only().time_domain->ScheduleDelayedWork( |
| 827 this, | 830 this, |
| 828 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 831 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 829 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... |
| 875 this, | 878 this, |
| 876 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 879 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 877 main_thread_only().delayed_incoming_queue.top().sequence_num}, | 880 main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| 878 main_thread_only().time_domain->Now()); | 881 main_thread_only().time_domain->Now()); |
| 879 } | 882 } |
| 880 } | 883 } |
| 881 } | 884 } |
| 882 | 885 |
| 883 void TaskQueueImpl::PushImmediateIncomingTaskForTest( | 886 void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
| 884 TaskQueueImpl::Task&& task) { | 887 TaskQueueImpl::Task&& task) { |
| 885 base::AutoLock lock(any_thread_lock_); | 888 base::AutoLock lock(immediate_incoming_queue_lock_); |
| 886 any_thread().immediate_incoming_queue.push_back(std::move(task)); | 889 immediate_incoming_queue().push_back(std::move(task)); |
| 887 } | 890 } |
| 888 | 891 |
| 889 } // namespace internal | 892 } // namespace internal |
| 890 } // namespace scheduler | 893 } // namespace scheduler |
| 891 } // namespace blink | 894 } // namespace blink |
| OLD | NEW |