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

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

Powered by Google App Engine
This is Rietveld 408576698