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

Unified Diff: base/message_loop/incoming_task_queue.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 side-by-side diff with in-line comments
Download patch
Index: base/message_loop/incoming_task_queue.cc
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
index bcc712b4a5d981b222b7a5ae4cbe84f9b67493e8..48c2f4202e13247ffcd27ee3c1eeeb6ce5e2aba4 100644
--- a/base/message_loop/incoming_task_queue.cc
+++ b/base/message_loop/incoming_task_queue.cc
@@ -8,12 +8,14 @@
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
+#include "base/time/time.h"
namespace base {
namespace internal {
IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop)
- : message_loop_(message_loop),
+ : high_res_task_count_(0),
+ message_loop_(message_loop),
next_sequence_num_(0) {
}
@@ -25,15 +27,23 @@ bool IncomingTaskQueue::AddToIncomingQueue(
AutoLock locked(incoming_queue_lock_);
PendingTask pending_task(
from_here, task, CalculateDelayedRuntime(delay), nestable);
+#if defined(OS_WIN)
+ // We consider the task needs a high resolution timer if the delay is
+ // more than 0 and less than 32ms. This caps the relative error to
+ // less than 50% : a 33ms wait can wake at 48ms since the default
+ // resolution on Windows is between 10 and 15ms.
+ if (delay > TimeDelta() &&
+ delay.InMilliseconds() < (2 * Time::kMinLowResolutionThresholdMs)) {
+ ++high_res_task_count_;
+ pending_task.is_high_res = true;
+ }
+#endif
return PostPendingTask(&pending_task);
}
-bool IncomingTaskQueue::IsHighResolutionTimerEnabledForTesting() {
-#if defined(OS_WIN)
- return !high_resolution_timer_expiration_.is_null();
-#else
- return true;
-#endif
+bool IncomingTaskQueue::HasHighResolutionTasks() {
+ AutoLock lock(incoming_queue_lock_);
+ return high_res_task_count_ > 0;
}
bool IncomingTaskQueue::IsIdleForTesting() {
@@ -41,29 +51,22 @@ bool IncomingTaskQueue::IsIdleForTesting() {
return incoming_queue_.empty();
}
-void IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) {
+int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) {
// Make sure no tasks are lost.
DCHECK(work_queue->empty());
// Acquire all we can from the inter-thread queue with one lock acquisition.
AutoLock lock(incoming_queue_lock_);
if (!incoming_queue_.empty())
- incoming_queue_.Swap(work_queue); // Constant time
+ incoming_queue_.Swap(work_queue);
- DCHECK(incoming_queue_.empty());
+ // Reset the count of high resolution tasks since our queue is now empty.
+ int high_res_tasks = high_res_task_count_;
+ high_res_task_count_ = 0;
+ return high_res_tasks;
}
void IncomingTaskQueue::WillDestroyCurrentMessageLoop() {
-#if defined(OS_WIN)
- // If we left the high-resolution timer activated, deactivate it now.
- // Doing this is not-critical, it is mainly to make sure we track
- // the high resolution timer activations properly in our unit tests.
- if (!high_resolution_timer_expiration_.is_null()) {
- Time::ActivateHighResolutionTimer(false);
- high_resolution_timer_expiration_ = TimeTicks();
- }
-#endif
-
AutoLock lock(incoming_queue_lock_);
message_loop_ = NULL;
}
@@ -75,40 +78,10 @@ IncomingTaskQueue::~IncomingTaskQueue() {
TimeTicks IncomingTaskQueue::CalculateDelayedRuntime(TimeDelta delay) {
TimeTicks delayed_run_time;
- if (delay > TimeDelta()) {
+ if (delay > TimeDelta())
delayed_run_time = TimeTicks::Now() + delay;
-
-#if defined(OS_WIN)
- if (high_resolution_timer_expiration_.is_null()) {
- // Windows timers are granular to 15.6ms. If we only set high-res
- // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms,
- // which as a percentage is pretty inaccurate. So enable high
- // res timers for any timer which is within 2x of the granularity.
- // This is a tradeoff between accuracy and power management.
- bool needs_high_res_timers = delay.InMilliseconds() <
- (2 * Time::kMinLowResolutionThresholdMs);
- if (needs_high_res_timers) {
- if (Time::ActivateHighResolutionTimer(true)) {
- high_resolution_timer_expiration_ = TimeTicks::Now() +
- TimeDelta::FromMilliseconds(
- MessageLoop::kHighResolutionTimerModeLeaseTimeMs);
- }
- }
- }
-#endif
- } else {
+ else
DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative";
- }
-
-#if defined(OS_WIN)
- if (!high_resolution_timer_expiration_.is_null()) {
- if (TimeTicks::Now() > high_resolution_timer_expiration_) {
- Time::ActivateHighResolutionTimer(false);
- high_resolution_timer_expiration_ = TimeTicks();
- }
- }
-#endif
-
return delayed_run_time;
}

Powered by Google App Engine
This is Rietveld 408576698