Index: base/message_loop/message_loop.cc |
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc |
index 8e817dab8adece6ff025f277167901d6babdeab4..178e726573334db88421dc908bedd41d4412fa62 100644 |
--- a/base/message_loop/message_loop.cc |
+++ b/base/message_loop/message_loop.cc |
@@ -127,6 +127,8 @@ MessageLoop::DestructionObserver::~DestructionObserver() { |
MessageLoop::MessageLoop(Type type) |
: type_(type), |
+ pending_high_res_tasks_(0), |
+ in_high_res_mode_(false), |
nestable_tasks_allowed_(true), |
#if defined(OS_WIN) |
os_modal_loop_(false), |
@@ -141,6 +143,8 @@ MessageLoop::MessageLoop(Type type) |
MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) |
: pump_(pump.Pass()), |
type_(TYPE_CUSTOM), |
+ pending_high_res_tasks_(0), |
+ in_high_res_mode_(false), |
nestable_tasks_allowed_(true), |
#if defined(OS_WIN) |
os_modal_loop_(false), |
@@ -153,8 +157,11 @@ MessageLoop::MessageLoop(scoped_ptr<MessagePump> pump) |
MessageLoop::~MessageLoop() { |
DCHECK_EQ(this, current()); |
- |
DCHECK(!run_loop_); |
+#if defined(OS_WIN) |
+ if (in_high_res_mode_) |
+ Time::ActivateHighResolutionTimer(false); |
+#endif |
// Clean up any unprocessed tasks, but take care: deleting a task could |
// result in the addition of more tasks (e.g., via DeleteSoon). We set a |
@@ -369,8 +376,8 @@ bool MessageLoop::is_running() const { |
return run_loop_ != NULL; |
} |
-bool MessageLoop::IsHighResolutionTimerEnabledForTesting() { |
- return incoming_task_queue_->IsHighResolutionTimerEnabledForTesting(); |
+bool MessageLoop::HasHighResolutionTasks() { |
+ return incoming_task_queue_->HasHighResolutionTasks(); |
} |
bool MessageLoop::IsIdleForTesting() { |
@@ -438,6 +445,11 @@ void MessageLoop::RunTask(const PendingTask& pending_task) { |
"src_file", pending_task.posted_from.file_name(), |
"src_func", pending_task.posted_from.function_name()); |
+ if (pending_task.is_high_res) { |
+ pending_high_res_tasks_--; |
+ CHECK(pending_high_res_tasks_ >= 0); |
+ } |
+ |
DCHECK(nestable_tasks_allowed_); |
// Execute the task and assume the worst: It is probably not reentrant. |
nestable_tasks_allowed_ = false; |
@@ -523,8 +535,10 @@ void MessageLoop::ReloadWorkQueue() { |
// |*work_queue| by waiting until the last minute (|*work_queue| is empty) to |
// load. That reduces the number of locks-per-task significantly when our |
// queues get large. |
- if (work_queue_.empty()) |
- incoming_task_queue_->ReloadWorkQueue(&work_queue_); |
+ if (work_queue_.empty()) { |
+ pending_high_res_tasks_ += |
+ incoming_task_queue_->ReloadWorkQueue(&work_queue_); |
+ } |
} |
void MessageLoop::ScheduleWork(bool was_empty) { |
@@ -629,6 +643,14 @@ bool MessageLoop::DoIdleWork() { |
if (run_loop_->quit_when_idle_received_) |
pump_->Quit(); |
+ // We will now do a kernel wait for more tasks. |
+#if defined(OS_WIN) |
+ // The Windows scheduler has by default ~15ms resolution. If we have high |
+ // resolution tasks pending we need to temporarity increase the systemwide |
+ // timer resolution to 1ms, and if we don't we need to go back to 15ms. |
+ in_high_res_mode_ = pending_high_res_tasks_ > 0; |
+ Time::ActivateHighResolutionTimer(in_high_res_mode_); |
+#endif |
return false; |
} |