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

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

Issue 543413004: High resolution timer fix reland (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2125
Patch Set: Created 6 years, 3 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
« no previous file with comments | « base/message_loop/message_loop.h ('k') | base/message_loop/message_loop_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 160
157 DCHECK(!run_loop_); 161 DCHECK(!run_loop_);
158 162 #if defined(OS_WIN)
163 if (in_high_res_mode_)
164 Time::ActivateHighResolutionTimer(false);
165 #endif
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();
168 ReloadWorkQueue(); 175 ReloadWorkQueue();
(...skipping 193 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 PendingTask pending_task = deferred_non_nestable_work_queue_.front(); 425 PendingTask pending_task = deferred_non_nestable_work_queue_.front();
419 deferred_non_nestable_work_queue_.pop(); 426 deferred_non_nestable_work_queue_.pop();
420 427
421 RunTask(pending_task); 428 RunTask(pending_task);
422 return true; 429 return true;
423 } 430 }
424 431
425 void MessageLoop::RunTask(const PendingTask& pending_task) { 432 void MessageLoop::RunTask(const PendingTask& pending_task) {
426 DCHECK(nestable_tasks_allowed_); 433 DCHECK(nestable_tasks_allowed_);
427 434
435 if (pending_task.is_high_res) {
436 pending_high_res_tasks_--;
437 CHECK(pending_high_res_tasks_ >= 0);
438 }
428 // Execute the task and assume the worst: It is probably not reentrant. 439 // Execute the task and assume the worst: It is probably not reentrant.
429 nestable_tasks_allowed_ = false; 440 nestable_tasks_allowed_ = false;
430 441
431 HistogramEvent(kTaskRunEvent); 442 HistogramEvent(kTaskRunEvent);
432 443
433 FOR_EACH_OBSERVER(TaskObserver, task_observers_, 444 FOR_EACH_OBSERVER(TaskObserver, task_observers_,
434 WillProcessTask(pending_task)); 445 WillProcessTask(pending_task));
435 task_annotator_.RunTask( 446 task_annotator_.RunTask(
436 "MessageLoop::PostTask", "MessageLoop::RunTask", pending_task); 447 "MessageLoop::PostTask", "MessageLoop::RunTask", pending_task);
437 FOR_EACH_OBSERVER(TaskObserver, task_observers_, 448 FOR_EACH_OBSERVER(TaskObserver, task_observers_,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 delayed_work_queue_.pop(); 497 delayed_work_queue_.pop();
487 } 498 }
488 return did_work; 499 return did_work;
489 } 500 }
490 501
491 void MessageLoop::ReloadWorkQueue() { 502 void MessageLoop::ReloadWorkQueue() {
492 // We can improve performance of our loading tasks from the incoming queue to 503 // We can improve performance of our loading tasks from the incoming queue to
493 // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to 504 // |*work_queue| by waiting until the last minute (|*work_queue| is empty) to
494 // load. That reduces the number of locks-per-task significantly when our 505 // load. That reduces the number of locks-per-task significantly when our
495 // queues get large. 506 // queues get large.
496 if (work_queue_.empty()) 507 if (work_queue_.empty()) {
497 incoming_task_queue_->ReloadWorkQueue(&work_queue_); 508 pending_high_res_tasks_ +=
509 incoming_task_queue_->ReloadWorkQueue(&work_queue_);
510 }
498 } 511 }
499 512
500 void MessageLoop::ScheduleWork(bool was_empty) { 513 void MessageLoop::ScheduleWork(bool was_empty) {
501 if (was_empty || AlwaysNotifyPump(type_)) 514 if (was_empty || AlwaysNotifyPump(type_))
502 pump_->ScheduleWork(); 515 pump_->ScheduleWork();
503 } 516 }
504 517
505 //------------------------------------------------------------------------------ 518 //------------------------------------------------------------------------------
506 // Method and data for histogramming events and actions taken by each instance 519 // Method and data for histogramming events and actions taken by each instance
507 // on each thread. 520 // on each thread.
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 return DeferOrRunPendingTask(pending_task); 603 return DeferOrRunPendingTask(pending_task);
591 } 604 }
592 605
593 bool MessageLoop::DoIdleWork() { 606 bool MessageLoop::DoIdleWork() {
594 if (ProcessNextDelayedNonNestableTask()) 607 if (ProcessNextDelayedNonNestableTask())
595 return true; 608 return true;
596 609
597 if (run_loop_->quit_when_idle_received_) 610 if (run_loop_->quit_when_idle_received_)
598 pump_->Quit(); 611 pump_->Quit();
599 612
613 // When we return we will do a kernel wait for more tasks.
614 #if defined(OS_WIN)
615 // On Windows we activate the high resolution timer so that the wait
616 // _if_ triggered by the timer happens with good resolution. If we don't
617 // do this the default resolution is 15ms which might not be acceptable
618 // for some tasks.
619 in_high_res_mode_ = pending_high_res_tasks_ > 0;
620 Time::ActivateHighResolutionTimer(in_high_res_mode_);
621 #endif
600 return false; 622 return false;
601 } 623 }
602 624
603 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here, 625 void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here,
604 void(*deleter)(const void*), 626 void(*deleter)(const void*),
605 const void* object) { 627 const void* object) {
606 PostNonNestableTask(from_here, Bind(deleter, object)); 628 PostNonNestableTask(from_here, Bind(deleter, object));
607 } 629 }
608 630
609 void MessageLoop::ReleaseSoonInternal( 631 void MessageLoop::ReleaseSoonInternal(
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 persistent, 707 persistent,
686 mode, 708 mode,
687 controller, 709 controller,
688 delegate); 710 delegate);
689 } 711 }
690 #endif 712 #endif
691 713
692 #endif // !defined(OS_NACL) 714 #endif // !defined(OS_NACL)
693 715
694 } // namespace base 716 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_loop.h ('k') | base/message_loop/message_loop_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698