[Libreoffice-commits] core.git: Branch 'feature/priorities' - 3 commits - include/vcl vcl/inc vcl/source
Tobias Madl
tobias.madl.dev at gmail.com
Wed Oct 29 00:22:23 PDT 2014
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.dev at 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.dev at 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.dev at 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() )
More information about the Libreoffice-commits
mailing list