| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "base/message_loop/message_loop.h" | 5 #include "base/message_loop/message_loop.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 DCHECK_EQ(this, current()); | 383 DCHECK_EQ(this, current()); |
| 384 DCHECK(run_loop_); | 384 DCHECK(run_loop_); |
| 385 CHECK(allow_nesting_ || run_loop_->run_depth_ == 1); | 385 CHECK(allow_nesting_ || run_loop_->run_depth_ == 1); |
| 386 pump_->Run(this); | 386 pump_->Run(this); |
| 387 } | 387 } |
| 388 | 388 |
| 389 bool MessageLoop::ProcessNextDelayedNonNestableTask() { | 389 bool MessageLoop::ProcessNextDelayedNonNestableTask() { |
| 390 if (run_loop_->run_depth_ != 1) | 390 if (run_loop_->run_depth_ != 1) |
| 391 return false; | 391 return false; |
| 392 | 392 |
| 393 if (deferred_non_nestable_work_queue_.empty()) | 393 while (!deferred_non_nestable_work_queue_.empty()) { |
| 394 return false; | 394 PendingTask pending_task = |
| 395 std::move(deferred_non_nestable_work_queue_.front()); |
| 396 deferred_non_nestable_work_queue_.pop(); |
| 395 | 397 |
| 396 PendingTask pending_task = | 398 if (pending_task.task.IsCancelled()) { |
| 397 std::move(deferred_non_nestable_work_queue_.front()); | 399 #if defined(OS_WIN) |
| 398 deferred_non_nestable_work_queue_.pop(); | 400 if (pending_task.is_high_res) { |
| 401 pending_high_res_tasks_--; |
| 402 CHECK_GE(pending_high_res_tasks_, 0); |
| 403 } |
| 404 #endif |
| 405 continue; |
| 406 } |
| 399 | 407 |
| 400 RunTask(&pending_task); | 408 RunTask(&pending_task); |
| 401 return true; | 409 return true; |
| 410 } |
| 411 |
| 412 return false; |
| 402 } | 413 } |
| 403 | 414 |
| 404 void MessageLoop::RunTask(PendingTask* pending_task) { | 415 void MessageLoop::RunTask(PendingTask* pending_task) { |
| 405 DCHECK(nestable_tasks_allowed_); | 416 DCHECK(nestable_tasks_allowed_); |
| 406 | 417 |
| 407 #if defined(OS_WIN) | 418 #if defined(OS_WIN) |
| 408 if (pending_task->is_high_res) { | 419 if (pending_task->is_high_res) { |
| 409 pending_high_res_tasks_--; | 420 pending_high_res_tasks_--; |
| 410 CHECK_GE(pending_high_res_tasks_, 0); | 421 CHECK_GE(pending_high_res_tasks_, 0); |
| 411 } | 422 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 437 // and the task isn't nestable. | 448 // and the task isn't nestable. |
| 438 deferred_non_nestable_work_queue_.push(std::move(pending_task)); | 449 deferred_non_nestable_work_queue_.push(std::move(pending_task)); |
| 439 return false; | 450 return false; |
| 440 } | 451 } |
| 441 | 452 |
| 442 void MessageLoop::AddToDelayedWorkQueue(PendingTask pending_task) { | 453 void MessageLoop::AddToDelayedWorkQueue(PendingTask pending_task) { |
| 443 // Move to the delayed work queue. | 454 // Move to the delayed work queue. |
| 444 delayed_work_queue_.push(std::move(pending_task)); | 455 delayed_work_queue_.push(std::move(pending_task)); |
| 445 } | 456 } |
| 446 | 457 |
| 458 bool MessageLoop::SweepDelayedWorkQueue() { |
| 459 DCHECK(!delayed_work_queue_.empty()); |
| 460 |
| 461 do { |
| 462 const auto& pending_task = delayed_work_queue_.top(); |
| 463 if (pending_task.task.IsCancelled()) { |
| 464 #if defined(OS_WIN) |
| 465 if (pending_task.is_high_res) { |
| 466 pending_high_res_tasks_--; |
| 467 CHECK_GE(pending_high_res_tasks_, 0); |
| 468 } |
| 469 #endif |
| 470 delayed_work_queue_.pop(); |
| 471 continue; |
| 472 } else { |
| 473 return false; |
| 474 } |
| 475 } while (!delayed_work_queue_.empty()); |
| 476 |
| 477 return true; |
| 478 } |
| 479 |
| 447 bool MessageLoop::DeletePendingTasks() { | 480 bool MessageLoop::DeletePendingTasks() { |
| 448 bool did_work = !work_queue_.empty(); | 481 bool did_work = !work_queue_.empty(); |
| 449 while (!work_queue_.empty()) { | 482 while (!work_queue_.empty()) { |
| 450 PendingTask pending_task = std::move(work_queue_.front()); | 483 PendingTask pending_task = std::move(work_queue_.front()); |
| 451 work_queue_.pop(); | 484 work_queue_.pop(); |
| 452 if (!pending_task.delayed_run_time.is_null()) { | 485 if (!pending_task.delayed_run_time.is_null()) { |
| 453 // We want to delete delayed tasks in the same order in which they would | 486 // We want to delete delayed tasks in the same order in which they would |
| 454 // normally be deleted in case of any funny dependencies between delayed | 487 // normally be deleted in case of any funny dependencies between delayed |
| 455 // tasks. | 488 // tasks. |
| 456 AddToDelayedWorkQueue(std::move(pending_task)); | 489 AddToDelayedWorkQueue(std::move(pending_task)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 | 538 |
| 506 for (;;) { | 539 for (;;) { |
| 507 ReloadWorkQueue(); | 540 ReloadWorkQueue(); |
| 508 if (work_queue_.empty()) | 541 if (work_queue_.empty()) |
| 509 break; | 542 break; |
| 510 | 543 |
| 511 // Execute oldest task. | 544 // Execute oldest task. |
| 512 do { | 545 do { |
| 513 PendingTask pending_task = std::move(work_queue_.front()); | 546 PendingTask pending_task = std::move(work_queue_.front()); |
| 514 work_queue_.pop(); | 547 work_queue_.pop(); |
| 548 |
| 549 if (pending_task.task.IsCancelled()) { |
| 550 #if defined(OS_WIN) |
| 551 if (pending_task.is_high_res) { |
| 552 pending_high_res_tasks_--; |
| 553 CHECK_GE(pending_high_res_tasks_, 0); |
| 554 } |
| 555 #endif |
| 556 continue; |
| 557 } |
| 558 |
| 515 if (!pending_task.delayed_run_time.is_null()) { | 559 if (!pending_task.delayed_run_time.is_null()) { |
| 516 int sequence_num = pending_task.sequence_num; | 560 int sequence_num = pending_task.sequence_num; |
| 517 TimeTicks delayed_run_time = pending_task.delayed_run_time; | 561 TimeTicks delayed_run_time = pending_task.delayed_run_time; |
| 518 AddToDelayedWorkQueue(std::move(pending_task)); | 562 AddToDelayedWorkQueue(std::move(pending_task)); |
| 519 // If we changed the topmost task, then it is time to reschedule. | 563 // If we changed the topmost task, then it is time to reschedule. |
| 520 if (delayed_work_queue_.top().sequence_num == sequence_num) | 564 if (delayed_work_queue_.top().sequence_num == sequence_num) |
| 521 pump_->ScheduleDelayedWork(delayed_run_time); | 565 pump_->ScheduleDelayedWork(delayed_run_time); |
| 522 } else { | 566 } else { |
| 523 if (DeferOrRunPendingTask(std::move(pending_task))) | 567 if (DeferOrRunPendingTask(std::move(pending_task))) |
| 524 return true; | 568 return true; |
| 525 } | 569 } |
| 526 } while (!work_queue_.empty()); | 570 } while (!work_queue_.empty()); |
| 527 } | 571 } |
| 528 | 572 |
| 529 // Nothing happened. | 573 // Nothing happened. |
| 530 return false; | 574 return false; |
| 531 } | 575 } |
| 532 | 576 |
| 533 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) { | 577 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) { |
| 534 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) { | 578 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty() || |
| 579 SweepDelayedWorkQueue()) { |
| 535 recent_time_ = *next_delayed_work_time = TimeTicks(); | 580 recent_time_ = *next_delayed_work_time = TimeTicks(); |
| 536 return false; | 581 return false; |
| 537 } | 582 } |
| 538 | 583 |
| 539 // When we "fall behind", there will be a lot of tasks in the delayed work | 584 // When we "fall behind", there will be a lot of tasks in the delayed work |
| 540 // queue that are ready to run. To increase efficiency when we fall behind, | 585 // queue that are ready to run. To increase efficiency when we fall behind, |
| 541 // we will only call Time::Now() intermittently, and then process all tasks | 586 // we will only call Time::Now() intermittently, and then process all tasks |
| 542 // that are ready to run before calling it again. As a result, the more we | 587 // that are ready to run before calling it again. As a result, the more we |
| 543 // fall behind (and have a lot of ready-to-run delayed tasks), the more | 588 // fall behind (and have a lot of ready-to-run delayed tasks), the more |
| 544 // efficient we'll be at handling the tasks. | 589 // efficient we'll be at handling the tasks. |
| 545 | 590 |
| 546 TimeTicks next_run_time = delayed_work_queue_.top().delayed_run_time; | 591 TimeTicks next_run_time = delayed_work_queue_.top().delayed_run_time; |
| 547 if (next_run_time > recent_time_) { | 592 if (next_run_time > recent_time_) { |
| 548 recent_time_ = TimeTicks::Now(); // Get a better view of Now(); | 593 recent_time_ = TimeTicks::Now(); // Get a better view of Now(); |
| 549 if (next_run_time > recent_time_) { | 594 if (next_run_time > recent_time_) { |
| 550 *next_delayed_work_time = next_run_time; | 595 *next_delayed_work_time = next_run_time; |
| 551 return false; | 596 return false; |
| 552 } | 597 } |
| 553 } | 598 } |
| 554 | 599 |
| 555 PendingTask pending_task = | 600 PendingTask pending_task = |
| 556 std::move(const_cast<PendingTask&>(delayed_work_queue_.top())); | 601 std::move(const_cast<PendingTask&>(delayed_work_queue_.top())); |
| 557 delayed_work_queue_.pop(); | 602 delayed_work_queue_.pop(); |
| 558 | 603 |
| 559 if (!delayed_work_queue_.empty()) | 604 bool did_work = DeferOrRunPendingTask(std::move(pending_task)); |
| 605 |
| 606 if (!delayed_work_queue_.empty() && !SweepDelayedWorkQueue()) |
| 560 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; | 607 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time; |
| 561 | 608 |
| 562 return DeferOrRunPendingTask(std::move(pending_task)); | 609 return did_work; |
| 563 } | 610 } |
| 564 | 611 |
| 565 bool MessageLoop::DoIdleWork() { | 612 bool MessageLoop::DoIdleWork() { |
| 566 if (ProcessNextDelayedNonNestableTask()) | 613 if (ProcessNextDelayedNonNestableTask()) |
| 567 return true; | 614 return true; |
| 568 | 615 |
| 569 if (run_loop_->quit_when_idle_received_) | 616 if (run_loop_->quit_when_idle_received_) |
| 570 pump_->Quit(); | 617 pump_->Quit(); |
| 571 | 618 |
| 572 // When we return we will do a kernel wait for more tasks. | 619 // When we return we will do a kernel wait for more tasks. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 662 persistent, | 709 persistent, |
| 663 mode, | 710 mode, |
| 664 controller, | 711 controller, |
| 665 delegate); | 712 delegate); |
| 666 } | 713 } |
| 667 #endif | 714 #endif |
| 668 | 715 |
| 669 #endif // !defined(OS_NACL_SFI) | 716 #endif // !defined(OS_NACL_SFI) |
| 670 | 717 |
| 671 } // namespace base | 718 } // namespace base |
| OLD | NEW |