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

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

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

Powered by Google App Engine
This is Rietveld 408576698