include/vcl/timer.hxx | 18 ++++++ vcl/inc/svdata.hxx | 1 vcl/source/app/timer.cxx | 122 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 121 insertions(+), 20 deletions(-)
New commits: commit aede500f3d565299c70670694494570b36f36d6c Author: Tobias Madl <tobias.madl....@gmail.com> Date: Wed Oct 29 07:20:41 2014 +0000 Added starvation protection and Prio scheduling Change-Id: I23f09ac5ce56179af3ac9dcd79ec4104b09297ba diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index 7a952db..1fec77d 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -28,14 +28,14 @@ struct ImplTimerData; struct ImplSVData; enum IdlePriority : sal_Int32 { - VCL_IDLE_PRIORITY_HIGHEST = -40, // -> 0ms - VCL_IDLE_PRIORITY_HIGH = -30, // -> 1ms - VCL_IDLE_PRIORITY_REPAINT = -20, // -> 30ms - VCL_IDLE_PRIORITY_RESIZE = -10, // -> 50ms + VCL_IDLE_PRIORITY_HIGHEST = -400, // -> 0ms + VCL_IDLE_PRIORITY_HIGH = -300, // -> 1ms + VCL_IDLE_PRIORITY_REPAINT = -200, // -> 30ms + VCL_IDLE_PRIORITY_RESIZE = -100, // -> 50ms VCL_IDLE_PRIORITY_MEDIUM = 0, // -> 50ms - VCL_IDLE_PRIORITY_LOW = 10, // -> 100ms - VCL_IDLE_PRIORITY_LOWER = 20, // -> 200ms - VCL_IDLE_PRIORITY_LOWEST = 30 // -> 400ms + VCL_IDLE_PRIORITY_LOW = 100, // -> 100ms + VCL_IDLE_PRIORITY_LOWER = 200, // -> 200ms + VCL_IDLE_PRIORITY_LOWEST = 300 // -> 400ms }; /// Base-class for timers - usually a simple, one-shot timeout diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index c1d9eed..dc74595 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -308,6 +308,7 @@ struct ImplSVData sal_uLong mnThreadCount; // is VCL MultiThread enabled ImplConfigData* mpFirstConfigData; // Zeiger auf ersten Config-Block ImplTimerData* mpFirstTimerData; // list of all running timers + ImplTimerData* mpWaitingTimerData; // sorted (prio) list of ready timers SalTimer* mpSalTimer; // interface to sal event loop/timers SalI18NImeStatus* mpImeStatus; // interface to ime status window SalSystem* mpSalSystem; // SalSystem interface diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index 8c635a2..c039de1 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -93,6 +93,7 @@ void Timer::ImplTimerCallbackProc() ImplTimerData* pTimerData; ImplTimerData* pPrioFirstTimerData; ImplTimerData* pPrevTimerData; + sal_Int32 nPrevPrio; sal_uLong nMinPeriod = MAX_TIMER_PERIOD; sal_uLong nDeltaTime; sal_uLong nTime = tools::Time::GetSystemTicks(); @@ -105,7 +106,11 @@ void Timer::ImplTimerCallbackProc() // find timer where the timer handler needs to be called pTimerData = pSVData->mpFirstTimerData; - pPrioFirstTimerData = pTimerData; + if(!pSVData->mpWaitingTimerData) + pPrioFirstTimerData = pTimerData; + else + pPrioFirstTimerData = pSVData->mpWaitingTimerData; + while ( pTimerData ) { // If the timer is not new, was not deleted, and if it is not in the timeout handler, then @@ -143,15 +148,24 @@ void Timer::ImplTimerCallbackProc() pCurrentTimer = pPrioFirstTimerData; } } + pTimerData->mpTimer->SetPriority(pTimerData->mpTimer->GetPriority() - 1); pPrioFirstTimerData = pCurrentTimer; } } pTimerData = pTimerData->mpNext; } - while(pPrioFirstTimerData && pPrioFirstTimerData->mpTimer){ + if(pPrioFirstTimerData && pPrioFirstTimerData->mpTimer){ + nPrevPrio = pPrioFirstTimerData->mpTimer->GetPriority(); + pSVData->mpWaitingTimerData = pPrioFirstTimerData; + } + else + pSVData->mpWaitingTimerData = NULL; + + while(pPrioFirstTimerData && pPrioFirstTimerData->mpTimer && pPrioFirstTimerData->mpTimer->GetPriority() == nPrevPrio){ // set new update time pPrioFirstTimerData->mnUpdateTime = nTime; + nPrevPrio = pPrioFirstTimerData->mpTimer->GetPriority(); // if no AutoTimer than stop if ( !pPrioFirstTimerData->mpTimer->mbAuto ) @@ -167,13 +181,17 @@ void Timer::ImplTimerCallbackProc() pPrioFirstTimerData->mbInTimeout = false; pPrevTimerData = pPrioFirstTimerData; pPrioFirstTimerData = pPrioFirstTimerData->mpPrioNext; + pPrevTimerData->mpNext = pPrevTimerData->mpPrioNext; pPrevTimerData->mpPrioNext = NULL; } + if(pPrevTimerData && !pPrevTimerData->mpPrioNext) + pPrevTimerData->mpNext = NULL; + // determine new time sal_uLong nNewTime = tools::Time::GetSystemTicks(); pPrevTimerData = NULL; - pTimerData = pSVData->mpFirstTimerData; + pTimerData = pSVData->mpWaitingTimerData; while ( pTimerData ) { // ignore if timer is still in timeout handler @@ -222,8 +240,13 @@ void Timer::ImplTimerCallbackProc() } } + if(pPrioFirstTimerData && pPrioFirstTimerData->mpTimer) + pSVData->mpWaitingTimerData = pPrioFirstTimerData; + else + pSVData->mpWaitingTimerData = NULL; + // delete clock if no more timers available - if ( !pSVData->mpFirstTimerData ) + if ( !pSVData->mpFirstTimerData && !pSVData->mpWaitingTimerData ) { pSVData->mpSalTimer->Stop(); pSVData->mnTimerPeriod = MAX_TIMER_PERIOD; @@ -231,8 +254,10 @@ void Timer::ImplTimerCallbackProc() else ImplStartTimer( pSVData, nMinPeriod ); - pSVData->mnTimerUpdate--; - pSVData->mbNotAllTimerCalled = false; + if(!pSVData->mpWaitingTimerData){ + pSVData->mnTimerUpdate--; + pSVData->mbNotAllTimerCalled = false; + } } Timer::Timer(): commit 529cc06e31c108545c827e302ceeeed1c84f8a8d Author: Tobias Madl <tobias.madl....@gmail.com> Date: Fri Oct 24 12:23:30 2014 +0000 Priority list ready, priorites calculated Change-Id: I85393e6986aef793f76caaa8c9d5bdb0c924842b diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index 836d729..7a952db 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -27,15 +27,15 @@ struct ImplTimerData; struct ImplSVData; -enum IdlePriority { - VCL_IDLE_PRIORITY_HIGHEST, // -> 0ms - VCL_IDLE_PRIORITY_HIGH, // -> 1ms - VCL_IDLE_PRIORITY_REPAINT, // -> 30ms - VCL_IDLE_PRIORITY_RESIZE, // -> 50ms - VCL_IDLE_PRIORITY_MEDIUM, // -> 50ms - VCL_IDLE_PRIORITY_LOW, // -> 100ms - VCL_IDLE_PRIORITY_LOWER, // -> 200ms - VCL_IDLE_PRIORITY_LOWEST // -> 400ms +enum IdlePriority : sal_Int32 { + VCL_IDLE_PRIORITY_HIGHEST = -40, // -> 0ms + VCL_IDLE_PRIORITY_HIGH = -30, // -> 1ms + VCL_IDLE_PRIORITY_REPAINT = -20, // -> 30ms + VCL_IDLE_PRIORITY_RESIZE = -10, // -> 50ms + VCL_IDLE_PRIORITY_MEDIUM = 0, // -> 50ms + VCL_IDLE_PRIORITY_LOW = 10, // -> 100ms + VCL_IDLE_PRIORITY_LOWER = 20, // -> 200ms + VCL_IDLE_PRIORITY_LOWEST = 30 // -> 400ms }; /// Base-class for timers - usually a simple, one-shot timeout @@ -61,7 +61,7 @@ public: void Stop(); /// set the timeout in milliseconds and the priority - void SetTimeout( sal_uLong nTimeoutMs, sal_Int32 nPriority = VCL_IDLE_PRIORITY_MEDIUM ); + void SetTimeout( sal_uLong nTimeoutMs ); void SetPriority( const sal_Int32 nPriority ) { mnPriority = nPriority; } sal_Int32 GetPriority() const { return mnPriority; } sal_Int32 GetDefaultPriority() const { return mnDefaultPriority; } @@ -76,18 +76,6 @@ public: static void ImplDeInitTimer(); static void ImplTimerCallbackProc(); - sal_Int32 getIntFromEnum (IdlePriority e){ - switch (e) { - case VCL_IDLE_PRIORITY_HIGHEST: return -40; - case VCL_IDLE_PRIORITY_HIGH: return -30; - case VCL_IDLE_PRIORITY_REPAINT: return -20; - case VCL_IDLE_PRIORITY_RESIZE: return -10; - case VCL_IDLE_PRIORITY_MEDIUM: return 0; - case VCL_IDLE_PRIORITY_LOW: return 10; - case VCL_IDLE_PRIORITY_LOWER: return 20; - case VCL_IDLE_PRIORITY_LOWEST: return 30; - } - } }; /// An auto-timer is a multi-shot timer re-emitting itself at diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index bfe7cbc..8c635a2 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -118,13 +118,14 @@ void Timer::ImplTimerCallbackProc() { ImplTimerData* pCurrentTimer = pPrioFirstTimerData; pPrevTimerData = NULL; - if(pCurrentTimer != pTimerData){ + //while the priority (number) of the new timer is greater than the priority + //of the current timer go to forward while(pCurrentTimer && pCurrentTimer->mpTimer && pCurrentTimer->mpTimer->GetPriority() <= pTimerData->mpTimer->GetPriority()){ pPrevTimerData = pCurrentTimer; pCurrentTimer = pCurrentTimer->mpPrioNext; } - + //if there is no previous timer: the new timer is the first timer in the list if(!pPrevTimerData){ if(pCurrentTimer && pCurrentTimer->mpTimer) pTimerData->mpPrioNext = pCurrentTimer; @@ -132,6 +133,7 @@ void Timer::ImplTimerCallbackProc() pTimerData->mpPrioNext = NULL; pCurrentTimer = pTimerData; } + //else the new timer is inserted in the middle or in the end of the list else{ pPrevTimerData->mpPrioNext = pTimerData; if(pCurrentTimer && pCurrentTimer->mpTimer) @@ -140,7 +142,6 @@ void Timer::ImplTimerCallbackProc() pTimerData->mpPrioNext = NULL; pCurrentTimer = pPrioFirstTimerData; } - } pPrioFirstTimerData = pCurrentTimer; } @@ -158,7 +159,6 @@ void Timer::ImplTimerCallbackProc() pPrioFirstTimerData->mpTimer->mbActive = false; pPrioFirstTimerData->mbDelete = true; } - // call Timeout pPrioFirstTimerData->mbInTimeout = true; pPrioFirstTimerData->mpTimer->Timeout(); @@ -270,11 +270,27 @@ void Timer::Timeout() maTimeoutHdl.Call( this ); } -void Timer::SetTimeout( sal_uLong nNewTimeout, sal_Int32 nNewPriority ) +void Timer::SetTimeout( sal_uLong nNewTimeout) { mnTimeout = nNewTimeout; - mnPriority = nNewPriority; - mnDefaultPriority = nNewPriority; + + if(nNewTimeout==0) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_HIGHEST; + if(nNewTimeout==1) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_HIGH; + if(nNewTimeout > 1 && nNewTimeout<=30) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_REPAINT; + if(nNewTimeout > 30 && nNewTimeout<=50) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_RESIZE; + if(nNewTimeout > 50 && nNewTimeout<=100) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_MEDIUM; + if(nNewTimeout > 100 && nNewTimeout<=200) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_LOW; + if(nNewTimeout > 200 && nNewTimeout<=400) + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_LOWER; + else + mnPriority = IdlePriority::VCL_IDLE_PRIORITY_LOWEST; + mnDefaultPriority = mnPriority; // if timer is active then renew clock if ( mbActive ) commit 4d4d8216f09c9f2c11f1e0694fc4c7855c0d0fa7 Author: Tobias Madl <tobias.madl....@gmail.com> Date: Thu Oct 23 13:39:05 2014 +0000 Interface timer.cxx/.hxx for priorities Change-Id: Ia2b0b9a9bc07a627027be17e7c21015699a8e9c5 diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index d3ebe1a..836d729 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -27,11 +27,24 @@ struct ImplTimerData; struct ImplSVData; +enum IdlePriority { + VCL_IDLE_PRIORITY_HIGHEST, // -> 0ms + VCL_IDLE_PRIORITY_HIGH, // -> 1ms + VCL_IDLE_PRIORITY_REPAINT, // -> 30ms + VCL_IDLE_PRIORITY_RESIZE, // -> 50ms + VCL_IDLE_PRIORITY_MEDIUM, // -> 50ms + VCL_IDLE_PRIORITY_LOW, // -> 100ms + VCL_IDLE_PRIORITY_LOWER, // -> 200ms + VCL_IDLE_PRIORITY_LOWEST // -> 400ms +}; + /// Base-class for timers - usually a simple, one-shot timeout class VCL_DLLPUBLIC Timer { protected: ImplTimerData* mpTimerData; + sal_Int32 mnDefaultPriority; + sal_Int32 mnPriority; sal_uLong mnTimeout; bool mbActive; bool mbAuto; @@ -47,8 +60,11 @@ public: void Start(); void Stop(); - /// set the timeout in milliseconds - void SetTimeout( sal_uLong nTimeoutMs ); + /// set the timeout in milliseconds and the priority + void SetTimeout( sal_uLong nTimeoutMs, sal_Int32 nPriority = VCL_IDLE_PRIORITY_MEDIUM ); + void SetPriority( const sal_Int32 nPriority ) { mnPriority = nPriority; } + sal_Int32 GetPriority() const { return mnPriority; } + sal_Int32 GetDefaultPriority() const { return mnDefaultPriority; } sal_uLong GetTimeout() const { return mnTimeout; } bool IsActive() const { return mbActive; } @@ -60,6 +76,18 @@ public: static void ImplDeInitTimer(); static void ImplTimerCallbackProc(); + sal_Int32 getIntFromEnum (IdlePriority e){ + switch (e) { + case VCL_IDLE_PRIORITY_HIGHEST: return -40; + case VCL_IDLE_PRIORITY_HIGH: return -30; + case VCL_IDLE_PRIORITY_REPAINT: return -20; + case VCL_IDLE_PRIORITY_RESIZE: return -10; + case VCL_IDLE_PRIORITY_MEDIUM: return 0; + case VCL_IDLE_PRIORITY_LOW: return 10; + case VCL_IDLE_PRIORITY_LOWER: return 20; + case VCL_IDLE_PRIORITY_LOWEST: return 30; + } + } }; /// An auto-timer is a multi-shot timer re-emitting itself at diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index ecbfa74..bfe7cbc 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -30,7 +30,9 @@ struct ImplTimerData { + ImplTimerData() : mpPrioNext(NULL) {} ImplTimerData* mpNext; // Pointer to the next Instance + ImplTimerData* mpPrioNext; // Pointer to the next Instance with lower Priority Timer* mpTimer; // Pointer to VCL Timer instance sal_uLong mnUpdateTime; // Last Update Time sal_uLong mnTimerUpdate; // TimerCallbackProcs on stack @@ -89,6 +91,7 @@ void Timer::ImplTimerCallbackProc() { ImplSVData* pSVData = ImplGetSVData(); ImplTimerData* pTimerData; + ImplTimerData* pPrioFirstTimerData; ImplTimerData* pPrevTimerData; sal_uLong nMinPeriod = MAX_TIMER_PERIOD; sal_uLong nDeltaTime; @@ -102,6 +105,7 @@ void Timer::ImplTimerCallbackProc() // find timer where the timer handler needs to be called pTimerData = pSVData->mpFirstTimerData; + pPrioFirstTimerData = pTimerData; while ( pTimerData ) { // If the timer is not new, was not deleted, and if it is not in the timeout handler, then @@ -112,26 +116,60 @@ void Timer::ImplTimerCallbackProc() // time has expired if ( (pTimerData->mnUpdateTime+pTimerData->mpTimer->mnTimeout) <= nTime ) { - // set new update time - pTimerData->mnUpdateTime = nTime; + ImplTimerData* pCurrentTimer = pPrioFirstTimerData; + pPrevTimerData = NULL; + + if(pCurrentTimer != pTimerData){ + while(pCurrentTimer && pCurrentTimer->mpTimer && pCurrentTimer->mpTimer->GetPriority() <= pTimerData->mpTimer->GetPriority()){ + pPrevTimerData = pCurrentTimer; + pCurrentTimer = pCurrentTimer->mpPrioNext; + } + + if(!pPrevTimerData){ + if(pCurrentTimer && pCurrentTimer->mpTimer) + pTimerData->mpPrioNext = pCurrentTimer; + else + pTimerData->mpPrioNext = NULL; + pCurrentTimer = pTimerData; + } + else{ + pPrevTimerData->mpPrioNext = pTimerData; + if(pCurrentTimer && pCurrentTimer->mpTimer) + pTimerData->mpPrioNext = pCurrentTimer; + else + pTimerData->mpPrioNext = NULL; + pCurrentTimer = pPrioFirstTimerData; + } - // if no AutoTimer than stop - if ( !pTimerData->mpTimer->mbAuto ) - { - pTimerData->mpTimer->mbActive = false; - pTimerData->mbDelete = true; } - - // call Timeout - pTimerData->mbInTimeout = true; - pTimerData->mpTimer->Timeout(); - pTimerData->mbInTimeout = false; + pPrioFirstTimerData = pCurrentTimer; } } - pTimerData = pTimerData->mpNext; } + while(pPrioFirstTimerData && pPrioFirstTimerData->mpTimer){ + // set new update time + pPrioFirstTimerData->mnUpdateTime = nTime; + + // if no AutoTimer than stop + if ( !pPrioFirstTimerData->mpTimer->mbAuto ) + { + pPrioFirstTimerData->mpTimer->mbActive = false; + pPrioFirstTimerData->mbDelete = true; + } + + // call Timeout + pPrioFirstTimerData->mbInTimeout = true; + pPrioFirstTimerData->mpTimer->Timeout(); + if(pPrioFirstTimerData->mpTimer) + pPrioFirstTimerData->mpTimer->SetPriority( pPrioFirstTimerData->mpTimer->GetDefaultPriority() ); + pPrioFirstTimerData->mbInTimeout = false; + pPrevTimerData = pPrioFirstTimerData; + pPrioFirstTimerData = pPrioFirstTimerData->mpPrioNext; + pPrevTimerData->mpPrioNext = NULL; + } + // determine new time sal_uLong nNewTime = tools::Time::GetSystemTicks(); pPrevTimerData = NULL; @@ -200,6 +238,7 @@ void Timer::ImplTimerCallbackProc() Timer::Timer(): mpTimerData(NULL), mnTimeout(1), + mnPriority(0), mbActive(false), mbAuto(false) { @@ -208,6 +247,7 @@ Timer::Timer(): Timer::Timer( const Timer& rTimer ): mpTimerData(NULL), mnTimeout(rTimer.mnTimeout), + mnPriority(rTimer.mnPriority), mbActive(false), mbAuto(false), maTimeoutHdl(rTimer.maTimeoutHdl) @@ -230,9 +270,11 @@ void Timer::Timeout() maTimeoutHdl.Call( this ); } -void Timer::SetTimeout( sal_uLong nNewTimeout ) +void Timer::SetTimeout( sal_uLong nNewTimeout, sal_Int32 nNewPriority ) { mnTimeout = nNewTimeout; + mnPriority = nNewPriority; + mnDefaultPriority = nNewPriority; // if timer is active then renew clock if ( mbActive ) @@ -312,6 +354,7 @@ Timer& Timer::operator=( const Timer& rTimer ) mbActive = false; mnTimeout = rTimer.mnTimeout; + mnPriority = rTimer.mnPriority; maTimeoutHdl = rTimer.maTimeoutHdl; if ( rTimer.IsActive() ) _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits