| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 should_monitor_quiescence_(spec.should_monitor_quiescence), | 86 should_monitor_quiescence_(spec.should_monitor_quiescence), |
| 87 should_notify_observers_(spec.should_notify_observers), | 87 should_notify_observers_(spec.should_notify_observers), |
| 88 should_report_when_execution_blocked_( | 88 should_report_when_execution_blocked_( |
| 89 spec.should_report_when_execution_blocked) { | 89 spec.should_report_when_execution_blocked) { |
| 90 DCHECK(time_domain); | 90 DCHECK(time_domain); |
| 91 time_domain->RegisterQueue(this); | 91 time_domain->RegisterQueue(this); |
| 92 } | 92 } |
| 93 | 93 |
| 94 TaskQueueImpl::~TaskQueueImpl() { | 94 TaskQueueImpl::~TaskQueueImpl() { |
| 95 #if DCHECK_IS_ON() | 95 #if DCHECK_IS_ON() |
| 96 base::AutoLock lock(any_thread_lock_); | 96 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 97 // NOTE this check shouldn't fire because |TaskQueueManager::queues_| | 97 // NOTE this check shouldn't fire because |TaskQueueManager::queues_| |
| 98 // contains a strong reference to this TaskQueueImpl and the TaskQueueManager | 98 // contains a strong reference to this TaskQueueImpl and the TaskQueueManager |
| 99 // destructor calls UnregisterTaskQueue on all task queues. | 99 // destructor calls UnregisterTaskQueue on all task queues. |
| 100 DCHECK(any_thread().task_queue_manager == nullptr) | 100 DCHECK(any_thread().task_queue_manager == nullptr) |
| 101 << "UnregisterTaskQueue must be called first!"; | 101 << "UnregisterTaskQueue must be called first!"; |
| 102 | 102 |
| 103 #endif | 103 #endif |
| 104 } | 104 } |
| 105 | 105 |
| 106 TaskQueueImpl::Task::Task() | 106 TaskQueueImpl::Task::Task() |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 time_domain(time_domain), | 156 time_domain(time_domain), |
| 157 delayed_work_queue( | 157 delayed_work_queue( |
| 158 new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)), | 158 new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)), |
| 159 immediate_work_queue(new WorkQueue(task_queue, | 159 immediate_work_queue(new WorkQueue(task_queue, |
| 160 "immediate", | 160 "immediate", |
| 161 WorkQueue::QueueType::IMMEDIATE)), | 161 WorkQueue::QueueType::IMMEDIATE)), |
| 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 any_thread_lock_acquired_count(0) {} |
| 167 | 168 |
| 168 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 169 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
| 169 | 170 |
| 170 void TaskQueueImpl::UnregisterTaskQueue() { | 171 void TaskQueueImpl::UnregisterTaskQueue() { |
| 171 base::AutoLock lock(any_thread_lock_); | 172 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 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; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 205 if (delay.is_zero()) | 206 if (delay.is_zero()) |
| 206 return PostImmediateTaskImpl(from_here, task, TaskType::NON_NESTABLE); | 207 return PostImmediateTaskImpl(from_here, task, TaskType::NON_NESTABLE); |
| 207 | 208 |
| 208 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); | 209 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); |
| 209 } | 210 } |
| 210 | 211 |
| 211 bool TaskQueueImpl::PostImmediateTaskImpl( | 212 bool TaskQueueImpl::PostImmediateTaskImpl( |
| 212 const tracked_objects::Location& from_here, | 213 const tracked_objects::Location& from_here, |
| 213 const base::Closure& task, | 214 const base::Closure& task, |
| 214 TaskType task_type) { | 215 TaskType task_type) { |
| 215 base::AutoLock lock(any_thread_lock_); | 216 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 216 if (!any_thread().task_queue_manager) | 217 if (!any_thread().task_queue_manager) |
| 217 return false; | 218 return false; |
| 218 | 219 |
| 219 EnqueueOrder sequence_number = | 220 EnqueueOrder sequence_number = |
| 220 any_thread().task_queue_manager->GetNextSequenceNumber(); | 221 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 221 | 222 |
| 222 PushOntoImmediateIncomingQueueLocked( | 223 PushOntoImmediateIncomingQueueLocked( |
| 223 from_here, | 224 from_here, |
| 224 task, | 225 task, |
| 225 base::TimeTicks(), | 226 base::TimeTicks(), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 246 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 247 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 247 PushOntoDelayedIncomingQueueFromMainThread( | 248 PushOntoDelayedIncomingQueueFromMainThread( |
| 248 Task(from_here, task, time_domain_delayed_run_time, sequence_number, | 249 Task(from_here, task, time_domain_delayed_run_time, sequence_number, |
| 249 task_type != TaskType::NON_NESTABLE), | 250 task_type != TaskType::NON_NESTABLE), |
| 250 time_domain_now); | 251 time_domain_now); |
| 251 } else { | 252 } else { |
| 252 // NOTE posting a delayed task from a different thread is not expected to | 253 // NOTE posting a delayed task from a different thread is not expected to |
| 253 // be common. This pathway is less optimal than perhaps it could be | 254 // be common. This pathway is less optimal than perhaps it could be |
| 254 // because it causes two main thread tasks to be run. Should this | 255 // because it causes two main thread tasks to be run. Should this |
| 255 // assumption prove to be false in future, we may need to revisit this. | 256 // assumption prove to be false in future, we may need to revisit this. |
| 256 base::AutoLock lock(any_thread_lock_); | 257 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 257 if (!any_thread().task_queue_manager) | 258 if (!any_thread().task_queue_manager) |
| 258 return false; | 259 return false; |
| 259 | 260 |
| 260 EnqueueOrder sequence_number = | 261 EnqueueOrder sequence_number = |
| 261 any_thread().task_queue_manager->GetNextSequenceNumber(); | 262 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 262 | 263 |
| 263 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); | 264 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); |
| 264 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 265 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
| 265 PushOntoDelayedIncomingQueueLocked( | 266 PushOntoDelayedIncomingQueueLocked( |
| 266 Task(from_here, task, time_domain_delayed_run_time, sequence_number, | 267 Task(from_here, task, time_domain_delayed_run_time, sequence_number, |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 } | 352 } |
| 352 | 353 |
| 353 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { | 354 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() { |
| 354 if (!main_thread_only().immediate_work_queue->Empty()) | 355 if (!main_thread_only().immediate_work_queue->Empty()) |
| 355 return; | 356 return; |
| 356 | 357 |
| 357 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); | 358 main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue(); |
| 358 } | 359 } |
| 359 | 360 |
| 360 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { | 361 WTF::Deque<TaskQueueImpl::Task> TaskQueueImpl::TakeImmediateIncomingQueue() { |
| 361 base::AutoLock lock(any_thread_lock_); | 362 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 362 WTF::Deque<TaskQueueImpl::Task> queue; | 363 WTF::Deque<TaskQueueImpl::Task> queue; |
| 363 queue.swap(any_thread().immediate_incoming_queue); | 364 queue.swap(any_thread().immediate_incoming_queue); |
| 364 return queue; | 365 return queue; |
| 365 } | 366 } |
| 366 | 367 |
| 367 bool TaskQueueImpl::IsEmpty() const { | 368 bool TaskQueueImpl::IsEmpty() const { |
| 368 if (!main_thread_only().delayed_work_queue->Empty() || | 369 if (!main_thread_only().delayed_work_queue->Empty() || |
| 369 !main_thread_only().delayed_incoming_queue.empty() || | 370 !main_thread_only().delayed_incoming_queue.empty() || |
| 370 !main_thread_only().immediate_work_queue->Empty()) { | 371 !main_thread_only().immediate_work_queue->Empty()) { |
| 371 return false; | 372 return false; |
| 372 } | 373 } |
| 373 | 374 |
| 374 base::AutoLock lock(any_thread_lock_); | 375 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 375 return any_thread().immediate_incoming_queue.empty(); | 376 return any_thread().immediate_incoming_queue.empty(); |
| 376 } | 377 } |
| 377 | 378 |
| 378 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { | 379 size_t TaskQueueImpl::GetNumberOfPendingTasks() const { |
| 379 size_t task_count = 0; | 380 size_t task_count = 0; |
| 380 task_count += main_thread_only().delayed_work_queue->Size(); | 381 task_count += main_thread_only().delayed_work_queue->Size(); |
| 381 task_count += main_thread_only().delayed_incoming_queue.size(); | 382 task_count += main_thread_only().delayed_incoming_queue.size(); |
| 382 task_count += main_thread_only().immediate_work_queue->Size(); | 383 task_count += main_thread_only().immediate_work_queue->Size(); |
| 383 | 384 |
| 384 base::AutoLock lock(any_thread_lock_); | 385 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 385 task_count += any_thread().immediate_incoming_queue.size(); | 386 task_count += any_thread().immediate_incoming_queue.size(); |
| 386 return task_count; | 387 return task_count; |
| 387 } | 388 } |
| 388 | 389 |
| 389 bool TaskQueueImpl::HasPendingImmediateWork() const { | 390 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 390 // Any work queue tasks count as immediate work. | 391 // Any work queue tasks count as immediate work. |
| 391 if (!main_thread_only().delayed_work_queue->Empty() || | 392 if (!main_thread_only().delayed_work_queue->Empty() || |
| 392 !main_thread_only().immediate_work_queue->Empty()) { | 393 !main_thread_only().immediate_work_queue->Empty()) { |
| 393 return true; | 394 return true; |
| 394 } | 395 } |
| 395 | 396 |
| 396 // Tasks on |delayed_incoming_queue| that could run now, count as | 397 // Tasks on |delayed_incoming_queue| that could run now, count as |
| 397 // immediate work. | 398 // immediate work. |
| 398 if (!main_thread_only().delayed_incoming_queue.empty() && | 399 if (!main_thread_only().delayed_incoming_queue.empty() && |
| 399 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 400 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= |
| 400 main_thread_only().time_domain->CreateLazyNow().Now()) { | 401 main_thread_only().time_domain->CreateLazyNow().Now()) { |
| 401 return true; | 402 return true; |
| 402 } | 403 } |
| 403 | 404 |
| 404 // Finally tasks on |immediate_incoming_queue| count as immediate work. | 405 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
| 405 base::AutoLock lock(any_thread_lock_); | 406 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 406 return !any_thread().immediate_incoming_queue.empty(); | 407 return !any_thread().immediate_incoming_queue.empty(); |
| 407 } | 408 } |
| 408 | 409 |
| 409 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { | 410 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { |
| 410 // Note we don't scheduled a wakeup for disabled queues. | 411 // Note we don't scheduled a wakeup for disabled queues. |
| 411 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) | 412 if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled()) |
| 412 return base::nullopt; | 413 return base::nullopt; |
| 413 | 414 |
| 414 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; | 415 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; |
| 415 } | 416 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 priority); | 484 priority); |
| 484 } | 485 } |
| 485 | 486 |
| 486 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 487 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
| 487 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 488 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
| 488 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 489 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
| 489 return static_cast<TaskQueue::QueuePriority>(set_index); | 490 return static_cast<TaskQueue::QueuePriority>(set_index); |
| 490 } | 491 } |
| 491 | 492 |
| 492 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 493 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
| 493 base::AutoLock lock(any_thread_lock_); | 494 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 494 state->BeginDictionary(); | 495 state->BeginDictionary(); |
| 495 state->SetString("name", GetName()); | 496 state->SetString("name", GetName()); |
| 496 state->SetString( | 497 state->SetString( |
| 497 "task_queue_id", | 498 "task_queue_id", |
| 498 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( | 499 base::StringPrintf("%" PRIx64, static_cast<uint64_t>( |
| 499 reinterpret_cast<uintptr_t>(this)))); | 500 reinterpret_cast<uintptr_t>(this)))); |
| 500 state->SetBoolean("enabled", IsQueueEnabled()); | 501 state->SetBoolean("enabled", IsQueueEnabled()); |
| 501 state->SetString("time_domain_name", | 502 state->SetString("time_domain_name", |
| 502 main_thread_only().time_domain->GetName()); | 503 main_thread_only().time_domain->GetName()); |
| 503 bool verbose_tracing_enabled = false; | 504 bool verbose_tracing_enabled = false; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 const base::PendingTask& pending_task) { | 562 const base::PendingTask& pending_task) { |
| 562 DCHECK(should_notify_observers_); | 563 DCHECK(should_notify_observers_); |
| 563 for (auto& observer : main_thread_only().task_observers) | 564 for (auto& observer : main_thread_only().task_observers) |
| 564 observer.DidProcessTask(pending_task); | 565 observer.DidProcessTask(pending_task); |
| 565 if (main_thread_only().blame_context) | 566 if (main_thread_only().blame_context) |
| 566 main_thread_only().blame_context->Leave(); | 567 main_thread_only().blame_context->Leave(); |
| 567 } | 568 } |
| 568 | 569 |
| 569 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { | 570 void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) { |
| 570 { | 571 { |
| 571 base::AutoLock lock(any_thread_lock_); | 572 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 572 DCHECK(time_domain); | 573 DCHECK(time_domain); |
| 573 // NOTE this is similar to checking |any_thread().task_queue_manager| but | 574 // NOTE this is similar to checking |any_thread().task_queue_manager| but |
| 574 // the TaskQueueSelectorTests constructs TaskQueueImpl directly with a null | 575 // the TaskQueueSelectorTests constructs TaskQueueImpl directly with a null |
| 575 // task_queue_manager. Instead we check |any_thread().time_domain| which is | 576 // task_queue_manager. Instead we check |any_thread().time_domain| which is |
| 576 // another way of asserting that UnregisterTaskQueue has not been called. | 577 // another way of asserting that UnregisterTaskQueue has not been called. |
| 577 DCHECK(any_thread().time_domain); | 578 DCHECK(any_thread().time_domain); |
| 578 if (!any_thread().time_domain) | 579 if (!any_thread().time_domain) |
| 579 return; | 580 return; |
| 580 DCHECK(main_thread_checker_.CalledOnValidThread()); | 581 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 581 if (time_domain == main_thread_only().time_domain) | 582 if (time_domain == main_thread_only().time_domain) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 594 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 595 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 595 main_thread_only().delayed_incoming_queue.top().sequence_num}, | 596 main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| 596 time_domain->Now()); | 597 time_domain->Now()); |
| 597 } | 598 } |
| 598 } | 599 } |
| 599 | 600 |
| 600 TimeDomain* TaskQueueImpl::GetTimeDomain() const { | 601 TimeDomain* TaskQueueImpl::GetTimeDomain() const { |
| 601 if (base::PlatformThread::CurrentId() == thread_id_) | 602 if (base::PlatformThread::CurrentId() == thread_id_) |
| 602 return main_thread_only().time_domain; | 603 return main_thread_only().time_domain; |
| 603 | 604 |
| 604 base::AutoLock lock(any_thread_lock_); | 605 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 605 return any_thread().time_domain; | 606 return any_thread().time_domain; |
| 606 } | 607 } |
| 607 | 608 |
| 608 void TaskQueueImpl::SetBlameContext( | 609 void TaskQueueImpl::SetBlameContext( |
| 609 base::trace_event::BlameContext* blame_context) { | 610 base::trace_event::BlameContext* blame_context) { |
| 610 main_thread_only().blame_context = blame_context; | 611 main_thread_only().blame_context = blame_context; |
| 611 } | 612 } |
| 612 | 613 |
| 613 void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) { | 614 void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) { |
| 614 if (!main_thread_only().task_queue_manager) | 615 if (!main_thread_only().task_queue_manager) |
| 615 return; | 616 return; |
| 616 | 617 |
| 617 EnqueueOrder previous_fence = main_thread_only().current_fence; | 618 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 618 main_thread_only().current_fence = | 619 main_thread_only().current_fence = |
| 619 position == TaskQueue::InsertFencePosition::NOW | 620 position == TaskQueue::InsertFencePosition::NOW |
| 620 ? main_thread_only().task_queue_manager->GetNextSequenceNumber() | 621 ? main_thread_only().task_queue_manager->GetNextSequenceNumber() |
| 621 : static_cast<EnqueueOrder>(EnqueueOrderValues::BLOCKING_FENCE); | 622 : static_cast<EnqueueOrder>(EnqueueOrderValues::BLOCKING_FENCE); |
| 622 | 623 |
| 623 // Tasks posted after this point will have a strictly higher enqueue order | 624 // Tasks posted after this point will have a strictly higher enqueue order |
| 624 // and will be blocked from running. | 625 // and will be blocked from running. |
| 625 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( | 626 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 626 main_thread_only().current_fence); | 627 main_thread_only().current_fence); |
| 627 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( | 628 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 628 main_thread_only().current_fence); | 629 main_thread_only().current_fence); |
| 629 | 630 |
| 630 if (!task_unblocked && previous_fence && | 631 if (!task_unblocked && previous_fence && |
| 631 previous_fence < main_thread_only().current_fence) { | 632 previous_fence < main_thread_only().current_fence) { |
| 632 base::AutoLock lock(any_thread_lock_); | 633 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 633 if (!any_thread().immediate_incoming_queue.empty() && | 634 if (!any_thread().immediate_incoming_queue.empty() && |
| 634 any_thread().immediate_incoming_queue.front().enqueue_order() > | 635 any_thread().immediate_incoming_queue.front().enqueue_order() > |
| 635 previous_fence && | 636 previous_fence && |
| 636 any_thread().immediate_incoming_queue.front().enqueue_order() < | 637 any_thread().immediate_incoming_queue.front().enqueue_order() < |
| 637 main_thread_only().current_fence) { | 638 main_thread_only().current_fence) { |
| 638 task_unblocked = true; | 639 task_unblocked = true; |
| 639 } | 640 } |
| 640 } | 641 } |
| 641 | 642 |
| 642 if (IsQueueEnabled() && task_unblocked) { | 643 if (IsQueueEnabled() && task_unblocked) { |
| 643 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 644 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 644 FROM_HERE); | 645 FROM_HERE); |
| 645 } | 646 } |
| 646 } | 647 } |
| 647 | 648 |
| 648 void TaskQueueImpl::RemoveFence() { | 649 void TaskQueueImpl::RemoveFence() { |
| 649 if (!main_thread_only().task_queue_manager) | 650 if (!main_thread_only().task_queue_manager) |
| 650 return; | 651 return; |
| 651 | 652 |
| 652 EnqueueOrder previous_fence = main_thread_only().current_fence; | 653 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 653 main_thread_only().current_fence = 0; | 654 main_thread_only().current_fence = 0; |
| 654 | 655 |
| 655 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); | 656 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 656 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); | 657 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 657 | 658 |
| 658 if (!task_unblocked && previous_fence) { | 659 if (!task_unblocked && previous_fence) { |
| 659 base::AutoLock lock(any_thread_lock_); | 660 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 660 if (!any_thread().immediate_incoming_queue.empty() && | 661 if (!any_thread().immediate_incoming_queue.empty() && |
| 661 any_thread().immediate_incoming_queue.front().enqueue_order() > | 662 any_thread().immediate_incoming_queue.front().enqueue_order() > |
| 662 previous_fence) { | 663 previous_fence) { |
| 663 task_unblocked = true; | 664 task_unblocked = true; |
| 664 } | 665 } |
| 665 } | 666 } |
| 666 | 667 |
| 667 if (IsQueueEnabled() && task_unblocked) { | 668 if (IsQueueEnabled() && task_unblocked) { |
| 668 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( | 669 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 669 FROM_HERE); | 670 FROM_HERE); |
| 670 } | 671 } |
| 671 } | 672 } |
| 672 | 673 |
| 673 bool TaskQueueImpl::BlockedByFence() const { | 674 bool TaskQueueImpl::BlockedByFence() const { |
| 674 if (!main_thread_only().current_fence) | 675 if (!main_thread_only().current_fence) |
| 675 return false; | 676 return false; |
| 676 | 677 |
| 677 if (!main_thread_only().immediate_work_queue->BlockedByFence() || | 678 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 678 !main_thread_only().delayed_work_queue->BlockedByFence()) { | 679 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 679 return false; | 680 return false; |
| 680 } | 681 } |
| 681 | 682 |
| 682 base::AutoLock lock(any_thread_lock_); | 683 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 683 if (any_thread().immediate_incoming_queue.empty()) | 684 if (any_thread().immediate_incoming_queue.empty()) |
| 684 return true; | 685 return true; |
| 685 | 686 |
| 686 return any_thread().immediate_incoming_queue.front().enqueue_order() > | 687 return any_thread().immediate_incoming_queue.front().enqueue_order() > |
| 687 main_thread_only().current_fence; | 688 main_thread_only().current_fence; |
| 688 } | 689 } |
| 689 | 690 |
| 690 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { | 691 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const { |
| 691 if (!IsQueueEnabled()) | 692 if (!IsQueueEnabled()) |
| 692 return false; | 693 return false; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 | 806 |
| 806 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { | 807 void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) { |
| 807 if (!main_thread_only().task_queue_manager) | 808 if (!main_thread_only().task_queue_manager) |
| 808 return; | 809 return; |
| 809 | 810 |
| 810 if (enable) { | 811 if (enable) { |
| 811 // Check if there's any immediate work on either queue. | 812 // Check if there's any immediate work on either queue. |
| 812 bool immediate_queues_empty = | 813 bool immediate_queues_empty = |
| 813 main_thread_only().immediate_work_queue->Empty(); | 814 main_thread_only().immediate_work_queue->Empty(); |
| 814 if (immediate_queues_empty) { | 815 if (immediate_queues_empty) { |
| 815 base::AutoLock lock(any_thread_lock_); | 816 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 816 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); | 817 immediate_queues_empty = any_thread().immediate_incoming_queue.empty(); |
| 817 } | 818 } |
| 818 // Avoid holding the lock while we fire the notification. | 819 // Avoid holding the lock while we fire the notification. |
| 819 if (!immediate_queues_empty) | 820 if (!immediate_queues_empty) |
| 820 main_thread_only().time_domain->OnQueueHasImmediateWork(this); | 821 main_thread_only().time_domain->OnQueueHasImmediateWork(this); |
| 821 | 822 |
| 822 if (!main_thread_only().delayed_incoming_queue.empty()) { | 823 if (!main_thread_only().delayed_incoming_queue.empty()) { |
| 823 main_thread_only().time_domain->ScheduleDelayedWork( | 824 main_thread_only().time_domain->ScheduleDelayedWork( |
| 824 this, | 825 this, |
| 825 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 826 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 this, | 873 this, |
| 873 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, | 874 {main_thread_only().delayed_incoming_queue.top().delayed_run_time, |
| 874 main_thread_only().delayed_incoming_queue.top().sequence_num}, | 875 main_thread_only().delayed_incoming_queue.top().sequence_num}, |
| 875 main_thread_only().time_domain->Now()); | 876 main_thread_only().time_domain->Now()); |
| 876 } | 877 } |
| 877 } | 878 } |
| 878 } | 879 } |
| 879 | 880 |
| 880 void TaskQueueImpl::PushImmediateIncomingTaskForTest( | 881 void TaskQueueImpl::PushImmediateIncomingTaskForTest( |
| 881 TaskQueueImpl::Task&& task) { | 882 TaskQueueImpl::Task&& task) { |
| 882 base::AutoLock lock(any_thread_lock_); | 883 AnyThreadAutoLock lock = AcquireAnyThreadLock(); |
| 883 any_thread().immediate_incoming_queue.push_back(std::move(task)); | 884 any_thread().immediate_incoming_queue.push_back(std::move(task)); |
| 884 } | 885 } |
| 885 | 886 |
| 887 TaskQueueImpl::AnyThreadAutoLock TaskQueueImpl::AcquireAnyThreadLock() const { |
| 888 size_t* any_thread_lock_acquired_from_main_thread_count = nullptr; |
| 889 if (thread_id_ == base::PlatformThread::CurrentId()) |
| 890 any_thread_lock_acquired_from_main_thread_count = |
| 891 &main_thread_only().any_thread_lock_acquired_count; |
| 892 return AnyThreadAutoLock(any_thread_lock_, |
| 893 any_thread_lock_acquired_from_main_thread_count); |
| 894 } |
| 895 |
| 896 TaskQueueImpl::AnyThreadAutoLock::AnyThreadAutoLock(base::Lock& lock, |
| 897 size_t* acquired_count) |
| 898 : lock_(lock), acquired_count_(acquired_count) { |
| 899 if (!acquired_count_ || *acquired_count_ == 0) { |
| 900 lock_.Acquire(); |
| 901 } |
| 902 if (acquired_count_) |
| 903 ++*acquired_count_; |
| 904 lock_.AssertAcquired(); |
| 905 } |
| 906 |
| 907 TaskQueueImpl::AnyThreadAutoLock::~AnyThreadAutoLock() { |
| 908 lock_.AssertAcquired(); |
| 909 if (acquired_count_) |
| 910 --*acquired_count_; |
| 911 if (!acquired_count_ || *acquired_count_ == 0) |
| 912 lock_.Release(); |
| 913 } |
| 914 |
| 886 } // namespace internal | 915 } // namespace internal |
| 887 } // namespace scheduler | 916 } // namespace scheduler |
| 888 } // namespace blink | 917 } // namespace blink |
| OLD | NEW |