[Libreoffice-commits] core.git: 2 commits - tools/source vcl/inc vcl/source vcl/win
Michael Meeks
michael.meeks at collabora.com
Tue Sep 23 13:31:14 PDT 2014
tools/source/datetime/ttime.cxx | 14 +++++
vcl/inc/win/saldata.hxx | 12 ++--
vcl/source/app/timer.cxx | 1
vcl/win/source/app/salinst.cxx | 5 +
vcl/win/source/app/saltimer.cxx | 102 +++++++++++++++++++++++-----------------
5 files changed, 86 insertions(+), 48 deletions(-)
New commits:
commit da21f7da44dc577a08ea3bc210083dc8decf18bc
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Tue Sep 23 21:27:46 2014 +0100
fdo#84000 - unwind recursive timer issues.
Seemingly timers were not being issued or re-queued. Handle recursion
issues in the main thread, not in the timer thread.
Change-Id: I4f49341115bb7c7b1613e61f77a467154818a8aa
diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx
index f83f55c..1f9870b 100644
--- a/vcl/source/app/timer.cxx
+++ b/vcl/source/app/timer.cxx
@@ -70,6 +70,7 @@ static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS )
if ( !nMS )
nMS = 1;
+ // Assume underlying timers are recurring timers, if same period - just wait.
if ( nMS != pSVData->mnTimerPeriod )
{
pSVData->mnTimerPeriod = nMS;
diff --git a/vcl/win/source/app/saltimer.cxx b/vcl/win/source/app/saltimer.cxx
index 779c691..fdfa5c0 100644
--- a/vcl/win/source/app/saltimer.cxx
+++ b/vcl/win/source/app/saltimer.cxx
@@ -54,11 +54,9 @@ void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
if (nMS > MAX_SYSPERIOD)
nMS = MAX_SYSPERIOD;
- // 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);
+ // 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);
pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
}
@@ -111,15 +109,10 @@ void CALLBACK SalTimerProc(PVOID, BOOLEAN)
__try
{
#endif
+
SalData* pSalData = GetSalData();
- ImplSVData* pSVData = ImplGetSVData();
-
- // don't allow recursive calls (mbInTimerProc is set when the callback
- // is being processed)
- if (pSVData->mpSalTimer && !pSalData->mbInTimerProc)
- {
- ImplPostMessage(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);
- }
+ ImplPostMessage(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);
+
#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
}
han.Reset();
@@ -149,23 +142,18 @@ 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())
+ if (ImplSalYieldMutexTryToAcquire() &&
+ (pSVData->mpSalTimer && (!pSalData->mbInTimerProc || bAllowRecursive)))
{
- if (pSVData->mpSalTimer && (!pSalData->mbInTimerProc || bAllowRecursive))
- {
- pSalData->mbInTimerProc = true;
- pSVData->mpSalTimer->CallCallback();
- pSalData->mbInTimerProc = false;
- ImplSalYieldMutexRelease();
-
- // Run the timer in the correct time, if we start this
- // with a small timeout, because we don't get the mutex
- if (pSalData->mnTimerId && (pSalData->mnTimerMS != pSalData->mnTimerOrgMS))
- ImplSalStartTimer(pSalData->mnTimerOrgMS, false);
- }
+ pSalData->mbInTimerProc = true;
+ pSVData->mpSalTimer->CallCallback();
+ pSalData->mbInTimerProc = false;
+ ImplSalYieldMutexRelease();
}
else
+ {
ImplSalStartTimer(10, true);
+ }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 211b3192f05c4120fa2dd0e23988e74bdd310830
Author: Jan Holesovsky <kendy at collabora.com>
Date: Fri Sep 19 15:48:24 2014 +0200
fdo#84000: Reimplement the Windows WinSalTimer using Timer Queues.
Timer Queues
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686796%28v=vs.85%29.aspx
allow creating & maintaing high-precision timers. This commit switches the
WinSalTimer implementation from using the Timers:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644900%28v=vs.85%29.aspx
to Timer Queue Timers.
The 'classic' Timers do not have better precision than some 15.6ms (the
documentation mentions 10ms, but some measuring seems to confirm that it is
more than that).
With the Timer Queue Timers, we now have 1ms precision.
Incorporates some cleanup from Michael Meeks <michael.meeks at collabora.com>.
Change-Id: I0312a0c9fdc2779258698b24389b24c39e643473
diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx
index 0b147b4..71836e7 100644
--- a/tools/source/datetime/ttime.cxx
+++ b/tools/source/datetime/ttime.cxx
@@ -400,7 +400,19 @@ Time Time::GetUTCOffset()
sal_uIntPtr Time::GetSystemTicks()
{
#if defined WNT
- return (sal_uIntPtr)GetTickCount();
+ static LARGE_INTEGER nTicksPerMS;
+ static bool bTicksPerMSInitialized = false;
+ if (!bTicksPerMSInitialized)
+ {
+ QueryPerformanceFrequency(&nTicksPerMS);
+ nTicksPerMS.QuadPart /= 1000;
+ bTicksPerMSInitialized = true;
+ }
+
+ LARGE_INTEGER nPerformanceCount;
+ QueryPerformanceCounter(&nPerformanceCount);
+
+ return (sal_uIntPtr)(nPerformanceCount.QuadPart/nTicksPerMS.QuadPart);
#else
timeval tv;
gettimeofday (&tv, 0);
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index d047fc5..409ca3e 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -83,11 +83,11 @@ public:
long* mpDitherDiff; // Dither mapping table
BYTE* mpDitherLow; // Dither mapping table
BYTE* mpDitherHigh; // Dither mapping table
- sal_uLong mnTimerMS; // Current Time (in MS) of the Timer
- sal_uLong mnTimerOrgMS; // Current Original Time (in MS)
+ sal_uLong mnTimerMS; // Current Time (in MS) of the Timer
+ sal_uLong mnTimerOrgMS; // Current Original Time (in MS)
DWORD mnNextTimerTime;
DWORD mnLastEventTime;
- UINT mnTimerId; // windows timer id
+ HANDLE mnTimerId; ///< Windows timer id
bool mbInTimerProc; // timer event is currently being dispatched
HHOOK mhSalObjMsgHook; // hook to get interesting msg for SalObject
HWND mhWantLeaveMsg; // window handle, that want a MOUSELEAVE message
@@ -181,8 +181,7 @@ void ImplSalAcquireYieldMutex( sal_uLong nCount );
LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam );
-#define SALTIMERPROC_RECURSIVE 0xffffffff
-void CALLBACK SalTimerProc( HWND hWnd, UINT nMsg, UINT_PTR nId, DWORD nTime );
+void EmitTimerCallback(bool bAllowRecursive);
void SalTestMouseLeave();
bool ImplWriteLastError( DWORD lastError, const char *szApiCall );
@@ -286,6 +285,9 @@ int ImplSalWICompareAscii( const wchar_t* pStr1, const char* pStr2 );
// POSTFOCUS-Message; wParam == bFocus; lParam == 0
#define SALOBJ_MSG_POSTFOCUS (WM_USER+161)
+// Call the Timer's callback from the main thread
+#define SAL_MSG_TIMER_CALLBACK (WM_USER+162)
+
// A/W-Wrapper
BOOL ImplPostMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
BOOL ImplSendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx
index 7a697ae..c8eb110 100644
--- a/vcl/win/source/app/salinst.cxx
+++ b/vcl/win/source/app/salinst.cxx
@@ -736,7 +736,10 @@ LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lPar
rDef = FALSE;
break;
case SAL_MSG_POSTTIMER:
- SalTimerProc( 0, 0, SALTIMERPROC_RECURSIVE, lParam );
+ EmitTimerCallback(/*bAllowRecursive = */ true);
+ break;
+ case SAL_MSG_TIMER_CALLBACK:
+ EmitTimerCallback(/*bAllowRecursive = */ false);
break;
}
diff --git a/vcl/win/source/app/saltimer.cxx b/vcl/win/source/app/saltimer.cxx
index 287ec9a..779c691 100644
--- a/vcl/win/source/app/saltimer.cxx
+++ b/vcl/win/source/app/saltimer.cxx
@@ -29,25 +29,37 @@
// maximum period
#define MAX_SYSPERIOD 65533
+void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);
+
+// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms687003%28v=vs.85%29.aspx
+// (and related pages) for details about the Timer Queues.
+
+void ImplSalStopTimer(SalData* pSalData)
+{
+ HANDLE hTimer = pSalData->mnTimerId;
+ pSalData->mnTimerId = 0;
+ DeleteTimerQueueTimer(NULL, hTimer, 0);
+}
+
void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
{
SalData* pSalData = GetSalData();
// Remember the time of the timer
pSalData->mnTimerMS = nMS;
- if ( !bMutex )
+ if (!bMutex)
pSalData->mnTimerOrgMS = nMS;
// duration has to fit into Window's sal_uInt16
- if ( nMS > MAX_SYSPERIOD )
+ if (nMS > MAX_SYSPERIOD)
nMS = MAX_SYSPERIOD;
- // kill timer if it exists
- if ( pSalData->mnTimerId )
- KillTimer( 0, pSalData->mnTimerId );
+ // 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);
- // Make a new timer with new period
- pSalData->mnTimerId = SetTimer( 0, 0, (UINT)nMS, SalTimerProc );
pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
}
@@ -77,13 +89,17 @@ void WinSalTimer::Stop()
// If we have a timer, than
if ( pSalData->mnTimerId )
{
- KillTimer( 0, pSalData->mnTimerId );
- pSalData->mnTimerId = 0;
+ ImplSalStopTimer(pSalData);
pSalData->mnNextTimerTime = 0;
}
}
-void CALLBACK SalTimerProc( HWND, UINT, UINT_PTR nId, DWORD )
+/** This gets invoked from a Timer Queue thread.
+
+Don't acquire the SolarMutex to avoid deadlocks, just wake up the main thread
+at better resolution than 10ms.
+*/
+void CALLBACK SalTimerProc(PVOID, BOOLEAN)
{
#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
jmp_buf jmpbuf;
@@ -98,42 +114,58 @@ void CALLBACK SalTimerProc( HWND, UINT, UINT_PTR nId, DWORD )
SalData* pSalData = GetSalData();
ImplSVData* pSVData = ImplGetSVData();
- // Test for MouseLeave
- SalTestMouseLeave();
-
- bool bRecursive = pSalData->mbInTimerProc && (nId != SALTIMERPROC_RECURSIVE);
- if ( pSVData->mpSalTimer && ! bRecursive )
+ // don't allow recursive calls (mbInTimerProc is set when the callback
+ // is being processed)
+ if (pSVData->mpSalTimer && !pSalData->mbInTimerProc)
{
- // Try to acquire the mutex. If we don't get the mutex then we
- // try this a short time later again.
- if ( ImplSalYieldMutexTryToAcquire() )
- {
- bRecursive = pSalData->mbInTimerProc && (nId != SALTIMERPROC_RECURSIVE);
- if ( pSVData->mpSalTimer && ! bRecursive )
- {
- pSalData->mbInTimerProc = TRUE;
- pSVData->mpSalTimer->CallCallback();
- pSalData->mbInTimerProc = FALSE;
- ImplSalYieldMutexRelease();
-
- // Run the timer in the correct time, if we start this
- // with a small timeout, because we don't get the mutex
- if ( pSalData->mnTimerId &&
- (pSalData->mnTimerMS != pSalData->mnTimerOrgMS) )
- ImplSalStartTimer( pSalData->mnTimerOrgMS, FALSE );
- }
- }
- else
- ImplSalStartTimer( 10, TRUE );
+ ImplPostMessage(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);
}
- }
#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
+ }
han.Reset();
#else
+ }
__except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
{
}
#endif
}
+/** Called in the main thread.
+
+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.
+
+ at param bAllowRecursive allows to skip the check that assures that two timeouts
+do not overlap.
+*/
+void EmitTimerCallback(bool bAllowRecursive)
+{
+ SalData* pSalData = GetSalData();
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Test for MouseLeave
+ SalTestMouseLeave();
+
+ // Try to acquire the mutex. If we don't get the mutex then we
+ // try this a short time later again.
+ if (ImplSalYieldMutexTryToAcquire())
+ {
+ if (pSVData->mpSalTimer && (!pSalData->mbInTimerProc || bAllowRecursive))
+ {
+ pSalData->mbInTimerProc = true;
+ pSVData->mpSalTimer->CallCallback();
+ pSalData->mbInTimerProc = false;
+ ImplSalYieldMutexRelease();
+
+ // Run the timer in the correct time, if we start this
+ // with a small timeout, because we don't get the mutex
+ if (pSalData->mnTimerId && (pSalData->mnTimerMS != pSalData->mnTimerOrgMS))
+ ImplSalStartTimer(pSalData->mnTimerOrgMS, false);
+ }
+ }
+ else
+ ImplSalStartTimer(10, true);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list