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 |