Rebased ref, commits from common ancestor: commit 9ec2e6352b13a19a632e3aaabb689257faabdb42 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Tue Oct 17 13:13:23 2017 +0200
Implement processing of (all) current LO tasks Processing all current events is currently just implemented for LO user events and system events, which is inconsistent. This implements the same functionality in the scheduler to process all current LO tasks. Currently used by DoYield in the Mac and Windows backends. This also fixes the testTriggerIdleFromIdle test, as this now correctly wait-yields until the watchdog kicks in. Change-Id: Icab8671ceae724a96959fa092ad00bff20c919e1 diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index ac429ed33b09..77396b90ae9c 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -43,16 +43,22 @@ class VCL_DLLPUBLIC Scheduler final static void Lock( sal_uInt32 nLockCount = 1 ); static sal_uInt32 Unlock( bool bUnlockAll = false ); + static bool ProcessSingleTask( sal_uInt64 nTime, + ImplSchedulerData ** const pLastDataPtr ); + public: static constexpr sal_uInt64 ImmediateTimeoutMs = 0; static constexpr sal_uInt64 InfiniteTimeoutMs = SAL_MAX_UINT64; static void ImplDeInitScheduler(); - /// Process one pending Timer with highhest priority - static void CallbackTaskScheduling(); - /// Process one pending task ahead of time with highest priority. - static bool ProcessTaskScheduling(); + /** + * Process one or all current pending tasks, ranked by priority + * + * @param bHandleAllCurrentEvents process one or all pending tasks + * @return true, if any task was processed + */ + static bool ProcessTaskScheduling( bool bHandleAllCurrentEvents ); /** * Process all events until none is pending * diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx index 60be08f83c09..64890b02129f 100644 --- a/sd/qa/unit/misc-tests.cxx +++ b/sd/qa/unit/misc-tests.cxx @@ -105,7 +105,7 @@ sd::DrawDocShellRef SdMiscTest::Load(const OUString& rURL, sal_Int32 nFormat) for (int i = 0; i < 1000; i++) { // Process all Tasks - slide sorter is created here - while (Scheduler::ProcessTaskScheduling()); + Scheduler::ProcessEventsToIdle(); if ((pSSVS = sd::slidesorter::SlideSorterViewShell::GetSlideSorter(pViewShell->GetViewShellBase())) != nullptr) break; osl::Thread::wait(std::chrono::milliseconds(100)); @@ -149,7 +149,7 @@ void SdMiscTest::testTdf96708() // Now wait for timers to trigger creation of auto-layout osl::Thread::wait(std::chrono::milliseconds(100)); - Scheduler::ProcessTaskScheduling(); + Scheduler::ProcessEventsToIdle(); rSSController.GetClipboard().DoPaste(); const sal_uInt16 nMasterPageCnt2 = xDocSh->GetDoc()->GetMasterSdPageCount(PageKind::Standard); diff --git a/vcl/README.scheduler b/vcl/README.scheduler index 80c14b032c54..ed44b66f5753 100644 --- a/vcl/README.scheduler +++ b/vcl/README.scheduler @@ -105,11 +105,8 @@ bool DoYield( bool bWait, bool bAllCurrent ) if ( !bAllCurrent && bWasEvent ) return true; bWasEvent = ProcessSystemEvents( bAllCurrent, &bWasSchedulerEvent ) || bWasEvent; - if ( !bWasSchedulerEvent && IsSchedulerEvent() ) - { - ProcessSchedulerEvent() - bWasEvent = true; - } + if ( (!bWasSchedulerEvent || bAllCurrent) && IsSchedulerEvent() ) + bWasEvent = ProcessSchedulerEvent( bAllCurrent ) || bWasEvent; if ( !bWasEvent && bWait ) { WaitForSystemEvents(); @@ -118,6 +115,11 @@ bool DoYield( bool bWait, bool bAllCurrent ) return bWasEvent; } +Since the Scheduler works priority based, processing all current events +might return before all current tasks are processed, if the next task +has a higher priority then a current task, but was started after the +current time! + == General: main thread deferral == Currently for Mac and Windows, we run main thread deferrals by disabling the diff --git a/vcl/android/androidinst.cxx b/vcl/android/androidinst.cxx index 3c181ace2ff6..13ce4f83061f 100644 --- a/vcl/android/androidinst.cxx +++ b/vcl/android/androidinst.cxx @@ -69,7 +69,7 @@ AndroidSalInstance::~AndroidSalInstance() bool AndroidSalInstance::AnyInput( VclInputFlags nType ) { if( nType & VclInputFlags::TIMER ) - return CheckTimeout( false ); + return HandleTimeout( HandleTimeoutMode::CheckOnly ); // Unfortunately there is no way to check for a specific type of // input being queued. That information is too hidden, sigh. diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx index 44df78a7df60..478fcfd85c5e 100644 --- a/vcl/headless/svpinst.cxx +++ b/vcl/headless/svpinst.cxx @@ -164,7 +164,7 @@ void SvpSalInstance::Wakeup() #endif } -bool SvpSalInstance::CheckTimeout( bool bExecuteTimers ) +bool SvpSalInstance::HandleTimeout( const HandleTimeoutMode eMode ) { bool bRet = false; if( m_aTimeout.tv_sec ) // timer is started @@ -174,7 +174,7 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers ) if( aTimeOfDay >= m_aTimeout ) { bRet = true; - if( bExecuteTimers ) + if( eMode != HandleTimeoutMode::CheckOnly ) { // timed out, update timeout m_aTimeout = aTimeOfDay; @@ -183,9 +183,8 @@ bool SvpSalInstance::CheckTimeout( bool bExecuteTimers ) osl::Guard< comphelper::SolarMutex > aGuard( mpSalYieldMutex.get() ); // notify - ImplSVData* pSVData = ImplGetSVData(); - if( pSVData->maSchedCtx.mpSalTimer ) - pSVData->maSchedCtx.mpSalTimer->CallCallback(); + bRet = SalTimer::CallCallback( + eMode == HandleTimeoutMode::ProcessAllCurrentTasks ); } } } @@ -269,7 +268,9 @@ bool SvpSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents) if ( !bHandleAllCurrentEvents &&bEvent ) return true; - bEvent = CheckTimeout() || bEvent; + bEvent = HandleTimeout( bHandleAllCurrentEvents + ? HandleTimeoutMode::ProcessAllCurrentTasks + : HandleTimeoutMode::ProcessSingleTask ) || bEvent; if (bWait && ! bEvent ) { @@ -330,7 +331,7 @@ void SvpSalInstance::DoReleaseYield( int nTimeoutMS ) bool SvpSalInstance::AnyInput( VclInputFlags nType ) { if( nType & VclInputFlags::TIMER ) - return CheckTimeout( false ); + return HandleTimeout( HandleTimeoutMode::CheckOnly ); return false; } diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx index ba80960326dc..17ee24cd8107 100644 --- a/vcl/inc/headless/svpinst.hxx +++ b/vcl/inc/headless/svpinst.hxx @@ -85,7 +85,7 @@ public: inline void registerFrame( SalFrame* pFrame ); inline void deregisterFrame( SalFrame* pFrame ); - bool CheckTimeout( bool bExecuteTimers = true ); + bool HandleTimeout( HandleTimeoutMode eMode ); // Frame virtual SalFrame* CreateChildFrame( SystemParentData* pParent, SalFrameStyleFlags nStyle ) override; diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx index 357a2df6a74b..fea6d4908ea2 100644 --- a/vcl/inc/osx/saldata.hxx +++ b/vcl/inc/osx/saldata.hxx @@ -62,7 +62,6 @@ class SystemFontList; class SalData { public: - SALTIMERPROC mpTimerProc; // timer callback proc AquaSalInstance *mpInstance; std::list<AquaSalFrame*> maPresentationFrames; // list of frames in presentation mode SalObject *mpFirstObject; // pointer of first object window diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h index a9934f280636..97c8db397e9c 100644 --- a/vcl/inc/osx/saltimer.h +++ b/vcl/inc/osx/saltimer.h @@ -47,7 +47,7 @@ class AquaSalTimer final : public SalTimer, protected VersionedEvent bool m_bDirectTimeout; ///< timeout can be processed directly void queueDispatchTimerEvent( bool bAtStart ); - void callTimerCallback(); + bool callTimerCallback( bool bHandleAllCurrentEvents ); public: AquaSalTimer(); @@ -58,7 +58,7 @@ public: void handleStartTimerEvent( NSEvent* pEvent ); bool handleDispatchTimerEvent( NSEvent* pEvent ); - void handleTimerElapsed(); + bool handleTimerElapsed( bool bHandleAllCurrentEvents ); void handleWindowShouldClose(); bool IsTimerElapsed() const; diff --git a/vcl/inc/saltimer.hxx b/vcl/inc/saltimer.hxx index 983e0771ee9b..9fde8de82071 100644 --- a/vcl/inc/saltimer.hxx +++ b/vcl/inc/saltimer.hxx @@ -22,8 +22,9 @@ #include <sal/config.h> #include <vcl/dllapi.h> -#include <salwtype.hxx> -#include <iostream> +#include <svdata.hxx> + +typedef bool (*SALTIMERPROC)( bool bHandleAllCurrentEvents ); /* * note: there will be only a single instance of SalTimer @@ -40,19 +41,32 @@ public: virtual ~SalTimer() COVERITY_NOEXCEPT_FALSE; // AutoRepeat and Restart - virtual void Start( sal_uLong nMS ) = 0; - virtual void Stop() = 0; + virtual void Start( sal_uLong nMS ) = 0; + virtual void Stop() = 0; // Callbacks (indepen in \sv\source\app\timer.cxx) - void SetCallback( SALTIMERPROC pProc ) + void SetCallback( SALTIMERPROC pProc ) { m_pProc = pProc; } - void CallCallback() + bool Timeout( bool bHandleAllCurrentEvents ) { + bool bRet = false; if( m_pProc ) - m_pProc(); + bRet = m_pProc( bHandleAllCurrentEvents ); + return bRet; + } + + static bool CallCallback( bool bHandleAllCurrentEvents ) + { + ImplSVData* pSVData = ImplGetSVData(); + bool bRet = false; + assert( pSVData ); + SalTimer *pTimer = pSVData->maSchedCtx.mpSalTimer; + if( pTimer ) + bRet = pTimer->Timeout( bHandleAllCurrentEvents ); + return bRet; } }; diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx index 1538c8e78a25..e4eca95dcfe8 100644 --- a/vcl/inc/salwtype.hxx +++ b/vcl/inc/salwtype.hxx @@ -215,7 +215,8 @@ struct SalQueryCharPositionEvent typedef bool (*SALFRAMEPROC)( vcl::Window* pInst, SalEvent nEvent, const void* pEvent ); -enum class SalObjEvent { +enum class SalObjEvent +{ GetFocus = 1, LoseFocus = 2, ToTop = 3 @@ -258,7 +259,12 @@ struct SalLongPressEvent long mnY; }; -typedef void (*SALTIMERPROC)(); +enum class HandleTimeoutMode +{ + CheckOnly, + ProcessSingleTask, + ProcessAllCurrentTasks +}; #endif // INCLUDED_VCL_INC_SALWTYPE_HXX diff --git a/vcl/inc/unx/saldata.hxx b/vcl/inc/unx/saldata.hxx index 6a7902dbf444..753f6ce8973b 100644 --- a/vcl/inc/unx/saldata.hxx +++ b/vcl/inc/unx/saldata.hxx @@ -72,8 +72,6 @@ public: SalXLib* GetLib() const { return pXLib_; } - static void Timeout(); - // X errors virtual void ErrorTrapPush() override; virtual bool ErrorTrapPop( bool bIgnoreError = true ) override; diff --git a/vcl/inc/unx/saldisp.hxx b/vcl/inc/unx/saldisp.hxx index 54799149e25c..e8d0f7b67bb9 100644 --- a/vcl/inc/unx/saldisp.hxx +++ b/vcl/inc/unx/saldisp.hxx @@ -179,7 +179,7 @@ public: virtual void StartTimer( sal_uLong nMS ); virtual void StopTimer(); - virtual bool CheckTimeout( bool bExecuteTimers = true ); + virtual bool HandleTimeout( HandleTimeoutMode eMode ); SalI18N_InputMethod* GetInputMethod() const { return m_pInputMethod; } Display* GetDisplay() const { return m_pDisplay; } diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h index 61d284d82ddb..ec6b8faebd7a 100644 --- a/vcl/inc/win/saltimer.h +++ b/vcl/inc/win/saltimer.h @@ -43,7 +43,7 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent void ImplStart( sal_uIntPtr nMS ); void ImplStop(); bool ImplHandleTimerEvent( WPARAM aWPARAM ); - void ImplHandleElapsedTimer(); + bool ImplHandleElapsedTimer( bool bHandleAllCurrentEvents ); bool ImplHandle_WM_TIMER( WPARAM aWPARAM ); public: diff --git a/vcl/osx/saldata.cxx b/vcl/osx/saldata.cxx index a445e5cfb7ad..b35210bc6754 100644 --- a/vcl/osx/saldata.cxx +++ b/vcl/osx/saldata.cxx @@ -36,7 +36,6 @@ static void SAL_CALL releasePool( void* pPool ) SalData::SalData() : - mpTimerProc( nullptr ), mpInstance( nullptr ), mpFirstObject( nullptr ), mpFirstVD( nullptr ), diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm index c0d28fe4bc3f..5798f5b3e7a1 100644 --- a/vcl/osx/salframeview.mm +++ b/vcl/osx/salframeview.mm @@ -538,7 +538,7 @@ private: if ( bWasLiveResize != bIsLiveResize ) { GetSalData()->mpInstance->mbIsLiveResize = bIsLiveResize; - Scheduler::ProcessTaskScheduling(); + Scheduler::ProcessTaskScheduling( false ); } } diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index 922046bcbfe8..8add64168bb3 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -603,11 +603,8 @@ SAL_WNODEPRECATED_DECLARATIONS_POP while( true ); AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); - if ( !mbTimerProcessed && pTimer && pTimer->IsDirectTimeout() ) - { - pTimer->handleTimerElapsed(); - bHadEvent = true; - } + if ( (!mbTimerProcessed || bHandleAllCurrentEvents) && pTimer && pTimer->IsDirectTimeout() ) + bHadEvent = pTimer->handleTimerElapsed( bHandleAllCurrentEvents ) || bHadEvent; // if we had no event yet, wait for one if requested if( bWait && ! bHadEvent ) diff --git a/vcl/osx/salnstimer.mm b/vcl/osx/salnstimer.mm index 9647bb6b87c1..b21e6a7e9695 100644 --- a/vcl/osx/salnstimer.mm +++ b/vcl/osx/salnstimer.mm @@ -32,7 +32,7 @@ (void) pNSTimer; AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); if (pTimer) - pTimer->handleTimerElapsed(); + pTimer->handleTimerElapsed( false ); } @end diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx index af18ae7ea740..60bf9a67e5e1 100644 --- a/vcl/osx/saltimer.cxx +++ b/vcl/osx/saltimer.cxx @@ -90,7 +90,10 @@ void AquaSalTimer::Start( sal_uLong nMS ) } if ( 0 == nMS && !pSalData->mpInstance->mbIsLiveResize ) - queueDispatchTimerEvent( NO ); + { + Stop(); + m_bDirectTimeout = true; + } else { NSTimeInterval aTI = double(nMS) / 1000.0; @@ -136,32 +139,33 @@ void AquaSalTimer::Stop() InvalidateEvent(); } -void AquaSalTimer::callTimerCallback() +bool AquaSalTimer::callTimerCallback( bool bHandleAllCurrentEvents ) { - ImplSVData* pSVData = ImplGetSVData(); SolarMutexGuard aGuard; m_bDirectTimeout = false; - if( pSVData->maSchedCtx.mpSalTimer ) - pSVData->maSchedCtx.mpSalTimer->CallCallback(); + return SalTimer::CallCallback( bHandleAllCurrentEvents ); } -void AquaSalTimer::handleTimerElapsed() +bool AquaSalTimer::handleTimerElapsed( bool bHandleAllCurrentEvent ) { + bool bRet = false; + if ( m_bDirectTimeout || GetSalData()->mpInstance->mbIsLiveResize ) { - // Stop the timer, as it is just invalidated after the firing function - Stop(); - callTimerCallback(); - } - else - queueDispatchTimerEvent( YES ); + // Stop the timer, as it is just invalidated after the firing function + Stop(); + bRet = callTimerCallback( bHandleAllCurrentEvent ); + } + else + queueDispatchTimerEvent( YES ); + return bRet; } bool AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent ) { bool bIsValidEvent = IsValidEventVersion( [pEvent data1] ); if ( bIsValidEvent ) - callTimerCallback(); + callTimerCallback( false ); return bIsValidEvent; } diff --git a/vcl/qa/cppunit/lifecycle.cxx b/vcl/qa/cppunit/lifecycle.cxx index 26f8796a57ea..18160ccdb056 100644 --- a/vcl/qa/cppunit/lifecycle.cxx +++ b/vcl/qa/cppunit/lifecycle.cxx @@ -212,7 +212,7 @@ void LifecycleTest::testFocus() xWin->Show(); xChild->GrabFocus(); // process asynchronous ToTop - Scheduler::ProcessTaskScheduling(); + Scheduler::ProcessTaskScheduling( false ); // FIXME: really awful to test focus issues without showing windows. // CPPUNIT_ASSERT(xChild->HasFocus()); } diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx index 7b712bd76c04..a94d44cb7a15 100644 --- a/vcl/qa/cppunit/timer.cxx +++ b/vcl/qa/cppunit/timer.cxx @@ -402,8 +402,10 @@ public: { Start(); if (mpOther) + { mpOther->Start(); - Application::Yield(); + Application::Yield(); + } if (mpTriggered) *mpTriggered = true; } diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index 8fd26ec79a55..6c3059cedec1 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -236,7 +236,7 @@ void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime) rSchedCtx.mnTimerStart = 0; rSchedCtx.mnTimerPeriod = InfiniteTimeoutMs; rSchedCtx.mpSalTimer = pSVData->mpDefInst->CreateSalTimer(); - rSchedCtx.mpSalTimer->SetCallback(Scheduler::CallbackTaskScheduling); + rSchedCtx.mpSalTimer->SetCallback( Scheduler::ProcessTaskScheduling ); } assert(SAL_MAX_UINT64 - nMS >= nTime); @@ -256,12 +256,6 @@ void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime) } } -void Scheduler::CallbackTaskScheduling() -{ - // this function is for the saltimer callback - Scheduler::ProcessTaskScheduling(); -} - static bool g_bDeterministicMode = false; void Scheduler::SetDeterministicMode(bool bDeterministic) @@ -325,7 +319,8 @@ static inline ImplSchedulerData* DropSchedulerData( return pSchedulerDataNext; } -bool Scheduler::ProcessTaskScheduling() +bool Scheduler::ProcessSingleTask( const sal_uInt64 nTime, + ImplSchedulerData ** const pLastDataPtr ) { ImplSVData *pSVData = ImplGetSVData(); ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx; @@ -336,25 +331,26 @@ bool Scheduler::ProcessTaskScheduling() if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod ) return false; - sal_uInt64 nTime = tools::Time::GetSystemTicks(); if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod ) { - SAL_WARN( "vcl.schedule", "we're too early - restart the timer!" ); + SAL_WARN_IF( !pLastDataPtr, + "vcl.schedule", "we're too early - restart the timer!" ); UpdateSystemTimer( rSchedCtx, rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod - nTime, true, nTime ); return false; } - ImplSchedulerData* pSchedulerData = nullptr; + ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData; ImplSchedulerData* pPrevSchedulerData = nullptr; ImplSchedulerData *pMostUrgent = nullptr; ImplSchedulerData *pPrevMostUrgent = nullptr; sal_uInt64 nMinPeriod = InfiniteTimeoutMs; sal_uInt64 nMostUrgentPeriod = InfiniteTimeoutMs; sal_uInt64 nReadyPeriod = InfiniteTimeoutMs; + bool bAfterLastData = false; + bool bInvokeMostUrgent = ( !pLastDataPtr || *pLastDataPtr ); - pSchedulerData = rSchedCtx.mpFirstSchedulerData; while ( pSchedulerData ) { const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask ); @@ -386,6 +382,8 @@ bool Scheduler::ProcessTaskScheduling() pSchedulerData->mpTask->mpSchedulerData = nullptr; delete pSchedulerData; } + if ( pLastDataPtr && *pLastDataPtr == pSchedulerData ) + bAfterLastData = true; pSchedulerData = pSchedulerDataNext; continue; } @@ -404,11 +402,15 @@ bool Scheduler::ProcessTaskScheduling() pPrevMostUrgent = pPrevSchedulerData; pMostUrgent = pSchedulerData; nMostUrgentPeriod = nReadyPeriod; + if ( bAfterLastData || pMostUrgent->mnUpdateTime > nTime ) + bInvokeMostUrgent = false; } else if ( nMinPeriod > nReadyPeriod ) nMinPeriod = nReadyPeriod; next_entry: + if ( pLastDataPtr && *pLastDataPtr == pSchedulerData ) + bAfterLastData = true; pPrevSchedulerData = pSchedulerData; pSchedulerData = pSchedulerData->mpNext; } @@ -417,8 +419,19 @@ next_entry: SAL_INFO("vcl.schedule", "Calculated minimum timeout as " << nMinPeriod ); UpdateSystemTimer( rSchedCtx, nMinPeriod, true, nTime ); - if ( pMostUrgent ) + if ( pMostUrgent && !bInvokeMostUrgent ) + { + nReadyPeriod = pMostUrgent->mpTask->UpdateMinPeriod( nMinPeriod, nTime ); + if ( nMinPeriod > nReadyPeriod ) + nMinPeriod = nReadyPeriod; + UpdateSystemTimer( rSchedCtx, nMinPeriod, false, nTime ); + pMostUrgent = nullptr; + } + else if ( pMostUrgent ) { + if ( pLastDataPtr && *pLastDataPtr == pMostUrgent ) + *pLastDataPtr = nullptr; + SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " " << pMostUrgent << " invoke-in " << *pMostUrgent->mpTask ); @@ -460,6 +473,8 @@ next_entry: AppendSchedulerData( rSchedCtx, pSchedulerData ); UpdateSystemTimer( rSchedCtx, ImmediateTimeoutMs, true, tools::Time::GetSystemTicks() ); + if ( pLastDataPtr && *pLastDataPtr && rSchedCtx.mpLastSchedulerData != *pLastDataPtr ) + *pLastDataPtr = rSchedCtx.mpLastSchedulerData; } else { @@ -484,6 +499,26 @@ next_entry: return !!pMostUrgent; } +bool Scheduler::ProcessTaskScheduling( bool bHandleAllCurrentEvents ) +{ + sal_uInt64 nTime = tools::Time::GetSystemTicks(); + bool bWasEvent = false, bAnyEvent = false; + ImplSchedulerData *pLastData = ImplGetSVData()->maSchedCtx.mpLastSchedulerData; + ImplSchedulerData ** const pLastDataPtr = bHandleAllCurrentEvents ? &pLastData : nullptr; + SAL_INFO_IF( bHandleAllCurrentEvents, "vcl.schedule", tools::Time::GetSystemTicks() + << " process all current events - start" ); + do + { + bWasEvent = ProcessSingleTask( nTime, pLastDataPtr ); + if ( !bAnyEvent && bWasEvent ) + bAnyEvent = bWasEvent; + } + while ( bWasEvent && bHandleAllCurrentEvents ); + SAL_INFO_IF( bHandleAllCurrentEvents, "vcl.schedule", tools::Time::GetSystemTicks() + << " process all current events - done" ); + return bAnyEvent; +} + void Task::StartTimer( sal_uInt64 nMS ) { Scheduler::ImplStartTimer( nMS, false, tools::Time::GetSystemTicks() ); diff --git a/vcl/unx/generic/app/saldata.cxx b/vcl/unx/generic/app/saldata.cxx index 4ad2c02db54f..39bab4f7368f 100644 --- a/vcl/unx/generic/app/saldata.cxx +++ b/vcl/unx/generic/app/saldata.cxx @@ -560,13 +560,6 @@ void X11SalData::XError( Display *pDisplay, XErrorEvent *pEvent ) m_aXErrorHandlerStack.back().m_bWas = true; } -void X11SalData::Timeout() -{ - ImplSVData* pSVData = ImplGetSVData(); - if( pSVData->maSchedCtx.mpSalTimer ) - pSVData->maSchedCtx.mpSalTimer->CallCallback(); -} - struct YieldEntry { int fd; // file descriptor for reading @@ -622,7 +615,7 @@ void SalXLib::Remove( int nFD ) } } -bool SalXLib::CheckTimeout( bool bExecuteTimers ) +bool SalXLib::HandleTimeout( HandleTimeoutMode eMode ) { bool bRet = false; if( m_aTimeout.tv_sec ) // timer is started @@ -632,7 +625,7 @@ bool SalXLib::CheckTimeout( bool bExecuteTimers ) if( aTimeOfDay >= m_aTimeout ) { bRet = true; - if( bExecuteTimers ) + if( eMode != HandleTimeoutMode::CheckOnly ) { // timed out, update timeout m_aTimeout = aTimeOfDay; @@ -644,7 +637,7 @@ bool SalXLib::CheckTimeout( bool bExecuteTimers ) */ m_aTimeout += m_nTimeoutMS; // notify - X11SalData::Timeout(); + bRet = SalTimer::CallCallback( eMode == HandleTimeoutMode::ProcessAllCurrentTasks ); } } } @@ -655,10 +648,7 @@ bool SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) { // check for timeouts here if you want to make screenshots - static char* p_prioritize_timer = getenv ("SAL_HIGHPRIORITY_REPAINT"); bool bHandledEvent = false; - if (p_prioritize_timer != nullptr) - bHandledEvent = CheckTimeout(); const int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1; @@ -724,8 +714,9 @@ SalXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) } // usually handle timeouts here (as in 5.2) - if (p_prioritize_timer == nullptr) - bHandledEvent = CheckTimeout() || bHandledEvent; + bHandledEvent = HandleTimeout( bHandleAllCurrentEvents + ? HandleTimeoutMode::ProcessAllCurrentTasks + : HandleTimeoutMode::ProcessSingleTask ) || bHandledEvent; // handle wakeup events. if ((nFound > 0) && FD_ISSET(m_pTimeoutFDS[0], &ReadFDS)) diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx index 0d30e1d17a99..b1615b052e94 100644 --- a/vcl/unx/generic/app/salinst.cxx +++ b/vcl/unx/generic/app/salinst.cxx @@ -145,7 +145,8 @@ bool X11SalInstance::AnyInput(VclInputFlags nType) Display *pDisplay = vcl_sal::getSalDisplay(pData)->GetDisplay(); bool bRet = false; - if( (nType & VclInputFlags::TIMER) && (mpXLib && mpXLib->CheckTimeout(false)) ) + if( (nType & VclInputFlags::TIMER) + && mpXLib && mpXLib->HandleTimeout( HandleTimeoutMode::CheckOnly ) ) bRet = true; if( !bRet && XPending(pDisplay) ) diff --git a/vcl/unx/gtk/gtkdata.cxx b/vcl/unx/gtk/gtkdata.cxx index 97541eed22c1..6f849f212eaa 100644 --- a/vcl/unx/gtk/gtkdata.cxx +++ b/vcl/unx/gtk/gtkdata.cxx @@ -728,9 +728,7 @@ extern "C" { sal_gtk_timeout_defer( pTSource ); - ImplSVData* pSVData = ImplGetSVData(); - if( pSVData->maSchedCtx.mpSalTimer ) - pSVData->maSchedCtx.mpSalTimer->CallCallback(); + SalTimer::CallCallback( false ); return G_SOURCE_REMOVE; } diff --git a/vcl/unx/gtk3/gtk3gtkdata.cxx b/vcl/unx/gtk3/gtk3gtkdata.cxx index f4d41a53d2c0..bf69882d181f 100644 --- a/vcl/unx/gtk3/gtk3gtkdata.cxx +++ b/vcl/unx/gtk3/gtk3gtkdata.cxx @@ -693,9 +693,7 @@ extern "C" { sal_gtk_timeout_defer( pTSource ); - ImplSVData* pSVData = ImplGetSVData(); - if( pSVData->maSchedCtx.mpSalTimer ) - pSVData->maSchedCtx.mpSalTimer->CallCallback(); + SalTimer::CallCallback( false ); return G_SOURCE_REMOVE; } diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index 43e055a2c0bb..8be84f99a925 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -42,6 +42,8 @@ #include "KDESalDisplay.hxx" +#include <saltimer.hxx> + #if KDE4_HAVE_GLIB #include "KDE4FilePicker.hxx" #include "tst_exclude_socket_notifiers.moc" @@ -356,11 +358,11 @@ void KDEXLib::StopTimer() timeoutTimer.stop(); } -bool KDEXLib::CheckTimeout( bool bExecuteTimers ) +bool KDEXLib::HandleTimeout( HandleTimeoutMode eMode ) { if( !m_isGlibEventLoopType ) - return SalXLib::CheckTimeout( bExecuteTimers ); - assert( !bExecuteTimers ); + return SalXLib::HandleTimeout( eMode ); + assert( eMode == HandleTimeoutMode::CheckOnly ); return m_bTimedOut; } @@ -376,7 +378,7 @@ void KDEXLib::customEvent(QEvent* e) if( e->type() == m_timerEventId ) { m_bTimedOut = false; - X11SalData::Timeout(); + SalTimer::CallCallback( false ); } } diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx index 452aae8b3286..e2d6d6b024fb 100644 --- a/vcl/unx/kde4/KDEXLib.hxx +++ b/vcl/unx/kde4/KDEXLib.hxx @@ -84,7 +84,7 @@ public: virtual void Remove( int fd ) override; virtual void StartTimer( sal_uLong nMS ) override; virtual void StopTimer() override; - virtual bool CheckTimeout( bool bExecuteTimers = true ) override; + virtual bool HandleTimeout( HandleTimeoutMode eMode ) override; virtual void Wakeup() override; void TriggerUserEventProcessing(); diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index f2a998ee78e7..ceb3651b4353 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -512,11 +512,8 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) // event loop with timeout messages. // We ensure we never handle more then one timeout per call. // This way we'll always process a normal system message. - if ( !bWasTimeoutMsg && pTimer && pTimer->IsDirectTimeout() ) - { - pTimer->ImplHandleElapsedTimer(); - bWasMsg = true; - } + if ( (!bWasTimeoutMsg || bHandleAllCurrentEvents) && pTimer && pTimer->IsDirectTimeout() ) + bWasMsg = pTimer->ImplHandleElapsedTimer( bHandleAllCurrentEvents ) || bWasMsg; if ( bHandleAllCurrentEvents ) nLastTicks = nCurTicks; diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx index 9c67e841956e..2098e757d953 100644 --- a/vcl/win/app/saltimer.cxx +++ b/vcl/win/app/saltimer.cxx @@ -147,15 +147,16 @@ void CALLBACK SalTimerProc(PVOID data, BOOLEAN) } } -void WinSalTimer::ImplHandleElapsedTimer() +bool WinSalTimer::ImplHandleElapsedTimer( bool bHandleAllCurrentEvents ) { // Test for MouseLeave SalTestMouseLeave(); m_bDirectTimeout = false; ImplSalYieldMutexAcquireWithWait(); - CallCallback(); + bool bRet = Timeout( bHandleAllCurrentEvents ); ImplSalYieldMutexRelease(); + return bRet; } bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM ) @@ -163,9 +164,7 @@ bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM ) assert( aWPARAM <= SAL_MAX_INT32 ); if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) ) return false; - - ImplHandleElapsedTimer(); - return true; + return ImplHandleElapsedTimer( false ); } void WinSalTimer::SetForceRealTimer( const bool bVal ) @@ -185,9 +184,7 @@ bool WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM ) assert( m_aWmTimerId == aWPARAM ); if ( !(m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer) ) return false; - - ImplHandleElapsedTimer(); - return true; + return ImplHandleElapsedTimer( false ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 7f9415fcb0e7fd765bb69988e14086b2ec7a340c Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Mon Oct 16 17:04:24 2017 +0200 WIN scheduler cleanup and refactoring Replace a lot of duplicated case code with macros. Some minor constifications of function parameters. I restrained from shorten the SAL_MSG_* via preprocessor concat, so a grep will still find the whole names. Change-Id: If1f2477fc8817b4ae7816e807154e35004bb4da9 diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h index 01e50af77b99..a80af4fb5ee7 100644 --- a/vcl/inc/osx/salinst.h +++ b/vcl/inc/osx/salinst.h @@ -63,6 +63,8 @@ public: class AquaSalInstance : public SalInstance, public SalUserEventList { + friend class AquaSalFrame; + bool RunInMainYield( bool bHandleAllCurrentEvents ); virtual void TriggerUserEventProcessing() override; @@ -81,7 +83,6 @@ public: static std::list<const ApplicationEvent*> aAppEventList; -public: AquaSalInstance(); virtual ~AquaSalInstance() override; @@ -136,9 +137,6 @@ public: // this is needed to avoid duplicate open events through a) command line and b) NSApp's openFile static bool isOnCommandLine( const OUString& ); -public: - friend class AquaSalFrame; - void delayedSettingsChanged( bool bInvalidate ); // Is this the NSAppThread? diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx index 0f3e05b8f31a..659fd68f7dda 100644 --- a/vcl/inc/win/saldata.hxx +++ b/vcl/inc/win/saldata.hxx @@ -180,8 +180,8 @@ bool ImplHandleSalObjSysCharMsg( HWND hWnd, WPARAM wParam, LPARAM lParam ); bool ImplHandleGlobalMsg( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT& rlResult ); WinSalObject* ImplFindSalObject( HWND hWndChild ); -bool ImplSalPreDispatchMsg( MSG* pMsg ); -void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT nDispatchResult ); +bool ImplSalPreDispatchMsg( const MSG* pMsg ); +void ImplSalPostDispatchMsg( const MSG* pMsg ); void ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, vcl::Font& rFont ); diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h index b7d1a1e0d0f1..61d284d82ddb 100644 --- a/vcl/inc/win/saltimer.h +++ b/vcl/inc/win/saltimer.h @@ -25,7 +25,7 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent { // for access to Impl* functions - friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ); + friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef ); // for access to GetNextVersionedEvent friend void CALLBACK SalTimerProc( PVOID data, BOOLEAN ); // for access to ImplHandleElapsedTimer diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm index 4dd8ceac8169..23b22c360eeb 100644 --- a/vcl/osx/vclnsapp.mm +++ b/vcl/osx/vclnsapp.mm @@ -66,7 +66,7 @@ SAL_WNODEPRECATED_DECLARATIONS_PUSH NSEvent* pEvent = [NSEvent otherEventWithType: NSApplicationDefined location: NSZeroPoint modifierFlags: 0 - timestamp: 0 + timestamp: [[NSProcessInfo processInfo] systemUptime] windowNumber: 0 context: nil subtype: AquaSalInstance::AppExecuteSVMain diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index 5fcca5cde5b4..f2a998ee78e7 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -569,124 +569,108 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents) return bDidWork; } -LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ) +#define CASE_NOYIELDLOCK( salmsg, function ) \ + case salmsg: \ + assert( !pInst->mbNoYieldLock ); \ + pInst->mbNoYieldLock = true; \ + function; \ + pInst->mbNoYieldLock = false; \ + break; + +#define CASE_NOYIELDLOCK_RESULT( salmsg, function ) \ + case salmsg: \ + assert( !pInst->mbNoYieldLock ); \ + pInst->mbNoYieldLock = true; \ + nRet = reinterpret_cast<LRESULT>( function ); \ + pInst->mbNoYieldLock = false; \ + break; + +LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, bool& rDef ) { LRESULT nRet = 0; WinSalInstance *pInst = GetSalData()->mpInstance; + WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); switch ( nMsg ) { case SAL_MSG_THREADYIELD: assert( !(bool)wParam ); - nRet = static_cast<LRESULT>(ImplSalYield( false, (bool)lParam )); - rDef = FALSE; + nRet = static_cast<LRESULT>(ImplSalYield( + false, static_cast<bool>( lParam ) )); break; + case SAL_MSG_STARTTIMER: { sal_uInt64 nTime = tools::Time::GetSystemTicks(); - if ( nTime < (sal_uInt64) lParam ) - nTime = (sal_uInt64) lParam - nTime; + if ( nTime < static_cast<sal_uInt64>( lParam ) ) + nTime = static_cast<sal_uInt64>( lParam ) - nTime; else nTime = 0; - static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStart( nTime ); - rDef = FALSE; + assert( pTimer != nullptr ); + pTimer->ImplStart( nTime ); break; } + case SAL_MSG_STOPTIMER: - static_cast<WinSalTimer*>(ImplGetSVData()->maSchedCtx.mpSalTimer)->ImplStop(); - break; - case SAL_MSG_CREATEFRAME: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - nRet = reinterpret_cast<LRESULT>(ImplSalCreateFrame( GetSalData()->mpInstance, reinterpret_cast<HWND>(lParam), (SalFrameStyleFlags)wParam )); - pInst->mbNoYieldLock = false; - rDef = FALSE; - break; - case SAL_MSG_RECREATEHWND: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false )); - pInst->mbNoYieldLock = false; - rDef = FALSE; - break; - case SAL_MSG_RECREATECHILDHWND: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - nRet = reinterpret_cast<LRESULT>(ImplSalReCreateHWND( reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true )); - pInst->mbNoYieldLock = false; - rDef = FALSE; - break; - case SAL_MSG_DESTROYFRAME: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - delete reinterpret_cast<SalFrame*>(lParam); - pInst->mbNoYieldLock = false; - rDef = FALSE; + assert( pTimer != nullptr ); + pTimer->ImplStop(); break; + + CASE_NOYIELDLOCK_RESULT( SAL_MSG_CREATEFRAME, ImplSalCreateFrame( GetSalData()->mpInstance, + reinterpret_cast<HWND>(lParam), static_cast<SalFrameStyleFlags>(wParam)) ) + CASE_NOYIELDLOCK_RESULT( SAL_MSG_RECREATEHWND, ImplSalReCreateHWND( + reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), false) ) + CASE_NOYIELDLOCK_RESULT( SAL_MSG_RECREATECHILDHWND, ImplSalReCreateHWND( + reinterpret_cast<HWND>(wParam), reinterpret_cast<HWND>(lParam), true) ) + CASE_NOYIELDLOCK( SAL_MSG_DESTROYFRAME, delete reinterpret_cast<SalFrame*>(lParam) ) + case SAL_MSG_DESTROYHWND: - //We only destroy the native window here. We do NOT destroy the SalFrame contained - //in the structure (GetWindowPtr()). + // We only destroy the native window here. We do NOT destroy the SalFrame contained + // in the structure (GetWindowPtr()). if (DestroyWindow(reinterpret_cast<HWND>(lParam)) == 0) { OSL_FAIL("DestroyWindow failed!"); - //Failure: We remove the SalFrame from the window structure. So we avoid that + // Failure: We remove the SalFrame from the window structure. So we avoid that // the window structure may contain an invalid pointer, once the SalFrame is deleted. - SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr); + SetWindowPtr(reinterpret_cast<HWND>(lParam), nullptr); } - rDef = FALSE; - break; - case SAL_MSG_CREATEOBJECT: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - nRet = reinterpret_cast<LRESULT>(ImplSalCreateObject( GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam) )); - pInst->mbNoYieldLock = false; - rDef = FALSE; - break; - case SAL_MSG_DESTROYOBJECT: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - delete reinterpret_cast<SalObject*>(lParam); - pInst->mbNoYieldLock = false; - rDef = FALSE; - break; - case SAL_MSG_GETDC: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - nRet = reinterpret_cast<LRESULT>(GetDCEx( reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE )); - pInst->mbNoYieldLock = false; - rDef = FALSE; - break; - case SAL_MSG_RELEASEDC: - assert( !pInst->mbNoYieldLock ); - pInst->mbNoYieldLock = true; - ReleaseDC( reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam) ); - pInst->mbNoYieldLock = false; - rDef = FALSE; break; + + CASE_NOYIELDLOCK_RESULT( SAL_MSG_CREATEOBJECT, ImplSalCreateObject( + GetSalData()->mpInstance, reinterpret_cast<WinSalFrame*>(lParam)) ) + CASE_NOYIELDLOCK( SAL_MSG_DESTROYOBJECT, delete reinterpret_cast<SalObject*>(lParam) ) + CASE_NOYIELDLOCK_RESULT( SAL_MSG_GETDC, GetDCEx( + reinterpret_cast<HWND>(wParam), nullptr, DCX_CACHE) ) + CASE_NOYIELDLOCK( SAL_MSG_RELEASEDC, ReleaseDC( + reinterpret_cast<HWND>(wParam), reinterpret_cast<HDC>(lParam)) ) + case SAL_MSG_TIMER_CALLBACK: - { - WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); assert( pTimer != nullptr ); nRet = static_cast<LRESULT>( pTimer->ImplHandleTimerEvent( wParam ) ); - nDef = FALSE; break; - } + case WM_TIMER: - { - WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); assert( pTimer != nullptr ); nRet = static_cast<LRESULT>( pTimer->ImplHandle_WM_TIMER( wParam ) ); - nDef = FALSE; break; - } + + case SAL_MSG_DUMMY: + break; + + default: + rDef = TRUE; + break; } return nRet; } +#undef CASE_NOYIELDLOCK +#undef CASE_NOYIELDLOCK_RESULT + LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) { - int bDef = TRUE; + bool bDef = FALSE; LRESULT nRet = 0; __try { diff --git a/vcl/win/window/salobj.cxx b/vcl/win/window/salobj.cxx index 172f61e923d3..75e406c33f61 100644 --- a/vcl/win/window/salobj.cxx +++ b/vcl/win/window/salobj.cxx @@ -145,7 +145,7 @@ LRESULT CALLBACK SalSysMsgProc( int nCode, WPARAM wParam, LPARAM lParam ) return CallNextHookEx( pSalData->mhSalObjMsgHook, nCode, wParam, lParam ); } -bool ImplSalPreDispatchMsg( MSG* pMsg ) +bool ImplSalPreDispatchMsg( const MSG* pMsg ) { // Used for Unicode and none Unicode SalData* pSalData = GetSalData(); @@ -231,10 +231,10 @@ bool ImplSalPreDispatchMsg( MSG* pMsg ) return FALSE; } -void ImplSalPostDispatchMsg( MSG* pMsg, LRESULT /* nDispatchResult */ ) +void ImplSalPostDispatchMsg( const MSG* pMsg ) { // Used for Unicode and none Unicode - SalData* pSalData = GetSalData(); + SalData *pSalData = GetSalData(); if ( (pMsg->message == WM_KEYDOWN) || (pMsg->message == WM_KEYUP) ) { commit 5c394609a32ab14475675895ed99855f2106b95c Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Oct 18 17:00:53 2017 +0200 OSX implement direct timeout processing Basically works in the same way then in the Windows backend. Change-Id: If48e2b55f037563839a5e716830ce75ed78381e4 diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h index 272cfc722d64..01e50af77b99 100644 --- a/vcl/inc/osx/salinst.h +++ b/vcl/inc/osx/salinst.h @@ -77,6 +77,7 @@ public: osl::Condition maWaitingYieldCond; bool mbIsLiveResize; bool mbNoYieldLock; + bool mbTimerProcessed; static std::list<const ApplicationEvent*> aAppEventList; diff --git a/vcl/inc/osx/saltimer.h b/vcl/inc/osx/saltimer.h index c860ad5cbdda..a9934f280636 100644 --- a/vcl/inc/osx/saltimer.h +++ b/vcl/inc/osx/saltimer.h @@ -44,6 +44,7 @@ public: class AquaSalTimer final : public SalTimer, protected VersionedEvent { NSTimer *m_pRunningTimer; + bool m_bDirectTimeout; ///< timeout can be processed directly void queueDispatchTimerEvent( bool bAtStart ); void callTimerCallback(); @@ -56,13 +57,19 @@ public: void Stop() override; void handleStartTimerEvent( NSEvent* pEvent ); - void handleDispatchTimerEvent( NSEvent* pEvent ); + bool handleDispatchTimerEvent( NSEvent* pEvent ); void handleTimerElapsed(); void handleWindowShouldClose(); bool IsTimerElapsed() const; + inline bool IsDirectTimeout() const; }; +inline bool AquaSalTimer::IsDirectTimeout() const +{ + return m_bDirectTimeout; +} + #endif // INCLUDED_VCL_INC_OSX_SALTIMER_H /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index d475f30275b0..922046bcbfe8 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -379,6 +379,7 @@ AquaSalInstance::AquaSalInstance() : mnActivePrintJobs( 0 ) , mbIsLiveResize( false ) , mbNoYieldLock( false ) + , mbTimerProcessed( false ) { mpSalYieldMutex = new SalYieldMutex; mpSalYieldMutex->acquire(); @@ -452,9 +453,12 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent ) break; } case DispatchTimerEvent: - if ( pTimer ) - pTimer->handleDispatchTimerEvent( pEvent ); + { + AquaSalInstance *pInst = GetSalData()->mpInstance; + if ( pTimer && pInst ) + pInst->mbTimerProcessed = pTimer->handleDispatchTimerEvent( pEvent ); break; + } #if !HAVE_FEATURE_MACOSX_SANDBOX case AppleRemoteControlEvent: // Defined in <apple_remote/RemoteMainController.h> { @@ -570,6 +574,8 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents) // handle available events NSEvent* pEvent = nil; NSTimeInterval now = [[NSProcessInfo processInfo] systemUptime]; + mbTimerProcessed = false; + do { SolarMutexReleaser aReleaser; @@ -596,6 +602,13 @@ SAL_WNODEPRECATED_DECLARATIONS_POP } while( true ); + AquaSalTimer *pTimer = static_cast<AquaSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); + if ( !mbTimerProcessed && pTimer && pTimer->IsDirectTimeout() ) + { + pTimer->handleTimerElapsed(); + bHadEvent = true; + } + // if we had no event yet, wait for one if requested if( bWait && ! bHadEvent ) { diff --git a/vcl/osx/saltimer.cxx b/vcl/osx/saltimer.cxx index 34d46f08728a..af18ae7ea740 100644 --- a/vcl/osx/saltimer.cxx +++ b/vcl/osx/saltimer.cxx @@ -74,6 +74,7 @@ SAL_WNODEPRECATED_DECLARATIONS_POP void AquaSalTimer::queueDispatchTimerEvent( bool bAtStart ) { Stop(); + m_bDirectTimeout = true; ImplNSAppPostEvent( AquaSalInstance::DispatchTimerEvent, bAtStart, GetNextEventVersion() ); } @@ -139,13 +140,14 @@ void AquaSalTimer::callTimerCallback() { ImplSVData* pSVData = ImplGetSVData(); SolarMutexGuard aGuard; + m_bDirectTimeout = false; if( pSVData->maSchedCtx.mpSalTimer ) pSVData->maSchedCtx.mpSalTimer->CallCallback(); } void AquaSalTimer::handleTimerElapsed() { - if ( GetSalData()->mpInstance->mbIsLiveResize ) + if ( m_bDirectTimeout || GetSalData()->mpInstance->mbIsLiveResize ) { // Stop the timer, as it is just invalidated after the firing function Stop(); @@ -155,10 +157,12 @@ void AquaSalTimer::handleTimerElapsed() queueDispatchTimerEvent( YES ); } -void AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent ) +bool AquaSalTimer::handleDispatchTimerEvent( NSEvent *pEvent ) { - if ( IsValidEventVersion( [pEvent data1] ) ) + bool bIsValidEvent = IsValidEventVersion( [pEvent data1] ); + if ( bIsValidEvent ) callTimerCallback(); + return bIsValidEvent; } void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent ) @@ -177,8 +181,8 @@ void AquaSalTimer::handleStartTimerEvent( NSEvent* pEvent ) bool AquaSalTimer::IsTimerElapsed() const { - assert( !(ExistsValidEvent() && m_pRunningTimer) ); - if ( ExistsValidEvent() ) + assert( !((ExistsValidEvent() || m_bDirectTimeout) && m_pRunningTimer) ); + if ( ExistsValidEvent() || m_bDirectTimeout ) return true; if ( !m_pRunningTimer ) return false; commit 32d6653c1cd5cd031ad30216ad7a94c90ee70871 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Mon Oct 16 16:59:45 2017 +0200 WIN guarantee direct timeout handling The code did acccount processing of an invaild timeout system message as a valid timeout event. Change-Id: I3c31f8b9cec592631b4089411163dadecffde816 diff --git a/vcl/README.scheduler b/vcl/README.scheduler index 17648ae3b439..80c14b032c54 100644 --- a/vcl/README.scheduler +++ b/vcl/README.scheduler @@ -89,6 +89,35 @@ can be added to the scheduler reasonably. = Implementation details = +== General: event priority for DoYield == + +There are three types of events, with different priority: + +1. LO user events +2. System events +3. LO Scheduler event + +They should be processed according to the following code: + +bool DoYield( bool bWait, bool bAllCurrent ) +{ + bool bWasEvent = ProcessUserEvents( bAllCurrent ); + if ( !bAllCurrent && bWasEvent ) + return true; + bWasEvent = ProcessSystemEvents( bAllCurrent, &bWasSchedulerEvent ) || bWasEvent; + if ( !bWasSchedulerEvent && IsSchedulerEvent() ) + { + ProcessSchedulerEvent() + bWasEvent = true; + } + if ( !bWasEvent && bWait ) + { + WaitForSystemEvents(); + bWasEvent = true; + } + return bWasEvent; +} + == General: main thread deferral == Currently for Mac and Windows, we run main thread deferrals by disabling the diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h index d762b51b6716..b7d1a1e0d0f1 100644 --- a/vcl/inc/win/saltimer.h +++ b/vcl/inc/win/saltimer.h @@ -42,9 +42,9 @@ class WinSalTimer final : public SalTimer, protected VersionedEvent void ImplStart( sal_uIntPtr nMS ); void ImplStop(); - void ImplHandleTimerEvent( WPARAM aWPARAM ); + bool ImplHandleTimerEvent( WPARAM aWPARAM ); void ImplHandleElapsedTimer(); - void ImplHandle_WM_TIMER( WPARAM aWPARAM ); + bool ImplHandle_WM_TIMER( WPARAM aWPARAM ); public: WinSalTimer(); diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index d1fc8adb6272..5fcca5cde5b4 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -459,17 +459,15 @@ void WinSalInstance::AcquireYieldMutex( sal_uInt32 nCount ) mpSalYieldMutex->acquire( nCount ); } -static void ImplSalDispatchMessage( MSG* pMsg ) +static LRESULT ImplSalDispatchMessage( const MSG* pMsg ) { SalData* pSalData = GetSalData(); - if ( pSalData->mpFirstObject ) - { - if ( ImplSalPreDispatchMsg( pMsg ) ) - return; - } + if ( pSalData->mpFirstObject && ImplSalPreDispatchMsg( pMsg ) ) + return 0; LRESULT lResult = DispatchMessageW( pMsg ); if ( pSalData->mpFirstObject ) - ImplSalPostDispatchMsg( pMsg, lResult ); + ImplSalPostDispatchMsg( pMsg ); + return lResult; } bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) @@ -491,10 +489,13 @@ bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) if ( bOneEvent ) { bWasMsg = true; - if ( !bWasTimeoutMsg ) - bWasTimeoutMsg = (SAL_MSG_TIMER_CALLBACK == aMsg.message); TranslateMessage( &aMsg ); - ImplSalDispatchMessage( &aMsg ); + LRESULT nRet = ImplSalDispatchMessage( &aMsg ); + + if ( !bWasTimeoutMsg ) + bWasTimeoutMsg = (SAL_MSG_TIMER_CALLBACK == aMsg.message) + && static_cast<bool>( nRet ); + if ( bHandleAllCurrentEvents && !bHadNewerEvent && aMsg.time > nCurTicks && (nLastTicks <= nCurTicks || aMsg.time < nLastTicks) ) @@ -666,14 +667,16 @@ LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, i { WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); assert( pTimer != nullptr ); - pTimer->ImplHandleTimerEvent( wParam ); + nRet = static_cast<LRESULT>( pTimer->ImplHandleTimerEvent( wParam ) ); + nDef = FALSE; break; } case WM_TIMER: { WinSalTimer *const pTimer = static_cast<WinSalTimer*>( ImplGetSVData()->maSchedCtx.mpSalTimer ); assert( pTimer != nullptr ); - pTimer->ImplHandle_WM_TIMER( wParam ); + nRet = static_cast<LRESULT>( pTimer->ImplHandle_WM_TIMER( wParam ) ); + nDef = FALSE; break; } } diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx index 9d20c70bdb5a..9c67e841956e 100644 --- a/vcl/win/app/saltimer.cxx +++ b/vcl/win/app/saltimer.cxx @@ -158,13 +158,14 @@ void WinSalTimer::ImplHandleElapsedTimer() ImplSalYieldMutexRelease(); } -void WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM ) +bool WinSalTimer::ImplHandleTimerEvent( const WPARAM aWPARAM ) { assert( aWPARAM <= SAL_MAX_INT32 ); if ( !IsValidEventVersion( static_cast<sal_Int32>( aWPARAM ) ) ) - return; + return false; ImplHandleElapsedTimer(); + return true; } void WinSalTimer::SetForceRealTimer( const bool bVal ) @@ -179,11 +180,14 @@ void WinSalTimer::SetForceRealTimer( const bool bVal ) Start( 0 ); } -void WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM ) +bool WinSalTimer::ImplHandle_WM_TIMER( const WPARAM aWPARAM ) { assert( m_aWmTimerId == aWPARAM ); - if ( m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer ) - ImplHandleElapsedTimer(); + if ( !(m_aWmTimerId == aWPARAM && m_bDirectTimeout && m_bForceRealTimer) ) + return false; + + ImplHandleElapsedTimer(); + return true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 80a5f83dc69ceb31822d00112db2c48e268074cd Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Mon Oct 16 19:03:59 2017 +0200 tdf#105062 prevent AutoRecovery DB deadlock AutoRecovery document event notification - at least for Firebird DB files - needs the SolarMutex for getLocation(). If I place the SolarMutex inside the CacheLockGuard I get a the css::uno::RuntimeException from CacheLockGuard::lock. Change-Id: I3341a80ecf144d29e0a68de6695d1ca6a7241c60 diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx index d1b106592d4e..53f02f4e3d5f 100644 --- a/framework/source/services/autorecovery.cxx +++ b/framework/source/services/autorecovery.cxx @@ -2606,6 +2606,7 @@ void AutoRecovery::implts_updateDocumentUsedForSavingState(const css::uno::Refer void AutoRecovery::implts_markDocumentAsSaved(const css::uno::Reference< css::frame::XModel >& xDocument) { + SolarMutexGuard aSolarGuard; CacheLockGuard aCacheLock(this, cppu::WeakComponentImplHelperBase::rBHelper.rMutex, m_nDocCacheLock, LOCK_FOR_CACHE_USE); AutoRecovery::TDocumentInfo aInfo; commit 8da62bd0c521ad65e5344ef462b8951b99148ff3 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Wed Oct 18 14:54:20 2017 +0200 Prefer ACE over Jet ODBC Excel drivers in VB tests The Jet drivers are deprectated and unsupported. From commit 66b3970c946bd25647484ea1ac2c2e62bd9fb7b4 I guess a Windows 10 64bit doesn't provide any, but don't know. Essentially commit 66b3970c946bd25647484ea1ac2c2e62bd9fb7b4, is reverted, as it also removed the ole_dfltObjDflMethod.vb test. Change-Id: I2dfc525c7cdf7ceb7f46521905933f9ce67aa2e6 diff --git a/basic/qa/cppunit/test_vba.cxx b/basic/qa/cppunit/test_vba.cxx index d153a1d62f82..13d897a01894 100644 --- a/basic/qa/cppunit/test_vba.cxx +++ b/basic/qa/cppunit/test_vba.cxx @@ -30,13 +30,17 @@ namespace public: VBATest() : BootstrapFixture(true, false) {} void testMiscVBAFunctions(); +#ifdef _WIN32 void testMiscOLEStuff(); +#endif // Adds code needed to register the test suite CPPUNIT_TEST_SUITE(VBATest); // Declares the method as a test to call CPPUNIT_TEST(testMiscVBAFunctions); +#ifdef _WIN32 CPPUNIT_TEST(testMiscOLEStuff); +#endif // End of test suite definition CPPUNIT_TEST_SUITE_END(); @@ -175,16 +179,11 @@ void VBATest::testMiscVBAFunctions() } } -void VBATest::testMiscOLEStuff() -{ // Not much point even trying to run except on Windows. // (Without Excel doesn't really do anything anyway, -// see "so skip test" below.) - -// Since some time, on a properly updated Windows 10, this works -// only with a 64-bit LibreOffice - -#if defined(_WIN64) +#ifdef _WIN32 +void VBATest::testMiscOLEStuff() +{ // test if we have the necessary runtime environment // to run the OLE tests. uno::Reference< lang::XMultiServiceFactory > xOLEFactory; @@ -203,27 +202,45 @@ void VBATest::testMiscOLEStuff() bOk = xADODB.is(); } if ( !bOk ) - return; // can't do anything, skip test + return; // can't do anything without OLE, so skip test + // search for the ODBC Excel drivers const int nBufSize = 1024 * 4; wchar_t sBuf[nBufSize]; - SQLGetInstalledDriversW( sBuf, nBufSize, nullptr ); + if( !SQLGetInstalledDriversW( sBuf, nBufSize, nullptr ) ) + return; + + const wchar_t *aExcelDriverNameList[] + { + L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)", + L"Microsoft Excel Driver (*.xls)" + }; + const unsigned MAX_DRV = SAL_N_ELEMENTS( aExcelDriverNameList ); + bool bFoundDrivers[ MAX_DRV ] = { false, }; const wchar_t *pODBCDriverName = sBuf; - bool bFound = false; - for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 ) { - if( wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls)" ) == 0 || - wcscmp( pODBCDriverName, L"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)" ) == 0 ) { - bFound = true; + for (; wcslen( pODBCDriverName ) != 0; pODBCDriverName += wcslen( pODBCDriverName ) + 1 ) + { + for ( unsigned i = 0; i < MAX_DRV; ++i ) + if ( !bFoundDrivers[ i ] && wcscmp( pODBCDriverName, aExcelDriverNameList[ i ] ) == 0 ) + bFoundDrivers[ i ] = true; + } + + pODBCDriverName = nullptr; + for ( unsigned i = 0; i < MAX_DRV; ++i ) + if ( bFoundDrivers[ i ] ) + { + pODBCDriverName = aExcelDriverNameList[ i ]; break; } - } - if ( !bFound ) - return; // can't find ODBC driver needed test, so skip test + + if ( !pODBCDriverName ) + return; // can't find any ODBC driver needed for the test, so skip it const char* macroSource[] = { "ole_ObjAssignNoDflt.vb", "ole_ObjAssignToNothing.vb", + "ole_dfltObjDflMethod.vb", }; OUString sMacroPathURL = m_directories.getURLFromSrc("/basic/qa/vba_tests/"); @@ -251,11 +268,8 @@ void VBATest::testMiscOLEStuff() CPPUNIT_ASSERT_MESSAGE("No return variable huh?", pReturn.get() != nullptr ); CPPUNIT_ASSERT_EQUAL_MESSAGE("Result not as expected", OUString("OK"), pReturn->GetOUString() ); } -#else - // Avoid "this method is empty and should be removed" warning - (void) 42; -#endif } +#endif // Put the test suite in the registry CPPUNIT_TEST_SUITE_REGISTRATION(VBATest); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits