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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 MessageLoop::TaskObserver::~TaskObserver() { | 120 MessageLoop::TaskObserver::~TaskObserver() { |
121 } | 121 } |
122 | 122 |
123 MessageLoop::DestructionObserver::~DestructionObserver() { | 123 MessageLoop::DestructionObserver::~DestructionObserver() { |
124 } | 124 } |
125 | 125 |
126 //------------------------------------------------------------------------------ | 126 //------------------------------------------------------------------------------ |
127 | 127 |
128 MessageLoop::MessageLoop(Type type) | 128 MessageLoop::MessageLoop(Type type) |
129 : type_(type), | 129 : type_(type), |
130 pending_high_res_tasks_(0), | |
131 in_high_res_mode_(false), | |
132 nestable_tasks_allowed_(true), | 130 nestable_tasks_allowed_(true), |
133 #if defined(OS_WIN) | 131 #if defined(OS_WIN) |
134 os_modal_loop_(false), | 132 os_modal_loop_(false), |
135 #endif // OS_WIN | 133 #endif // OS_WIN |
136 message_histogram_(NULL), | 134 message_histogram_(NULL), |
137 run_loop_(NULL) { | 135 run_loop_(NULL) { |
138 Init(); | 136 Init(); |
139 | 137 |
140 pump_ = CreateMessagePumpForType(type).Pass(); | 138 pump_ = CreateMessagePumpForType(type).Pass(); |
141 } | 139 } |
142 | 140 |
143 MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) | 141 MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) |
144 : pump_(pump.Pass()), | 142 : pump_(pump.Pass()), |
145 type_(TYPE_CUSTOM), | 143 type_(TYPE_CUSTOM), |
146 pending_high_res_tasks_(0), | |
147 in_high_res_mode_(false), | |
148 nestable_tasks_allowed_(true), | 144 nestable_tasks_allowed_(true), |
149 #if defined(OS_WIN) | 145 #if defined(OS_WIN) |
150 os_modal_loop_(false), | 146 os_modal_loop_(false), |
151 #endif // OS_WIN | 147 #endif // OS_WIN |
152 message_histogram_(NULL), | 148 message_histogram_(NULL), |
153 run_loop_(NULL) { | 149 run_loop_(NULL) { |
154 DCHECK(pump_.get()); | 150 DCHECK(pump_.get()); |
155 Init(); | 151 Init(); |
156 } | 152 } |
157 | 153 |
158 MessageLoop::~MessageLoop() { | 154 MessageLoop::~MessageLoop() { |
159 DCHECK_EQ(this, current()); | 155 DCHECK_EQ(this, current()); |
| 156 |
160 DCHECK(!run_loop_); | 157 DCHECK(!run_loop_); |
161 #if defined(OS_WIN) | |
162 if (in_high_res_mode_) | |
163 Time::ActivateHighResolutionTimer(false); | |
164 #endif | |
165 | 158 |
166 // Clean up any unprocessed tasks, but take care: deleting a task could | 159 // Clean up any unprocessed tasks, but take care: deleting a task could |
167 // result in the addition of more tasks (e.g., via DeleteSoon). We set a | 160 // result in the addition of more tasks (e.g., via DeleteSoon). We set a |
168 // limit on the number of times we will allow a deleted task to generate more | 161 // limit on the number of times we will allow a deleted task to generate more |
169 // tasks. Normally, we should only pass through this loop once or twice. If | 162 // tasks. Normally, we should only pass through this loop once or twice. If |
170 // we end up hitting the loop limit, then it is probably due to one task that | 163 // we end up hitting the loop limit, then it is probably due to one task that |
171 // is being stubborn. Inspect the queues to see who is left. | 164 // is being stubborn. Inspect the queues to see who is left. |
172 bool did_work; | 165 bool did_work; |
173 for (int i = 0; i < 100; ++i) { | 166 for (int i = 0; i < 100; ++i) { |
174 DeletePendingTasks(); | 167 DeletePendingTasks(); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { | 362 void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) { |
370 DCHECK_EQ(this, current()); | 363 DCHECK_EQ(this, current()); |
371 task_observers_.RemoveObserver(task_observer); | 364 task_observers_.RemoveObserver(task_observer); |
372 } | 365 } |
373 | 366 |
374 bool MessageLoop::is_running() const { | 367 bool MessageLoop::is_running() const { |
375 DCHECK_EQ(this, current()); | 368 DCHECK_EQ(this, current()); |
376 return run_loop_ != NULL; | 369 return run_loop_ != NULL; |
377 } | 370 } |
378 | 371 |
379 bool MessageLoop::HasHighResolutionTasks() { | 372 bool MessageLoop::IsHighResolutionTimerEnabledForTesting() { |
380 return incoming_task_queue_->HasHighResolutionTasks(); | 373 return incoming_task_queue_->IsHighResolutionTimerEnabledForTesting(); |
381 } | 374 } |
382 | 375 |
383 bool MessageLoop::IsIdleForTesting() { | 376 bool MessageLoop::IsIdleForTesting() { |
384 // We only check the imcoming queue|, since we don't want to lock the work | 377 // We only check the imcoming queue|, since we don't want to lock the work |
385 // queue. | 378 // queue. |
386 return incoming_task_queue_->IsIdleForTesting(); | 379 return incoming_task_queue_->IsIdleForTesting(); |
387 } | 380 } |
388 | 381 |
389 //------------------------------------------------------------------------------ | 382 //------------------------------------------------------------------------------ |
390 | 383 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 "queue_duration", | 431 "queue_duration", |
439 (start_time - pending_task.EffectiveTimePosted()).InMilliseconds()); | 432 (start_time - pending_task.EffectiveTimePosted()).InMilliseconds()); |
440 // When tracing memory for posted tasks it's more valuable to attribute the | 433 // When tracing memory for posted tasks it's more valuable to attribute the |
441 // memory allocations to the source function than generically to "RunTask". | 434 // memory allocations to the source function than generically to "RunTask". |
442 TRACE_EVENT_WITH_MEMORY_TAG2( | 435 TRACE_EVENT_WITH_MEMORY_TAG2( |
443 "toplevel", "MessageLoop::RunTask", | 436 "toplevel", "MessageLoop::RunTask", |
444 pending_task.posted_from.function_name(), // Name for memory tracking. | 437 pending_task.posted_from.function_name(), // Name for memory tracking. |
445 "src_file", pending_task.posted_from.file_name(), | 438 "src_file", pending_task.posted_from.file_name(), |
446 "src_func", pending_task.posted_from.function_name()); | 439 "src_func", pending_task.posted_from.function_name()); |
447 | 440 |
448 if (pending_task.is_high_res) { | |
449 pending_high_res_tasks_--; | |
450 CHECK(pending_high_res_tasks_ >= 0); | |
451 } | |
452 | |
453 DCHECK(nestable_tasks_allowed_); | 441 DCHECK(nestable_tasks_allowed_); |
454 // Execute the task and assume the worst: It is probably not reentrant. | 442 // Execute the task and assume the worst: It is probably not reentrant. |
455 nestable_tasks_allowed_ = false; | 443 nestable_tasks_allowed_ = false; |
456 | 444 |
457 // Before running the task, store the program counter where it was posted | 445 // Before running the task, store the program counter where it was posted |
458 // and deliberately alias it to ensure it is on the stack if the task | 446 // and deliberately alias it to ensure it is on the stack if the task |
459 // crashes. Be careful not to assume that the variable itself will have the | 447 // crashes. Be careful not to assume that the variable itself will have the |
460 // expected value when displayed by the optimizer in an optimized build. | 448 // expected value when displayed by the optimizer in an optimized build. |
461 // Look at a memory dump of the stack. | 449 // Look at a memory dump of the stack. |
462 const void* program_counter = | 450 const void* program_counter = |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 uint64 MessageLoop::GetTaskTraceID(const PendingTask& task) { | 516 uint64 MessageLoop::GetTaskTraceID(const PendingTask& task) { |
529 return (static_cast<uint64>(task.sequence_num) << 32) | | 517 return (static_cast<uint64>(task.sequence_num) << 32) | |
530 ((static_cast<uint64>(reinterpret_cast<intptr_t>(this)) << 32) >> 32); | 518 ((static_cast<uint64>(reinterpret_cast<intptr_t>(this)) << 32) >> 32); |
531 } | 519 } |
532 | 520 |
533 void MessageLoop::ReloadWorkQueue() { | 521 void MessageLoop::ReloadWorkQueue() { |
534 // We can improve performance of our loading tasks from the incoming queue to | 522 // We can improve performance of our loading tasks from the incoming queue to |
535 // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to | 523 // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to |
536 // load. That reduces the number of locks-per-task significantly when our | 524 // load. That reduces the number of locks-per-task significantly when our |
537 // queues get large. | 525 // queues get large. |
538 if (work_queue_.empty()) { | 526 if (work_queue_.empty()) |
539 pending_high_res_tasks_ += | 527 incoming_task_queue_->ReloadWorkQueue(&work_queue_); |
540 incoming_task_queue_->ReloadWorkQueue(&work_queue_); | |
541 } | |
542 } | 528 } |
543 | 529 |
544 void MessageLoop::ScheduleWork(bool was_empty) { | 530 void MessageLoop::ScheduleWork(bool was_empty) { |
545 // The Android UI message loop needs to get notified each time | 531 // The Android UI message loop needs to get notified each time |
546 // a task is added to the incoming queue. | 532 // a task is added to the incoming queue. |
547 if (was_empty || AlwaysNotifyPump(type_)) | 533 if (was_empty || AlwaysNotifyPump(type_)) |
548 pump_->ScheduleWork(); | 534 pump_->ScheduleWork(); |
549 } | 535 } |
550 | 536 |
551 //------------------------------------------------------------------------------ | 537 //------------------------------------------------------------------------------ |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 return DeferOrRunPendingTask(pending_task); | 622 return DeferOrRunPendingTask(pending_task); |
637 } | 623 } |
638 | 624 |
639 bool MessageLoop::DoIdleWork() { | 625 bool MessageLoop::DoIdleWork() { |
640 if (ProcessNextDelayedNonNestableTask()) | 626 if (ProcessNextDelayedNonNestableTask()) |
641 return true; | 627 return true; |
642 | 628 |
643 if (run_loop_->quit_when_idle_received_) | 629 if (run_loop_->quit_when_idle_received_) |
644 pump_->Quit(); | 630 pump_->Quit(); |
645 | 631 |
646 // We will now do a kernel wait for more tasks. | |
647 #if defined(OS_WIN) | |
648 // The Windows scheduler has by default ~15ms resolution. If we have high | |
649 // resolution tasks pending we need to temporarity increase the systemwide | |
650 // timer resolution to 1ms, and if we don't we need to go back to 15ms. | |
651 in_high_res_mode_ = pending_high_res_tasks_ > 0; | |
652 Time::ActivateHighResolutionTimer(in_high_res_mode_); | |
653 #endif | |
654 return false; | 632 return false; |
655 } | 633 } |
656 | 634 |
657 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, | 635 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, |
658 void(*deleter)(const void*), | 636 void(*deleter)(const void*), |
659 const void* object) { | 637 const void* object) { |
660 PostNonNestableTask(from_here, Bind(deleter, object)); | 638 PostNonNestableTask(from_here, Bind(deleter, object)); |
661 } | 639 } |
662 | 640 |
663 void MessageLoop::ReleaseSoonInternal( | 641 void MessageLoop::ReleaseSoonInternal( |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 persistent, | 727 persistent, |
750 mode, | 728 mode, |
751 controller, | 729 controller, |
752 delegate); | 730 delegate); |
753 } | 731 } |
754 #endif | 732 #endif |
755 | 733 |
756 #endif // !defined(OS_NACL) | 734 #endif // !defined(OS_NACL) |
757 | 735 |
758 } // namespace base | 736 } // namespace base |
OLD | NEW |