Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc

Issue 2590593002: Revert of [Reland] Scheduler refactoring to virtually eliminate redundant DoWorks (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 : task_queue_manager(task_queue_manager), time_domain(time_domain) {} 147 : task_queue_manager(task_queue_manager), time_domain(time_domain) {}
148 148
149 TaskQueueImpl::AnyThread::~AnyThread() {} 149 TaskQueueImpl::AnyThread::~AnyThread() {}
150 150
151 TaskQueueImpl::MainThreadOnly::MainThreadOnly( 151 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
152 TaskQueueManager* task_queue_manager, 152 TaskQueueManager* task_queue_manager,
153 TaskQueueImpl* task_queue, 153 TaskQueueImpl* task_queue,
154 TimeDomain* time_domain) 154 TimeDomain* time_domain)
155 : task_queue_manager(task_queue_manager), 155 : task_queue_manager(task_queue_manager),
156 time_domain(time_domain), 156 time_domain(time_domain),
157 delayed_work_queue( 157 delayed_work_queue(new WorkQueue(task_queue, "delayed")),
158 new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::DELAYED)), 158 immediate_work_queue(new WorkQueue(task_queue, "immediate")),
159 immediate_work_queue(new WorkQueue(task_queue,
160 "immediate",
161 WorkQueue::QueueType::IMMEDIATE)),
162 set_index(0), 159 set_index(0),
163 is_enabled_refcount(0), 160 is_enabled_refcount(0),
164 voter_refcount(0), 161 voter_refcount(0),
165 blame_context(nullptr), 162 blame_context(nullptr),
166 current_fence(0) {} 163 current_fence(0) {}
167 164
168 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 165 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
169 166
170 void TaskQueueImpl::UnregisterTaskQueue() { 167 void TaskQueueImpl::UnregisterTaskQueue() {
171 base::AutoLock lock(any_thread_lock_); 168 base::AutoLock lock(any_thread_lock_);
172 if (main_thread_only().time_domain) 169 if (main_thread_only().time_domain)
173 main_thread_only().time_domain->UnregisterQueue(this); 170 main_thread_only().time_domain->UnregisterQueue(this);
174 if (!any_thread().task_queue_manager) 171 if (!any_thread().task_queue_manager)
175 return; 172 return;
176 any_thread().time_domain = nullptr; 173 any_thread().time_domain = nullptr;
177 main_thread_only().time_domain = nullptr; 174 main_thread_only().time_domain = nullptr;
178 any_thread().task_queue_manager->UnregisterTaskQueue(this); 175 any_thread().task_queue_manager->UnregisterTaskQueue(this);
179 176
180 any_thread().task_queue_manager = nullptr; 177 any_thread().task_queue_manager = nullptr;
181 main_thread_only().task_queue_manager = nullptr; 178 main_thread_only().task_queue_manager = nullptr;
182 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); 179 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>();
183 any_thread().immediate_incoming_queue = std::queue<Task>(); 180 any_thread().immediate_incoming_queue = std::queue<Task>();
184 main_thread_only().immediate_work_queue.reset(); 181 main_thread_only().immediate_work_queue.reset();
185 main_thread_only().delayed_work_queue.reset(); 182 main_thread_only().delayed_work_queue.reset();
186 } 183 }
187 184
188 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { 185 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
186 base::AutoLock lock(any_thread_lock_);
189 return base::PlatformThread::CurrentId() == thread_id_; 187 return base::PlatformThread::CurrentId() == thread_id_;
190 } 188 }
191 189
192 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, 190 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
193 const base::Closure& task, 191 const base::Closure& task,
194 base::TimeDelta delay) { 192 base::TimeDelta delay) {
195 if (delay.is_zero()) 193 if (delay.is_zero())
196 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); 194 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
197 195
198 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); 196 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 } 318 }
321 TraceQueueSize(false); 319 TraceQueueSize(false);
322 } 320 }
323 321
324 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked( 322 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
325 const tracked_objects::Location& posted_from, 323 const tracked_objects::Location& posted_from,
326 const base::Closure& task, 324 const base::Closure& task,
327 base::TimeTicks desired_run_time, 325 base::TimeTicks desired_run_time,
328 EnqueueOrder sequence_number, 326 EnqueueOrder sequence_number,
329 bool nestable) { 327 bool nestable) {
328 if (any_thread().immediate_incoming_queue.empty())
329 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
330 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 330 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
331 // it run. 331 // it run.
332 if (any_thread().immediate_incoming_queue.empty()) { 332 if (any_thread().immediate_incoming_queue.empty()) {
333 // There's no point posting a DoWork for a blocked or disabled queue, 333 // There's no point posting a DoWork for a disabled queue, however we can
334 // although we can only determine that on the main thread. 334 // only tell if it's disabled from the main thread.
335 bool ensure_do_work_posted = !RunsTasksOnCurrentThread() || 335 if (base::PlatformThread::CurrentId() == thread_id_) {
336 (IsQueueEnabled() && !BlockedByFenceLocked()); 336 if (IsQueueEnabled() && !BlockedByFenceLocked())
337 any_thread().task_queue_manager->OnQueueHasImmediateWork( 337 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
338 this, ensure_do_work_posted); 338 } else {
339 any_thread().time_domain->OnQueueHasImmediateWork(this); 339 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
340 }
340 } 341 }
341
342 any_thread().immediate_incoming_queue.emplace( 342 any_thread().immediate_incoming_queue.emplace(
343 posted_from, task, desired_run_time, sequence_number, nestable, 343 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber);
344 sequence_number); 344 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back());
345 any_thread().task_queue_manager->DidQueueTask(
346 any_thread().immediate_incoming_queue.back());
347 TraceQueueSize(true); 345 TraceQueueSize(true);
348 } 346 }
349 347
350 void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() {
351 if (!main_thread_only().immediate_work_queue->Empty())
352 return;
353
354 base::AutoLock lock(any_thread_lock_);
355 if (any_thread().immediate_incoming_queue.empty())
356 return;
357
358 main_thread_only().immediate_work_queue->SwapLocked(
359 any_thread().immediate_incoming_queue);
360 }
361
362 void TaskQueueImpl::OnImmediateWorkQueueHasBecomeEmpty(
363 std::queue<TaskQueueImpl::Task>* work_queue) {
364 base::AutoLock lock(any_thread_lock_);
365 DCHECK(work_queue->empty());
366
367 if (any_thread().immediate_incoming_queue.empty())
368 return;
369
370 std::swap(any_thread().immediate_incoming_queue, *work_queue);
371 }
372
373 bool TaskQueueImpl::IsEmpty() const { 348 bool TaskQueueImpl::IsEmpty() const {
374 if (!main_thread_only().delayed_work_queue->Empty() || 349 if (!main_thread_only().delayed_work_queue->Empty() ||
375 !main_thread_only().delayed_incoming_queue.empty() || 350 !main_thread_only().delayed_incoming_queue.empty() ||
376 !main_thread_only().immediate_work_queue->Empty()) { 351 !main_thread_only().immediate_work_queue->Empty()) {
377 return false; 352 return false;
378 } 353 }
379 354
380 base::AutoLock lock(any_thread_lock_); 355 base::AutoLock lock(any_thread_lock_);
381 return any_thread().immediate_incoming_queue.empty(); 356 return any_thread().immediate_incoming_queue.empty();
382 } 357 }
(...skipping 29 matching lines...) Expand all
412 return !any_thread().immediate_incoming_queue.empty(); 387 return !any_thread().immediate_incoming_queue.empty();
413 } 388 }
414 389
415 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() { 390 base::Optional<base::TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
416 if (main_thread_only().delayed_incoming_queue.empty()) 391 if (main_thread_only().delayed_incoming_queue.empty())
417 return base::nullopt; 392 return base::nullopt;
418 393
419 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; 394 return main_thread_only().delayed_incoming_queue.top().delayed_run_time;
420 } 395 }
421 396
422 base::Optional<base::TimeTicks> TaskQueueImpl::WakeUpForDelayedWork( 397 void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
423 LazyNow* lazy_now) {
424 // Enqueue all delayed tasks that should be running now, skipping any that 398 // Enqueue all delayed tasks that should be running now, skipping any that
425 // have been canceled. 399 // have been canceled.
426 while (!main_thread_only().delayed_incoming_queue.empty()) { 400 while (!main_thread_only().delayed_incoming_queue.empty()) {
427 Task& task = 401 Task& task =
428 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top()); 402 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
429 if (task.task.IsCancelled()) { 403 if (task.task.IsCancelled()) {
430 main_thread_only().delayed_incoming_queue.pop(); 404 main_thread_only().delayed_incoming_queue.pop();
431 continue; 405 continue;
432 } 406 }
433 if (task.delayed_run_time > lazy_now->Now()) 407 if (task.delayed_run_time > lazy_now->Now())
434 break; 408 break;
435 task.set_enqueue_order( 409 task.set_enqueue_order(
436 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 410 main_thread_only().task_queue_manager->GetNextSequenceNumber());
437 main_thread_only().delayed_work_queue->Push(std::move(task)); 411 main_thread_only().delayed_work_queue->Push(std::move(task));
438 main_thread_only().delayed_incoming_queue.pop(); 412 main_thread_only().delayed_incoming_queue.pop();
439 } 413 }
440 414
441 // Make sure the next wake up is scheduled. 415 // Make sure the next wake up is scheduled.
442 if (!main_thread_only().delayed_incoming_queue.empty()) 416 if (!main_thread_only().delayed_incoming_queue.empty()) {
443 return main_thread_only().delayed_incoming_queue.top().delayed_run_time; 417 main_thread_only().time_domain->ScheduleDelayedWork(
418 this, main_thread_only().delayed_incoming_queue.top().delayed_run_time,
419 lazy_now->Now());
420 }
421 }
444 422
445 return base::Optional<base::TimeTicks>(); 423 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
424 if (!main_thread_only().task_queue_manager)
425 return false;
426
427 if (!main_thread_only().immediate_work_queue->Empty())
428 return true;
429
430 base::AutoLock lock(any_thread_lock_);
431 main_thread_only().immediate_work_queue->SwapLocked(
432 any_thread().immediate_incoming_queue);
433 // |immediate_work_queue| is now empty so updates are no longer required.
434 return false;
446 } 435 }
447 436
448 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { 437 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
449 bool is_tracing; 438 bool is_tracing;
450 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 439 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
451 &is_tracing); 440 &is_tracing);
452 if (!is_tracing) 441 if (!is_tracing)
453 return; 442 return;
454 443
455 // It's only safe to access the work queues from the main thread. 444 // It's only safe to access the work queues from the main thread.
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 // another way of asserting that UnregisterTaskQueue has not been called. 567 // another way of asserting that UnregisterTaskQueue has not been called.
579 DCHECK(any_thread().time_domain); 568 DCHECK(any_thread().time_domain);
580 if (!any_thread().time_domain) 569 if (!any_thread().time_domain)
581 return; 570 return;
582 DCHECK(main_thread_checker_.CalledOnValidThread()); 571 DCHECK(main_thread_checker_.CalledOnValidThread());
583 if (time_domain == main_thread_only().time_domain) 572 if (time_domain == main_thread_only().time_domain)
584 return; 573 return;
585 574
586 any_thread().time_domain = time_domain; 575 any_thread().time_domain = time_domain;
587 } 576 }
588 577 // We rely here on TimeDomain::MigrateQueue being thread-safe to use with
578 // TimeDomain::Register/UnregisterAsUpdatableTaskQueue.
589 main_thread_only().time_domain->MigrateQueue(this, time_domain); 579 main_thread_only().time_domain->MigrateQueue(this, time_domain);
590 main_thread_only().time_domain = time_domain; 580 main_thread_only().time_domain = time_domain;
591 } 581 }
592 582
593 TimeDomain* TaskQueueImpl::GetTimeDomain() const { 583 TimeDomain* TaskQueueImpl::GetTimeDomain() const {
594 if (base::PlatformThread::CurrentId() == thread_id_) 584 if (base::PlatformThread::CurrentId() == thread_id_)
595 return main_thread_only().time_domain; 585 return main_thread_only().time_domain;
596 586
597 base::AutoLock lock(any_thread_lock_); 587 base::AutoLock lock(any_thread_lock_);
598 return any_thread().time_domain; 588 return any_thread().time_domain;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 664
675 base::AutoLock lock(any_thread_lock_); 665 base::AutoLock lock(any_thread_lock_);
676 if (any_thread().immediate_incoming_queue.empty()) 666 if (any_thread().immediate_incoming_queue.empty())
677 return true; 667 return true;
678 668
679 return any_thread().immediate_incoming_queue.front().enqueue_order() > 669 return any_thread().immediate_incoming_queue.front().enqueue_order() >
680 main_thread_only().current_fence; 670 main_thread_only().current_fence;
681 } 671 }
682 672
683 bool TaskQueueImpl::BlockedByFenceLocked() const { 673 bool TaskQueueImpl::BlockedByFenceLocked() const {
684 any_thread_lock_.AssertAcquired();
685
686 if (!main_thread_only().current_fence) 674 if (!main_thread_only().current_fence)
687 return false; 675 return false;
688 676
689 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 677 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
690 !main_thread_only().delayed_work_queue->BlockedByFence()) { 678 !main_thread_only().delayed_work_queue->BlockedByFence()) {
691 return false; 679 return false;
692 } 680 }
693 681
694 if (any_thread().immediate_incoming_queue.empty()) 682 if (any_thread().immediate_incoming_queue.empty())
695 return true; 683 return true;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter> 815 std::unique_ptr<TaskQueueImpl::QueueEnabledVoter>
828 TaskQueueImpl::CreateQueueEnabledVoter() { 816 TaskQueueImpl::CreateQueueEnabledVoter() {
829 main_thread_only().voter_refcount++; 817 main_thread_only().voter_refcount++;
830 main_thread_only().is_enabled_refcount++; 818 main_thread_only().is_enabled_refcount++;
831 return base::MakeUnique<QueueEnabledVoterImpl>(this); 819 return base::MakeUnique<QueueEnabledVoterImpl>(this);
832 } 820 }
833 821
834 } // namespace internal 822 } // namespace internal
835 } // namespace scheduler 823 } // namespace scheduler
836 } // namespace blink 824 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698