tools/source/datetime/ttime.cxx |   13 ++++++-------
 vcl/inc/win/saldata.hxx         |    2 +-
 vcl/win/source/app/salinst.cxx  |   17 ++++++++++++++---
 vcl/win/source/app/saltimer.cxx |   27 ++++++++++++++++-----------
 4 files changed, 37 insertions(+), 22 deletions(-)

New commits:
commit d68ce6e173502e1b1ce214503f41729a8502cd92
Author: Jan Holesovsky <ke...@collabora.com>
Date:   Thu Sep 25 16:30:05 2014 +0200

    fdo#84000: Sort out problems with short timeouts & long callbacks.
    
    Previously, the timer events could have accumulated in that scenario leading
    to unresponsiveness to user events.
    
    Change-Id: I455d726ae7475f7dbf98d871c54d8c156cb64e52

diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
index 71836e7..66d16b4 100644
--- a/tools/source/datetime/ttime.cxx
+++ b/tools/source/datetime/ttime.cxx
@@ -400,19 +400,18 @@ Time Time::GetUTCOffset()
 sal_uIntPtr Time::GetSystemTicks()
 {
 #if defined WNT
-    static LARGE_INTEGER nTicksPerMS;
-    static bool bTicksPerMSInitialized = false;
-    if (!bTicksPerMSInitialized)
+    static LARGE_INTEGER nTicksPerSecond;
+    static bool bTicksPerSecondInitialized = false;
+    if (!bTicksPerSecondInitialized)
     {
-        QueryPerformanceFrequency(&nTicksPerMS);
-        nTicksPerMS.QuadPart /= 1000;
-        bTicksPerMSInitialized = true;
+        QueryPerformanceFrequency(&nTicksPerSecond);
+        bTicksPerSecondInitialized = true;
     }
 
     LARGE_INTEGER nPerformanceCount;
     QueryPerformanceCounter(&nPerformanceCount);
 
-    return (sal_uIntPtr)(nPerformanceCount.QuadPart/nTicksPerMS.QuadPart);
+    return 
(sal_uIntPtr)((nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart);
 #else
     timeval tv;
     gettimeofday (&tv, 0);
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index a50e67d..e1ae8cc 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -180,7 +180,7 @@ void ImplSalAcquireYieldMutex( sal_uLong nCount );
 
 LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM 
lParam );
 
-void EmitTimerCallback(bool bAllowRecursive);
+void EmitTimerCallback();
 
 void SalTestMouseLeave();
 bool ImplWriteLastError( DWORD lastError, const char *szApiCall );
diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
index 57dfc28..b1d33e4 100644
--- a/vcl/win/source/app/salinst.cxx
+++ b/vcl/win/source/app/salinst.cxx
@@ -345,7 +345,6 @@ SalData::SalData()
     mnNextTimerTime = 0;
     mnLastEventTime = 0;
     mnTimerId = 0;              // windows timer id
-    mbInTimerProc = FALSE;      // timer event is currently being dispatched
     mhSalObjMsgHook = 0;        // hook to get interesting msg for SalObject
     mhWantLeaveMsg = 0;         // window handle, that want a MOUSELEAVE 
message
     mpMouseLeaveTimer = 0;      // Timer for MouseLeave Test
@@ -731,10 +730,22 @@ LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, 
WPARAM wParam, LPARAM lPar
             rDef = FALSE;
             break;
         case SAL_MSG_POSTTIMER:
-            EmitTimerCallback(/*bAllowRecursive = */ true);
+            EmitTimerCallback();
             break;
         case SAL_MSG_TIMER_CALLBACK:
-            EmitTimerCallback(/*bAllowRecursive = */ false);
+            EmitTimerCallback();
+            MSG aMsg;
+            while (PeekMessageW(&aMsg, 0, SAL_MSG_TIMER_CALLBACK, 
SAL_MSG_TIMER_CALLBACK, PM_REMOVE))
+            {
+                // nothing; just remove all the SAL_MSG_TIMER_CALLBACKs that
+                // accumulated in the queue during the EmitTimerCallback(),
+                // otherwise it happens with short timeouts and long callbacks
+                // that no other events will ever be processed, as the queue
+                // is full of SAL_MSG_TIMER_CALLBACKs.
+                // It is impossible to limit the amount of them being emited
+                // in the first place, as they are emited asynchronously, but
+                // here we are already fully synchronized.
+            }
             break;
     }
 
diff --git a/vcl/win/source/app/saltimer.cxx b/vcl/win/source/app/saltimer.cxx
index 9191d5e..e1ce31e 100644
--- a/vcl/win/source/app/saltimer.cxx
+++ b/vcl/win/source/app/saltimer.cxx
@@ -54,9 +54,11 @@ void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
     if (nMS > MAX_SYSPERIOD)
         nMS = MAX_SYSPERIOD;
 
-    // can't change a one-shot timer if it has fired already (odd) so delete & 
re-create
-    ImplSalStopTimer(pSalData);
-    CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, nMS, 
nMS, WT_EXECUTEDEFAULT);
+    // change if it exists, create if not
+    if (pSalData->mnTimerId)
+        ChangeTimerQueueTimer(NULL, pSalData->mnTimerId, nMS, nMS);
+    else
+        CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, 
nMS, nMS, WT_EXECUTEDEFAULT);
 
     pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
 }
@@ -111,6 +113,10 @@ void CALLBACK SalTimerProc(PVOID, BOOLEAN)
 #endif
 
         SalData* pSalData = GetSalData();
+
+        // always post message when the timer fires, we will remove the ones
+        // that happened during execution of the callback later directly from
+        // the message queue
         PostMessageW(pSalData->mpFirstInstance->mhComWnd, 
SAL_MSG_TIMER_CALLBACK, 0, 0);
 
 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
@@ -128,11 +134,8 @@ void CALLBACK SalTimerProc(PVOID, BOOLEAN)
 
 We assured that by posting the message from the SalTimeProc only, the real
 call then happens when the main thread gets SAL_MSG_TIMER_CALLBACK.
-
-@param bAllowRecursive allows to skip the check that assures that two timeouts
-do not overlap.
 */
-void EmitTimerCallback(bool bAllowRecursive)
+void EmitTimerCallback()
 {
     SalData* pSalData = GetSalData();
     ImplSVData* pSVData = ImplGetSVData();
@@ -142,13 +145,15 @@ void EmitTimerCallback(bool bAllowRecursive)
 
     // Try to acquire the mutex. If we don't get the mutex then we
     // try this a short time later again.
-    if (ImplSalYieldMutexTryToAcquire() &&
-        (pSVData->mpSalTimer && (!pSalData->mbInTimerProc || bAllowRecursive)))
+    if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire())
     {
-        pSalData->mbInTimerProc = true;
         pSVData->mpSalTimer->CallCallback();
-        pSalData->mbInTimerProc = false;
         ImplSalYieldMutexRelease();
+
+        // Run the timer in the correct time, if we started this
+        // with a small timeout, because we didn't get the mutex
+        if (pSalData->mnTimerId && (pSalData->mnTimerMS != 
pSalData->mnTimerOrgMS))
+            ImplSalStartTimer(pSalData->mnTimerOrgMS, false);
     }
     else
     {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to