include/vcl/idle.hxx | 22 +++++++++++--------- include/vcl/timer.hxx | 1 vcl/source/app/idle.cxx | 51 +++++++++++++++++++++++++++++++++++++++++++++-- vcl/source/app/timer.cxx | 25 +++++++++++++++++++++++ 4 files changed, 88 insertions(+), 11 deletions(-)
New commits: commit f3e757ea37d176f70605bbadbb1b5018f9fbce9f Author: Tobias Madl <tobias.madl....@gmail.com> Date: Fri Jan 16 13:28:29 2015 +0000 Scheduling optimization and starving protection If a Timeout appears, while the idle scheduling is in progress. The idle scheduler gets interrupted and the timeouts are handled. Now the idle scheduler has a new starving protection. Change-Id: Ic9081c647e3fb0abf3b0dc014e711a3b97e0e37d diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx index 9da8414..da0a5c7 100644 --- a/include/vcl/idle.hxx +++ b/include/vcl/idle.hxx @@ -28,14 +28,16 @@ struct ImplIdleData; struct ImplSVData; enum class IdlePriority { - VCL_IDLE_PRIORITY_HIGHEST = 0, // -> 0ms - VCL_IDLE_PRIORITY_HIGH = 1, // -> 1ms - VCL_IDLE_PRIORITY_REPAINT = 2, // -> 30ms - VCL_IDLE_PRIORITY_RESIZE = 3, // -> 50ms - VCL_IDLE_PRIORITY_MEDIUM = 4, // -> 50ms - VCL_IDLE_PRIORITY_LOW = 5, // -> 100ms - VCL_IDLE_PRIORITY_LOWER = 6, // -> 200ms - VCL_IDLE_PRIORITY_LOWEST = 7 // -> 400ms + VCL_IDLE_PRIORITY_STARVATIONPROTECTION = -1, // Do not use this for normal prioritizing + VCL_IDLE_PRIORITY_HIGHEST = 0, // -> 0ms + VCL_IDLE_PRIORITY_HIGH = 1, // -> 1ms + VCL_IDLE_PRIORITY_DEFAULT = 1, // -> 1ms + VCL_IDLE_PRIORITY_REPAINT = 2, // -> 30ms + VCL_IDLE_PRIORITY_RESIZE = 3, // -> 50ms + VCL_IDLE_PRIORITY_MEDIUM = 3, // -> 50ms + VCL_IDLE_PRIORITY_LOW = 5, // -> 100ms + VCL_IDLE_PRIORITY_LOWER = 6, // -> 200ms + VCL_IDLE_PRIORITY_LOWEST = 7 // -> 400ms }; @@ -46,6 +48,7 @@ class VCL_DLLPUBLIC Idle protected: ImplIdleData* mpIdleData; IdlePriority mePriority; + IdlePriority meDefaultPriority; bool mbActive; Link maIdleHdl; @@ -56,8 +59,9 @@ public: Idle( const Idle& rIdle ); virtual ~Idle(); - void SetPriority( IdlePriority ePriority ) { mePriority = ePriority; } + void SetPriority( IdlePriority ePriority ); IdlePriority GetPriority() const { return mePriority; } + IdlePriority GetDefaultPriority() const { return meDefaultPriority; } /// Make it possible to associate a callback with this idle handler /// of course, you can also sub-class and override 'DoIdle' diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index ea65d6f..3aca8e5 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -62,6 +62,7 @@ public: static void ImplDeInitTimer(); static void ImplTimerCallbackProc(); + static bool TimerReady(); }; /// An auto-timer is a multi-shot timer re-emitting itself at diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx index 15427d6..74f0eaf 100644 --- a/vcl/source/app/idle.cxx +++ b/vcl/source/app/idle.cxx @@ -19,6 +19,7 @@ #include <vcl/svapp.hxx> #include <vcl/idle.hxx> +#include <vcl/timer.hxx> #include <svdata.hxx> #include <salinst.hxx> @@ -35,6 +36,7 @@ struct ImplIdleData if (mbDelete || mbInIdle ) return; + mpIdle->SetPriority(mpIdle->GetDefaultPriority()); mbDelete = true; mpIdle->mbActive = false; @@ -59,12 +61,47 @@ struct ImplIdleData { // Find the highest priority one somehow. if ( p->mpIdle->GetPriority() < pMostUrgent->mpIdle->GetPriority() ) + { + IncreasePriority(pMostUrgent->mpIdle); pMostUrgent = p; + } + else + IncreasePriority(p->mpIdle); } } return pMostUrgent; } + + static void IncreasePriority( Idle *pIdle ) + { + switch(pIdle->GetPriority()) + { + case IdlePriority::VCL_IDLE_PRIORITY_STARVATIONPROTECTION: + break; + case IdlePriority::VCL_IDLE_PRIORITY_HIGHEST: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_STARVATIONPROTECTION); + break; + case IdlePriority::VCL_IDLE_PRIORITY_HIGH: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_HIGHEST); + break; + case IdlePriority::VCL_IDLE_PRIORITY_REPAINT: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_HIGH); + break; + case IdlePriority::VCL_IDLE_PRIORITY_MEDIUM: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_REPAINT); + break; + case IdlePriority::VCL_IDLE_PRIORITY_LOW: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_MEDIUM); + break; + case IdlePriority::VCL_IDLE_PRIORITY_LOWER: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_LOW); + break; + case IdlePriority::VCL_IDLE_PRIORITY_LOWEST: + pIdle->SetPriority(IdlePriority::VCL_IDLE_PRIORITY_LOWER); + break; + } + } }; void Idle::ImplDeInitIdle() @@ -97,7 +134,7 @@ void Idle::ProcessAllIdleHandlers() ImplIdleData* pIdleData = NULL; ImplIdleData* pPrevIdleData = NULL; ImplSVData* pSVData = ImplGetSVData(); - while ((pIdleData = ImplIdleData::GetFirstIdle())) + while (!Timer::TimerReady() && (pIdleData = ImplIdleData::GetFirstIdle())) { pIdleData->Invoke(); } @@ -126,6 +163,13 @@ void Idle::ProcessAllIdleHandlers() } } +void Idle::SetPriority( IdlePriority ePriority ) +{ + mePriority = ePriority; + if( !mbActive && meDefaultPriority == IdlePriority::VCL_IDLE_PRIORITY_DEFAULT ) + meDefaultPriority = mePriority; +} + void Idle::DoIdle() { maIdleHdl.Call( this ); @@ -183,6 +227,7 @@ Idle& Idle::operator=( const Idle& rIdle ) mbActive = false; mePriority = rIdle.mePriority; + meDefaultPriority = rIdle.meDefaultPriority; maIdleHdl = rIdle.maIdleHdl; if ( rIdle.IsActive() ) @@ -193,7 +238,8 @@ Idle& Idle::operator=( const Idle& rIdle ) Idle::Idle(): mpIdleData(NULL), - mePriority(IdlePriority::VCL_IDLE_PRIORITY_HIGH), + mePriority(IdlePriority::VCL_IDLE_PRIORITY_DEFAULT), + meDefaultPriority(IdlePriority::VCL_IDLE_PRIORITY_DEFAULT), mbActive(false) { } @@ -201,6 +247,7 @@ Idle::Idle(): Idle::Idle( const Idle& rIdle ): mpIdleData(NULL), mePriority(rIdle.mePriority), + meDefaultPriority(rIdle.meDefaultPriority), mbActive(false), maIdleHdl(rIdle.maIdleHdl) { diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index 50023cb..4adc8e8 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -210,6 +210,31 @@ void Timer::ImplTimerCallbackProc() pSVData->mbNotAllTimerCalled = false; } +bool Timer::TimerReady() +{ +// find timer where the timer handler needs to be called + ImplSVData* pSVData = ImplGetSVData(); + ImplTimerData* pTimerData = pSVData->mpFirstTimerData; + sal_uLong nTime = tools::Time::GetSystemTicks(); + while ( pTimerData ) + { + // If the timer is not new, was not deleted, and if it is not in the timeout handler, then + // call the handler as soon as the time is up. + if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) && + !pTimerData->mbDelete && !pTimerData->mbInTimeout) + { + // time has expired + if ( pTimerData->GetDeadline() <= nTime ) + { + return true; + } + } + + pTimerData = pTimerData->mpNext; + } + return false; +} + Timer::Timer(): mpTimerData(NULL), mnTimeout(1), _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits