Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(395)

Side by Side Diff: base/message_loop/message_loop.cc

Issue 395913006: High resolution timer fix for Windows (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more cleanup Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698