diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2015-06-10 12:08:00 +0100 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2015-06-10 17:27:20 +0100 |
commit | 48c2815dd20cf20eeec8bb4e003000f4a3d13291 (patch) | |
tree | 19596543beea4e4f56d1d06f429e575f596f0ad7 | |
parent | ef4fd9c52f16e6d242f999dd87170e6cac07230d (diff) |
tdf#91727 - Unwind non-dispatch of idle handlers.
This clobbers the functionality from commit:
06d731428ef6cf93c7333e8228bfb6088853b52f
make idle timers actually activate only when idle
Since now all rendering and re-sizing is done in idle handlers it
does effectively the opposite of what was intended. A better solution
would allow special-casing the processing of just rendering,
re-sizing and window management to spin for eg. progress bar
rendering.
Also add helpful debugging labels to the idle & timeouts.
Also cleanup the Idle vs. Scheduler handling.
Also ensure that starting an Idle triggers a mainloop wakeup.
Also add a unit test.
Change-Id: Ifb0756714378fdb790be599b93c7a3ac1f9209e6
-rw-r--r-- | include/tools/time.hxx | 4 | ||||
-rw-r--r-- | include/vcl/idle.hxx | 8 | ||||
-rw-r--r-- | include/vcl/scheduler.hxx | 16 | ||||
-rw-r--r-- | include/vcl/timer.hxx | 2 | ||||
-rw-r--r-- | svtools/source/graphic/grfcache.cxx | 1 | ||||
-rw-r--r-- | svx/source/svdraw/svdetc.cxx | 1 | ||||
-rw-r--r-- | vcl/qa/cppunit/timer.cxx | 26 | ||||
-rw-r--r-- | vcl/source/app/idle.cxx | 25 | ||||
-rw-r--r-- | vcl/source/app/scheduler.cxx | 15 | ||||
-rw-r--r-- | vcl/source/app/timer.cxx | 2 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 2 |
11 files changed, 80 insertions, 22 deletions
diff --git a/include/tools/time.hxx b/include/tools/time.hxx index 2b950b860ee9..e25b2de73f53 100644 --- a/include/tools/time.hxx +++ b/include/tools/time.hxx @@ -123,7 +123,9 @@ public: { return (nTime <= rTime.nTime); } static Time GetUTCOffset(); - static sal_uInt64 GetSystemTicks(); // Elapsed time + + /// Elapsed time since epoch in milliseconds + static sal_uInt64 GetSystemTicks(); void ConvertToUTC() { *this -= Time::GetUTCOffset(); } void ConvertToLocalTime() { *this += Time::GetUTCOffset(); } diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx index b66a8893d023..258fd48dc85f 100644 --- a/include/vcl/idle.hxx +++ b/include/vcl/idle.hxx @@ -29,14 +29,18 @@ protected: Link<Idle *, void> maIdleHdl; // Callback Link public: - Idle(); + Idle( const sal_Char *pDebugName = NULL ); Idle( const Idle& rIdle ); + virtual void Start(); + /// Make it possible to associate a callback with this idle handler /// of course, you can also sub-class and override 'Invoke' void SetIdleHdl( const Link<Idle *, void>& rLink ) { maIdleHdl = rLink; } const Link<Idle *, void>& GetIdleHdl() const { return maIdleHdl; } - virtual void Invoke() SAL_OVERRIDE; + virtual void Invoke() SAL_OVERRIDE; + virtual bool ReadyForSchedule( bool bTimer ) SAL_OVERRIDE; + virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) SAL_OVERRIDE; Idle& operator=( const Idle& rIdle ); }; diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index dfa1483132b2..6c4e2116b589 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -52,23 +52,27 @@ enum class SchedulerPriority { class VCL_DLLPUBLIC Scheduler { protected: - ImplSchedulerData* mpSchedulerData; // Pointer to element in scheduler list - SchedulerPriority mePriority; // Scheduler priority - bool mbActive; // Currently in the scheduler + ImplSchedulerData* mpSchedulerData; /// Pointer to element in scheduler list + const sal_Char *mpDebugName; /// Useful for debugging + SchedulerPriority mePriority; /// Scheduler priority + bool mbActive; /// Currently in the scheduler friend struct ImplSchedulerData; virtual void SetDeletionFlags(); - virtual bool ReadyForSchedule( bool bTimer ) { return !bTimer; } - virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ); + virtual bool ReadyForSchedule( bool bTimer ) = 0; + virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) = 0; public: - Scheduler(); + Scheduler( const sal_Char *pDebugName = NULL ); Scheduler( const Scheduler& rScheduler ); virtual ~Scheduler(); void SetPriority( SchedulerPriority ePriority ); SchedulerPriority GetPriority() const { return mePriority; } + void SetDebugName( const sal_Char *pDebugName ) { mpDebugName = pDebugName; } + const sal_Char *GetDebugName() { return mpDebugName; } + // Call handler virtual void Invoke() = 0; diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index 458ad4e52bc8..8835291cac7e 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -38,7 +38,7 @@ private: static void InitSystemTimer(); public: - Timer(); + Timer( const sal_Char *pDebugName = NULL ); Timer( const Timer& rTimer ); /// Make it possible to associate a callback with this timer handler diff --git a/svtools/source/graphic/grfcache.cxx b/svtools/source/graphic/grfcache.cxx index 011f79a5b3ce..21aa7d7f10a2 100644 --- a/svtools/source/graphic/grfcache.cxx +++ b/svtools/source/graphic/grfcache.cxx @@ -805,6 +805,7 @@ void GraphicDisplayCacheEntry::Draw( OutputDevice* pOut, const Point& rPt, const } GraphicCache::GraphicCache( sal_uLong nDisplayCacheSize, sal_uLong nMaxObjDisplayCacheSize ) : + maReleaseTimer ( "GraphicCache maReleaseTimer" ), mnReleaseTimeoutSeconds ( 0UL ), mnMaxDisplaySize ( nDisplayCacheSize ), mnMaxObjDisplaySize ( nMaxObjDisplayCacheSize ), diff --git a/svx/source/svdraw/svdetc.cxx b/svx/source/svdraw/svdetc.cxx index 7f04c4a45ca4..abdb896b7232 100644 --- a/svx/source/svdraw/svdetc.cxx +++ b/svx/source/svdraw/svdetc.cxx @@ -102,6 +102,7 @@ OLEObjCache::OLEObjCache() pTimer->SetTimeoutHdl(aLink); pTimer->SetTimeout(20000); pTimer->Start(); + pTimer->SetDebugName("OLEObjCache pTimer UnloadCheck"); aLink.Call(pTimer); } diff --git a/vcl/qa/cppunit/timer.cxx b/vcl/qa/cppunit/timer.cxx index 976853c88e7b..12110b7fc3bf 100644 --- a/vcl/qa/cppunit/timer.cxx +++ b/vcl/qa/cppunit/timer.cxx @@ -18,6 +18,10 @@ #include <vcl/timer.hxx> #include <vcl/idle.hxx> #include <vcl/svapp.hxx> +#include "svdata.hxx" +#include "salinst.hxx" + +// #define TEST_WATCHDOG /// Avoid our timer tests just wedging the build if they fail. class WatchDog : public osl::Thread @@ -47,6 +51,7 @@ class TimerTest : public test::BootstrapFixture public: TimerTest() : BootstrapFixture(true, false) {} + void testIdleMainloop(); void testIdle(); #ifdef TEST_WATCHDOG void testWatchdog(); @@ -58,6 +63,7 @@ public: CPPUNIT_TEST_SUITE(TimerTest); CPPUNIT_TEST(testIdle); + CPPUNIT_TEST(testIdleMainloop); #ifdef TEST_WATCHDOG CPPUNIT_TEST(testWatchdog); #endif @@ -105,7 +111,25 @@ void TimerTest::testIdle() bool bTriggered = false; IdleBool aTest( bTriggered ); Scheduler::ProcessTaskScheduling(false); - CPPUNIT_ASSERT_MESSAGE("watchdog triggered", bTriggered); + CPPUNIT_ASSERT_MESSAGE("idle triggered", bTriggered); +} + +// tdf#91727 +void TimerTest::testIdleMainloop() +{ + bool bTriggered = false; + IdleBool aTest( bTriggered ); + while (!bTriggered) + { + ImplSVData* pSVData = ImplGetSVData(); + + // can't test this via Application::Yield since this + // also processes all tasks directly via the scheduler. + pSVData->maAppData.mnDispatchLevel++; + pSVData->mpDefInst->Yield( true, false ); + pSVData->maAppData.mnDispatchLevel--; + } + CPPUNIT_ASSERT_MESSAGE("mainloop idle triggered", bTriggered); } // -------------------------------------------------------------------- diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx index 7fe239d199f7..0dd8593bff84 100644 --- a/vcl/source/app/idle.cxx +++ b/vcl/source/app/idle.cxx @@ -18,6 +18,8 @@ */ #include <vcl/idle.hxx> +#include <vcl/timer.hxx> +#include "svdata.hxx" void Idle::Invoke() { @@ -31,7 +33,7 @@ Idle& Idle::operator=( const Idle& rIdle ) return *this; } -Idle::Idle() : Scheduler() +Idle::Idle( const sal_Char *pDebugName ) : Scheduler( pDebugName ) { } @@ -40,4 +42,25 @@ Idle::Idle( const Idle& rIdle ) : Scheduler(rIdle) maIdleHdl = rIdle.maIdleHdl; } +void Idle::Start() +{ + Scheduler::Start(); + ImplSVData* pSVData = ImplGetSVData(); + Timer::ImplStartTimer( pSVData, 0 ); +} + +bool Idle::ReadyForSchedule( bool bTimer ) +{ + // tdf#91727 - We need to re-work this to allow only UI idle handlers + // and not timeouts to be processed in some limited scenarios + (void)bTimer; + return true; // !bTimer +} + +sal_uInt64 Idle::UpdateMinPeriod( sal_uInt64 /* nMinPeriod */, sal_uInt64 /* nTime */ ) +{ + return 1; +} + + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index 20b11dc4c922..c3cea781e6b8 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -120,6 +120,7 @@ void Scheduler::ProcessTaskScheduling( bool bTimer ) sal_uInt64 nMinPeriod = MAX_TIMER_PERIOD; pSVData->mnUpdateStack++; + // tdf#91727 - NB. bTimer is ultimately not used if ((pSchedulerData = ImplSchedulerData::GetMostImportantTask(bTimer))) { pSchedulerData->mnUpdateTime = nTime; @@ -164,18 +165,12 @@ void Scheduler::ProcessTaskScheduling( bool bTimer ) pSVData->mnTimerPeriod = MAX_TIMER_PERIOD; } else + { Timer::ImplStartTimer( pSVData, nMinPeriod ); + } pSVData->mnUpdateStack--; } -sal_uInt64 Scheduler::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) -{ - // this period is only useful for timer - // so in this implementation it' only a pass through - (void)nTime; - return nMinPeriod; -} - void Scheduler::SetPriority( SchedulerPriority ePriority ) { mePriority = ePriority; @@ -235,8 +230,9 @@ Scheduler& Scheduler::operator=( const Scheduler& rScheduler ) return *this; } -Scheduler::Scheduler(): +Scheduler::Scheduler(const sal_Char *pDebugName): mpSchedulerData(NULL), + mpDebugName(pDebugName), mePriority(SchedulerPriority::HIGH), mbActive(false) { @@ -244,6 +240,7 @@ Scheduler::Scheduler(): Scheduler::Scheduler( const Scheduler& rScheduler ): mpSchedulerData(NULL), + mpDebugName(rScheduler.mpDebugName), mePriority(rScheduler.mePriority), mbActive(false) { diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index a49f4f5ed320..7d92283b6466 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -98,7 +98,7 @@ void Timer::InitSystemTimer() } } -Timer::Timer() : Scheduler() +Timer::Timer(const sal_Char *pDebugName) : Scheduler(pDebugName) { mnTimeout = 1; mbAuto = false; diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 497fc42de8bf..9754f33e1f5a 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -1058,9 +1058,11 @@ void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* p { mpWindowImpl->mpFrameData->maPaintIdle.SetPriority( SchedulerPriority::REPAINT ); mpWindowImpl->mpFrameData->maPaintIdle.SetIdleHdl( LINK( this, Window, ImplHandlePaintHdl ) ); + mpWindowImpl->mpFrameData->maPaintIdle.SetDebugName( "vcl::Window maPaintIdle" ); } mpWindowImpl->mpFrameData->maResizeIdle.SetPriority( SchedulerPriority::RESIZE ); mpWindowImpl->mpFrameData->maResizeIdle.SetIdleHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) ); + mpWindowImpl->mpFrameData->maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" ); mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = false; if ( pRealParent && IsTopWindow() ) |