From ae9700400f9e7c34101c3deec3f374395a7681d7 Mon Sep 17 00:00:00 2001
From: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Date: Mon, 1 Sep 2014 13:59:59 +0200
Subject: [PATCH] Avoid duplicating timers in MessagePumpForUIQt

Since DoDelayedWork always returns the time of the next delayed work
to process, we would create a new timer for the same event every
time we process an event. This would cause a timer starvation on
Windows for example.

Instead of blindly creating timers, keep track of the requested delay
and create a new timer only if the new delay is shorted than the
currently scheduled one.

Change-Id: I2606231f0a48b8feb85f058a78eb772d26b222f3
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
---
 src/core/content_browser_client_qt.cpp | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 022c02ff5..ba4759ad4 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -100,6 +100,7 @@ public:
         // our own event loop, attach it explicitly ourselves.
         : m_delegate(base::MessageLoopForUI::current())
         , m_explicitLoop(0)
+        , m_timerId(0)
     {
     }
 
@@ -126,7 +127,15 @@ public:
 
     virtual void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) Q_DECL_OVERRIDE
     {
-        startTimer(GetTimeIntervalMilliseconds(delayed_work_time));
+        if (delayed_work_time.is_null()) {
+            killTimer(m_timerId);
+            m_timerId = 0;
+            m_timerScheduledTime = base::TimeTicks();
+        } else if (!m_timerId || delayed_work_time < m_timerScheduledTime) {
+            killTimer(m_timerId);
+            m_timerId = startTimer(GetTimeIntervalMilliseconds(delayed_work_time));
+            m_timerScheduledTime = delayed_work_time;
+        }
     }
 
 protected:
@@ -138,13 +147,14 @@ protected:
 
     virtual void timerEvent(QTimerEvent *ev) Q_DECL_OVERRIDE
     {
-        killTimer(ev->timerId());
+        Q_ASSERT(m_timerId == ev->timerId());
+        killTimer(m_timerId);
+        m_timerId = 0;
+        m_timerScheduledTime = base::TimeTicks();
 
         base::TimeTicks next_delayed_work_time;
         m_delegate->DoDelayedWork(&next_delayed_work_time);
-
-        if (!next_delayed_work_time.is_null())
-            startTimer(GetTimeIntervalMilliseconds(next_delayed_work_time));
+        ScheduleDelayedWork(next_delayed_work_time);
     }
 
 private:
@@ -158,14 +168,16 @@ private:
             return true;
 
         more_work_is_plausible |= m_delegate->DoIdleWork();
-        if (!more_work_is_plausible && !delayed_work_time.is_null())
-            startTimer(GetTimeIntervalMilliseconds(delayed_work_time));
+        if (!more_work_is_plausible)
+            ScheduleDelayedWork(delayed_work_time);
 
         return more_work_is_plausible;
     }
 
     Delegate *m_delegate;
     QEventLoop *m_explicitLoop;
+    int m_timerId;
+    base::TimeTicks m_timerScheduledTime;
 };
 
 scoped_ptr<base::MessagePump> messagePumpFactory()
-- 
GitLab