summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2015-06-10 12:08:00 +0100
committerMichael Meeks <michael.meeks@collabora.com>2015-06-10 17:27:20 +0100
commit48c2815dd20cf20eeec8bb4e003000f4a3d13291 (patch)
tree19596543beea4e4f56d1d06f429e575f596f0ad7
parentef4fd9c52f16e6d242f999dd87170e6cac07230d (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.hxx4
-rw-r--r--include/vcl/idle.hxx8
-rw-r--r--include/vcl/scheduler.hxx16
-rw-r--r--include/vcl/timer.hxx2
-rw-r--r--svtools/source/graphic/grfcache.cxx1
-rw-r--r--svx/source/svdraw/svdetc.cxx1
-rw-r--r--vcl/qa/cppunit/timer.cxx26
-rw-r--r--vcl/source/app/idle.cxx25
-rw-r--r--vcl/source/app/scheduler.cxx15
-rw-r--r--vcl/source/app/timer.cxx2
-rw-r--r--vcl/source/window/window.cxx2
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() )