[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