| 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 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 // current() could be NULL if this message loop is destructed before it is | 133 // current() could be NULL if this message loop is destructed before it is |
| 134 // bound to a thread. | 134 // bound to a thread. |
| 135 DCHECK(current() == this || !current()); | 135 DCHECK(current() == this || !current()); |
| 136 | 136 |
| 137 // iOS just attaches to the loop, it doesn't Run it. | 137 // iOS just attaches to the loop, it doesn't Run it. |
| 138 // TODO(stuartmorgan): Consider wiring up a Detach(). | 138 // TODO(stuartmorgan): Consider wiring up a Detach(). |
| 139 #if !defined(OS_IOS) | 139 #if !defined(OS_IOS) |
| 140 DCHECK(!run_loop_); | 140 DCHECK(!run_loop_); |
| 141 #endif | 141 #endif |
| 142 | 142 |
| 143 #if defined(OS_WIN) | |
| 144 if (in_high_res_mode_) | |
| 145 Time::ActivateHighResolutionTimer(false); | |
| 146 #endif | |
| 147 // Clean up any unprocessed tasks, but take care: deleting a task could | 143 // Clean up any unprocessed tasks, but take care: deleting a task could |
| 148 // result in the addition of more tasks (e.g., via DeleteSoon). We set a | 144 // result in the addition of more tasks (e.g., via DeleteSoon). We set a |
| 149 // limit on the number of times we will allow a deleted task to generate more | 145 // limit on the number of times we will allow a deleted task to generate more |
| 150 // tasks. Normally, we should only pass through this loop once or twice. If | 146 // tasks. Normally, we should only pass through this loop once or twice. If |
| 151 // we end up hitting the loop limit, then it is probably due to one task that | 147 // we end up hitting the loop limit, then it is probably due to one task that |
| 152 // is being stubborn. Inspect the queues to see who is left. | 148 // is being stubborn. Inspect the queues to see who is left. |
| 153 bool did_work; | 149 bool did_work; |
| 154 for (int i = 0; i < 100; ++i) { | 150 for (int i = 0; i < 100; ++i) { |
| 155 DeletePendingTasks(); | 151 DeletePendingTasks(); |
| 156 ReloadWorkQueue(); | 152 ReloadWorkQueue(); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 | 363 |
| 368 //------------------------------------------------------------------------------ | 364 //------------------------------------------------------------------------------ |
| 369 | 365 |
| 370 scoped_ptr<MessageLoop> MessageLoop::CreateUnbound( | 366 scoped_ptr<MessageLoop> MessageLoop::CreateUnbound( |
| 371 Type type, MessagePumpFactoryCallback pump_factory) { | 367 Type type, MessagePumpFactoryCallback pump_factory) { |
| 372 return make_scoped_ptr(new MessageLoop(type, pump_factory)); | 368 return make_scoped_ptr(new MessageLoop(type, pump_factory)); |
| 373 } | 369 } |
| 374 | 370 |
| 375 MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory) | 371 MessageLoop::MessageLoop(Type type, MessagePumpFactoryCallback pump_factory) |
| 376 : type_(type), | 372 : type_(type), |
| 377 #if defined(OS_WIN) | |
| 378 pending_high_res_tasks_(0), | |
| 379 in_high_res_mode_(false), | |
| 380 #endif | |
| 381 nestable_tasks_allowed_(true), | 373 nestable_tasks_allowed_(true), |
| 382 #if defined(OS_WIN) | |
| 383 os_modal_loop_(false), | |
| 384 #endif // OS_WIN | |
| 385 pump_factory_(pump_factory), | 374 pump_factory_(pump_factory), |
| 386 message_histogram_(NULL), | 375 message_histogram_(NULL), |
| 387 run_loop_(NULL), | 376 run_loop_(NULL), |
| 388 incoming_task_queue_(new internal::IncomingTaskQueue(this)), | 377 incoming_task_queue_(new internal::IncomingTaskQueue(this)), |
| 389 message_loop_proxy_( | 378 message_loop_proxy_( |
| 390 new internal::MessageLoopProxyImpl(incoming_task_queue_)) { | 379 new internal::MessageLoopProxyImpl(incoming_task_queue_)) { |
| 391 // If type is TYPE_CUSTOM non-null pump_factory must be given. | 380 // If type is TYPE_CUSTOM non-null pump_factory must be given. |
| 392 DCHECK_EQ(type_ == TYPE_CUSTOM, !pump_factory_.is_null()); | 381 DCHECK_EQ(type_ == TYPE_CUSTOM, !pump_factory_.is_null()); |
| 393 } | 382 } |
| 394 | 383 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 406 message_loop_proxy_->BindToCurrentThread(); | 395 message_loop_proxy_->BindToCurrentThread(); |
| 407 thread_task_runner_handle_.reset( | 396 thread_task_runner_handle_.reset( |
| 408 new ThreadTaskRunnerHandle(message_loop_proxy_)); | 397 new ThreadTaskRunnerHandle(message_loop_proxy_)); |
| 409 } | 398 } |
| 410 | 399 |
| 411 void MessageLoop::RunHandler() { | 400 void MessageLoop::RunHandler() { |
| 412 DCHECK_EQ(this, current()); | 401 DCHECK_EQ(this, current()); |
| 413 | 402 |
| 414 StartHistogrammer(); | 403 StartHistogrammer(); |
| 415 | 404 |
| 416 #if defined(OS_WIN) | |
| 417 if (run_loop_->dispatcher_ && type() == TYPE_UI) { | |
| 418 static_cast<MessagePumpForUI*>(pump_.get())-> | |
| 419 RunWithDispatcher(this, run_loop_->dispatcher_); | |
| 420 return; | |
| 421 } | |
| 422 #endif | |
| 423 | |
| 424 pump_->Run(this); | 405 pump_->Run(this); |
| 425 } | 406 } |
| 426 | 407 |
| 427 bool MessageLoop::ProcessNextDelayedNonNestableTask() { | 408 bool MessageLoop::ProcessNextDelayedNonNestableTask() { |
| 428 if (run_loop_->run_depth_ != 1) | 409 if (run_loop_->run_depth_ != 1) |
| 429 return false; | 410 return false; |
| 430 | 411 |
| 431 if (deferred_non_nestable_work_queue_.empty()) | 412 if (deferred_non_nestable_work_queue_.empty()) |
| 432 return false; | 413 return false; |
| 433 | 414 |
| 434 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); | 415 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); |
| 435 deferred_non_nestable_work_queue_.pop(); | 416 deferred_non_nestable_work_queue_.pop(); |
| 436 | 417 |
| 437 RunTask(pending_task); | 418 RunTask(pending_task); |
| 438 return true; | 419 return true; |
| 439 } | 420 } |
| 440 | 421 |
| 441 void MessageLoop::RunTask(const PendingTask& pending_task) { | 422 void MessageLoop::RunTask(const PendingTask& pending_task) { |
| 442 DCHECK(nestable_tasks_allowed_); | 423 DCHECK(nestable_tasks_allowed_); |
| 443 | 424 |
| 444 #if defined(OS_WIN) | |
| 445 if (pending_task.is_high_res) { | |
| 446 pending_high_res_tasks_--; | |
| 447 CHECK_GE(pending_high_res_tasks_, 0); | |
| 448 } | |
| 449 #endif | |
| 450 | |
| 451 // Execute the task and assume the worst: It is probably not reentrant. | 425 // Execute the task and assume the worst: It is probably not reentrant. |
| 452 nestable_tasks_allowed_ = false; | 426 nestable_tasks_allowed_ = false; |
| 453 | 427 |
| 454 HistogramEvent(kTaskRunEvent); | 428 HistogramEvent(kTaskRunEvent); |
| 455 | 429 |
| 456 FOR_EACH_OBSERVER(TaskObserver, task_observers_, | 430 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
| 457 WillProcessTask(pending_task)); | 431 WillProcessTask(pending_task)); |
| 458 task_annotator_.RunTask( | 432 task_annotator_.RunTask( |
| 459 "MessageLoop::PostTask", "MessageLoop::RunTask", pending_task); | 433 "MessageLoop::PostTask", "MessageLoop::RunTask", pending_task); |
| 460 FOR_EACH_OBSERVER(TaskObserver, task_observers_, | 434 FOR_EACH_OBSERVER(TaskObserver, task_observers_, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 } | 484 } |
| 511 return did_work; | 485 return did_work; |
| 512 } | 486 } |
| 513 | 487 |
| 514 void MessageLoop::ReloadWorkQueue() { | 488 void MessageLoop::ReloadWorkQueue() { |
| 515 // We can improve performance of our loading tasks from the incoming queue to | 489 // We can improve performance of our loading tasks from the incoming queue to |
| 516 // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to | 490 // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to |
| 517 // load. That reduces the number of locks-per-task significantly when our | 491 // load. That reduces the number of locks-per-task significantly when our |
| 518 // queues get large. | 492 // queues get large. |
| 519 if (work_queue_.empty()) { | 493 if (work_queue_.empty()) { |
| 520 #if defined(OS_WIN) | |
| 521 pending_high_res_tasks_ += | |
| 522 incoming_task_queue_->ReloadWorkQueue(&work_queue_); | |
| 523 #else | |
| 524 incoming_task_queue_->ReloadWorkQueue(&work_queue_); | 494 incoming_task_queue_->ReloadWorkQueue(&work_queue_); |
| 525 #endif | |
| 526 } | 495 } |
| 527 } | 496 } |
| 528 | 497 |
| 529 void MessageLoop::ScheduleWork() { | 498 void MessageLoop::ScheduleWork() { |
| 530 pump_->ScheduleWork(); | 499 pump_->ScheduleWork(); |
| 531 } | 500 } |
| 532 | 501 |
| 533 //------------------------------------------------------------------------------ | 502 //------------------------------------------------------------------------------ |
| 534 // Method and data for histogramming events and actions taken by each instance | 503 // Method and data for histogramming events and actions taken by each instance |
| 535 // on each thread. | 504 // on each thread. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 } | 588 } |
| 620 | 589 |
| 621 bool MessageLoop::DoIdleWork() { | 590 bool MessageLoop::DoIdleWork() { |
| 622 if (ProcessNextDelayedNonNestableTask()) | 591 if (ProcessNextDelayedNonNestableTask()) |
| 623 return true; | 592 return true; |
| 624 | 593 |
| 625 if (run_loop_->quit_when_idle_received_) | 594 if (run_loop_->quit_when_idle_received_) |
| 626 pump_->Quit(); | 595 pump_->Quit(); |
| 627 | 596 |
| 628 // When we return we will do a kernel wait for more tasks. | 597 // When we return we will do a kernel wait for more tasks. |
| 629 #if defined(OS_WIN) | |
| 630 // On Windows we activate the high resolution timer so that the wait | |
| 631 // _if_ triggered by the timer happens with good resolution. If we don't | |
| 632 // do this the default resolution is 15ms which might not be acceptable | |
| 633 // for some tasks. | |
| 634 bool high_res = pending_high_res_tasks_ > 0; | |
| 635 if (high_res != in_high_res_mode_) { | |
| 636 in_high_res_mode_ = high_res; | |
| 637 Time::ActivateHighResolutionTimer(in_high_res_mode_); | |
| 638 } | |
| 639 #endif | |
| 640 return false; | 598 return false; |
| 641 } | 599 } |
| 642 | 600 |
| 643 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, | 601 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, |
| 644 void(*deleter)(const void*), | 602 void(*deleter)(const void*), |
| 645 const void* object) { | 603 const void* object) { |
| 646 PostNonNestableTask(from_here, Bind(deleter, object)); | 604 PostNonNestableTask(from_here, Bind(deleter, object)); |
| 647 } | 605 } |
| 648 | 606 |
| 649 void MessageLoop::ReleaseSoonInternal( | 607 void MessageLoop::ReleaseSoonInternal( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 void MessageLoopForIO::AddIOObserver( | 653 void MessageLoopForIO::AddIOObserver( |
| 696 MessageLoopForIO::IOObserver* io_observer) { | 654 MessageLoopForIO::IOObserver* io_observer) { |
| 697 ToPumpIO(pump_.get())->AddIOObserver(io_observer); | 655 ToPumpIO(pump_.get())->AddIOObserver(io_observer); |
| 698 } | 656 } |
| 699 | 657 |
| 700 void MessageLoopForIO::RemoveIOObserver( | 658 void MessageLoopForIO::RemoveIOObserver( |
| 701 MessageLoopForIO::IOObserver* io_observer) { | 659 MessageLoopForIO::IOObserver* io_observer) { |
| 702 ToPumpIO(pump_.get())->RemoveIOObserver(io_observer); | 660 ToPumpIO(pump_.get())->RemoveIOObserver(io_observer); |
| 703 } | 661 } |
| 704 | 662 |
| 705 #if defined(OS_WIN) | 663 #if defined(OS_POSIX) |
| 706 void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) { | |
| 707 ToPumpIO(pump_.get())->RegisterIOHandler(file, handler); | |
| 708 } | |
| 709 | |
| 710 bool MessageLoopForIO::RegisterJobObject(HANDLE job, IOHandler* handler) { | |
| 711 return ToPumpIO(pump_.get())->RegisterJobObject(job, handler); | |
| 712 } | |
| 713 | |
| 714 bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) { | |
| 715 return ToPumpIO(pump_.get())->WaitForIOCompletion(timeout, filter); | |
| 716 } | |
| 717 #elif defined(OS_POSIX) | |
| 718 bool MessageLoopForIO::WatchFileDescriptor(int fd, | 664 bool MessageLoopForIO::WatchFileDescriptor(int fd, |
| 719 bool persistent, | 665 bool persistent, |
| 720 Mode mode, | 666 Mode mode, |
| 721 FileDescriptorWatcher* controller, | 667 FileDescriptorWatcher* controller, |
| 722 Watcher* delegate) { | 668 Watcher* delegate) { |
| 723 return ToPumpIO(pump_.get())->WatchFileDescriptor( | 669 return ToPumpIO(pump_.get())->WatchFileDescriptor( |
| 724 fd, | 670 fd, |
| 725 persistent, | 671 persistent, |
| 726 mode, | 672 mode, |
| 727 controller, | 673 controller, |
| 728 delegate); | 674 delegate); |
| 729 } | 675 } |
| 730 #endif | 676 #endif |
| 731 | 677 |
| 732 #endif // !defined(OS_NACL_SFI) | 678 #endif // !defined(OS_NACL_SFI) |
| 733 | 679 |
| 734 } // namespace base | 680 } // namespace base |
| OLD | NEW |