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