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 |