Kaydet (Commit) d68ce6e1 authored tarafından Jan Holesovsky's avatar Jan Holesovsky

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
üst c1f8437d
......@@ -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);
......
......@@ -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 );
......
......@@ -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;
}
......
......@@ -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
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment