diff options
author | Juergen Funk <juergen.funk_ml@cib.de> | 2015-06-03 09:23:44 +0200 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2015-06-12 15:19:20 +0000 |
commit | 1289d3c42af66990a2c8e5a7a38e51b6cd51c7eb (patch) | |
tree | 5891add77480cc9b19edb4ccabe7061446a5c9cc | |
parent | beb8e2830dc9e1c771e196fcaf08cdfd6bf3dde3 (diff) |
std::list for Scheduler
Re-factor the scheduler to use std::list
Because
- ImplSchedulerData
- remove: mbInScheduler, mnUpdateTime, mnUpdateStack
that is scheduler stuff
- this struct is only a container for the scheduler-list
- UpdateMinPeriod
- the scheduler is the pure-virtual-class then
the idle-class must override this method
- ImplDeInitScheduler(bool All=true)
- this patch 2e29a518b04250b5f9cc9d0d77da3df076834d60 remove
all scheduler tasks and the scheduler, but after that,
the scheduler is using, then crash.
With this fix, only delete the scheduler-list, but not the
scheduler
The next steps
- split the scheduler from the scheduler-list-handling
the scheduler-list-handling need a static class
- remove the scheduler from the timer-handling staff
Change-Id: I8d4d4f27b2bc9684a48c2afafd0b3edd0716c71d
Reviewed-on: https://gerrit.libreoffice.org/16148
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
-rw-r--r-- | include/vcl/idle.hxx | 1 | ||||
-rw-r--r-- | include/vcl/scheduler.hxx | 39 | ||||
-rw-r--r-- | include/vcl/timer.hxx | 2 | ||||
-rw-r--r-- | sfx2/source/appl/appinit.cxx | 2 | ||||
-rw-r--r-- | vcl/inc/svdata.hxx | 2 | ||||
-rw-r--r-- | vcl/source/app/idle.cxx | 1 | ||||
-rw-r--r-- | vcl/source/app/scheduler.cxx | 219 | ||||
-rw-r--r-- | vcl/source/app/svdata.cxx | 3 | ||||
-rw-r--r-- | vcl/source/app/svmain.cxx | 3 | ||||
-rw-r--r-- | vcl/source/app/timer.cxx | 11 |
10 files changed, 155 insertions, 128 deletions
diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx index 2e853b788da6..3d235a5d7464 100644 --- a/include/vcl/idle.hxx +++ b/include/vcl/idle.hxx @@ -28,6 +28,7 @@ class VCL_DLLPUBLIC Idle : public Scheduler protected: Link<Idle *, void> maIdleHdl; // Callback Link + public: Idle( const sal_Char *pDebugName = NULL ); Idle( const Idle& rIdle ); diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index 6c4e2116b589..6b27e05530e8 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -21,23 +21,18 @@ #define INCLUDED_VCL_SCHEDULER_HXX #include <vcl/dllapi.h> +#include <list> + -struct ImplSVData; class Scheduler; struct ImplSchedulerData { - ImplSchedulerData* mpNext; // Pointer to the next element in list - Scheduler* mpScheduler; // Pointer to VCL Scheduler instance - bool mbDelete; // Destroy this scheduler? - bool mbInScheduler; // Scheduler currently processed? - sal_uInt64 mnUpdateTime; // Last Update Time - sal_uInt32 mnUpdateStack; // Update Stack - - void Invoke(); - - static ImplSchedulerData *GetMostImportantTask( bool bTimer ); + bool mbDelete; // Destroy this scheduler? + Scheduler* mpScheduler; // Pointer to VCL Scheduler instance }; +#define MAX_TIMER_PERIOD SAL_MAX_UINT64 + enum class SchedulerPriority { HIGHEST = 0, HIGH = 1, @@ -56,6 +51,7 @@ protected: const sal_Char *mpDebugName; /// Useful for debugging SchedulerPriority mePriority; /// Scheduler priority bool mbActive; /// Currently in the scheduler + sal_uInt64 mnUpdateTime; /// Last Update Time friend struct ImplSchedulerData; virtual void SetDeletionFlags(); @@ -82,15 +78,28 @@ public: bool IsActive() const { return mbActive; } void SetInActive() { mbActive = false; } - Scheduler& operator=( const Scheduler& rScheduler ); - static void ImplDeInitScheduler(); + Scheduler& operator=( const Scheduler& rScheduler ); + static void ImplDeInitScheduler(bool bAll=true); + static void ImplInitScheduler(); - // Process one pending Timer with highhest priority + // Process one pending Timer with highest priority static void CallbackTaskScheduling( bool ignore ); - /// Process one pending task ahead of time with highhest priority. + /// Process one pending task ahead of time with highest priority. static void ProcessTaskScheduling( bool bTimer ); + +private: + bool mbInScheduler; // Scheduler currently processed? + sal_uInt32 mnUpdateStack; // Update Stack + + bool ImplHandleTaskScheduling(sal_uInt64& nMinPeriod, sal_uInt64 nTime); + void ImplInvoke(sal_uInt64 nTime); + static Scheduler* ImplGetHighestPrioTask( bool bTimer ); + bool ImplIsScheduleReady(sal_uInt32 nUpdateStack); + void ImplDispose(); }; +typedef ::std::list< ImplSchedulerData* > ImplScheduler_t; + #endif // INCLUDED_VCL_SCHEDULER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index 8835291cac7e..f6f3dea4ec5c 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -23,6 +23,8 @@ #include <tools/link.hxx> #include <vcl/scheduler.hxx> +struct ImplSVData; + class VCL_DLLPUBLIC Timer : public Scheduler { protected: diff --git a/sfx2/source/appl/appinit.cxx b/sfx2/source/appl/appinit.cxx index d6315d286d45..1d577c784807 100644 --- a/sfx2/source/appl/appinit.cxx +++ b/sfx2/source/appl/appinit.cxx @@ -109,7 +109,7 @@ void SAL_CALL SfxTerminateListener_Impl::notifyTermination( const EventObject& a // Timers may access the SfxApplication and are only deleted in // Application::Quit(), which is asynchronous (PostUserEvent) - disable! - Scheduler::ImplDeInitScheduler(); + Scheduler::ImplDeInitScheduler(false); // false only delete the list SfxApplication* pApp = SfxGetpApp(); pApp->Broadcast( SfxSimpleHint( SFX_HINT_DEINITIALIZING ) ); diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index 595812abdb66..1261b28a436f 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -313,7 +313,7 @@ struct ImplSVData bool mbDeInit; // Is VCL deinitializing sal_uLong mnThreadCount; // is VCL MultiThread enabled ImplConfigData* mpFirstConfigData; // pointer to the first config block - ImplSchedulerData* mpFirstSchedulerData; // list of all running tasks + ImplScheduler_t* maSchedulers; // list of all running tasks 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/idle.cxx b/vcl/source/app/idle.cxx index 0dd8593bff84..e2fa915bc66d 100644 --- a/vcl/source/app/idle.cxx +++ b/vcl/source/app/idle.cxx @@ -62,5 +62,4 @@ sal_uInt64 Idle::UpdateMinPeriod( sal_uInt64 /* nMinPeriod */, sal_uInt64 /* nTi return 1; } - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index c3cea781e6b8..a4400450c321 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -21,85 +21,88 @@ #include <tools/time.hxx> #include <vcl/scheduler.hxx> #include <vcl/timer.hxx> +#include <algorithm> #include <saltimer.hxx> -#define MAX_TIMER_PERIOD SAL_MAX_UINT64 - -void ImplSchedulerData::Invoke() +void Scheduler::ImplInvoke(sal_uInt64 nTime) { - if (mbDelete || mbInScheduler ) + mnUpdateTime = nTime; + + if (mpSchedulerData->mbDelete || mbInScheduler ) return; // prepare Scheduler Object for deletion after handling - mpScheduler->SetDeletionFlags(); + SetDeletionFlags(); // invoke it mbInScheduler = true; - mpScheduler->Invoke(); + Invoke(); mbInScheduler = false; } -ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimer ) +Scheduler* Scheduler::ImplGetHighestPrioTask( bool bTimer ) { - ImplSVData* pSVData = ImplGetSVData(); - ImplSchedulerData *pMostUrgent = NULL; + ImplSVData* pSVData = ImplGetSVData(); + Scheduler * pMostUrgent = NULL; - for ( ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData; pSchedulerData; pSchedulerData = pSchedulerData->mpNext ) + std::for_each(pSVData->maSchedulers->begin(), pSVData->maSchedulers->end(), + [&pSVData, bTimer, &pMostUrgent] (ImplSchedulerData *rScheduler) { - if ( !pSchedulerData->mpScheduler || pSchedulerData->mbDelete || pSchedulerData->mnUpdateStack >= pSVData->mnUpdateStack - || !pSchedulerData->mpScheduler->ReadyForSchedule( bTimer ) || !pSchedulerData->mpScheduler->IsActive()) - continue; - if (!pMostUrgent) - pMostUrgent = pSchedulerData; - else + if ( rScheduler->mpScheduler && + rScheduler->mpScheduler->ImplIsScheduleReady(pSVData->mnUpdateStack) && + rScheduler->mpScheduler->ReadyForSchedule( bTimer ) && + rScheduler->mpScheduler->IsActive() ) { - // Find the highest priority. - // If the priority of the current task is higher (numerical value is lower) than - // the priority of the most urgent, the current task gets the new most urgent. - if ( pSchedulerData->mpScheduler->GetPriority() < pMostUrgent->mpScheduler->GetPriority() ) - pMostUrgent = pSchedulerData; + if (!pMostUrgent) + pMostUrgent = rScheduler->mpScheduler; + else + { + // Find the highest priority. + // If the priority of the current task is higher (numerical value is lower) than + // the priority of the most urgent, the current task gets the new most urgent. + if ( rScheduler->mpScheduler->GetPriority() < pMostUrgent->GetPriority() ) + pMostUrgent = rScheduler->mpScheduler; + } } - } + }); return pMostUrgent; } void Scheduler::SetDeletionFlags() { - mpSchedulerData->mbDelete = true; - mbActive = false; + Stop(); } -void Scheduler::ImplDeInitScheduler() +void Scheduler::ImplDeInitScheduler(bool bAll /*=true*/) { - ImplSVData* pSVData = ImplGetSVData(); - ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData; + ImplSVData* pSVData = ImplGetSVData(); + if (pSVData->mpSalTimer) { pSVData->mpSalTimer->Stop(); } - if ( pSchedulerData ) + pSVData->maSchedulers->remove_if( [] (ImplSchedulerData *rSchedulerData) { - do + if(rSchedulerData->mpScheduler != NULL) { - ImplSchedulerData* pTempSchedulerData = pSchedulerData; - if ( pSchedulerData->mpScheduler ) - { - pSchedulerData->mpScheduler->mbActive = false; - pSchedulerData->mpScheduler->mpSchedulerData = NULL; - } - pSchedulerData = pSchedulerData->mpNext; - delete pTempSchedulerData; + rSchedulerData->mpScheduler->ImplDispose(); } - while ( pSchedulerData ); + else + delete rSchedulerData; + + return true; + }); - pSVData->mpFirstSchedulerData = NULL; - pSVData->mnTimerPeriod = 0; + if(bAll) + { + delete pSVData->maSchedulers; + pSVData->maSchedulers = NULL; } delete pSVData->mpSalTimer; - pSVData->mpSalTimer = 0; + pSVData->mpSalTimer = NULL; } void Scheduler::CallbackTaskScheduling(bool ignore) @@ -113,52 +116,30 @@ void Scheduler::ProcessTaskScheduling( bool bTimer ) { // process all pending Tasks // if bTimer True, only handle timer - ImplSchedulerData* pSchedulerData = NULL; - ImplSchedulerData* pPrevSchedulerData = NULL; - ImplSVData* pSVData = ImplGetSVData(); - sal_uInt64 nTime = tools::Time::GetSystemTicks(); - sal_uInt64 nMinPeriod = MAX_TIMER_PERIOD; + Scheduler* pScheduler = NULL; + ImplSVData* pSVData = ImplGetSVData(); + sal_uInt64 nTime = tools::Time::GetSystemTicks(); + sal_uInt64 nMinPeriod = MAX_TIMER_PERIOD; + pSVData->mnUpdateStack++; // tdf#91727 - NB. bTimer is ultimately not used - if ((pSchedulerData = ImplSchedulerData::GetMostImportantTask(bTimer))) - { - pSchedulerData->mnUpdateTime = nTime; - pSchedulerData->Invoke(); - } + if ((pScheduler = Scheduler::ImplGetHighestPrioTask(bTimer)) != NULL) + pScheduler->ImplInvoke(nTime); - pSchedulerData = pSVData->mpFirstSchedulerData; - while ( pSchedulerData ) + pSVData->maSchedulers->remove_if( [&nMinPeriod, nTime, pSVData] (ImplSchedulerData *rSchedulerData) { - if( pSchedulerData->mbInScheduler ) - { - pPrevSchedulerData = pSchedulerData; - pSchedulerData = pSchedulerData->mpNext; - } - // Should Task be released from scheduling? - else if ( pSchedulerData->mbDelete ) - { - if ( pPrevSchedulerData ) - pPrevSchedulerData->mpNext = pSchedulerData->mpNext; - else - pSVData->mpFirstSchedulerData = pSchedulerData->mpNext; - if ( pSchedulerData->mpScheduler ) - pSchedulerData->mpScheduler->mpSchedulerData = NULL; - ImplSchedulerData* pTempSchedulerData = pSchedulerData; - pSchedulerData = pSchedulerData->mpNext; - delete pTempSchedulerData; - } + if (rSchedulerData->mpScheduler) + return rSchedulerData->mpScheduler->ImplHandleTaskScheduling(nMinPeriod, nTime); else { - pSchedulerData->mnUpdateStack = 0; - nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( nMinPeriod, nTime ); - pPrevSchedulerData = pSchedulerData; - pSchedulerData = pSchedulerData->mpNext; + delete rSchedulerData; + return true; } - } + }); // delete clock if no more timers available - if ( !pSVData->mpFirstSchedulerData ) + if ( pSVData->maSchedulers->empty() ) { if ( pSVData->mpSalTimer ) pSVData->mpSalTimer->Stop(); @@ -168,6 +149,7 @@ void Scheduler::ProcessTaskScheduling( bool bTimer ) { Timer::ImplStartTimer( pSVData, nMinPeriod ); } + pSVData->mnUpdateStack--; } @@ -178,34 +160,22 @@ void Scheduler::SetPriority( SchedulerPriority ePriority ) void Scheduler::Start() { + ImplSVData* pSVData = ImplGetSVData(); // Mark timer active mbActive = true; - ImplSVData* pSVData = ImplGetSVData(); if ( !mpSchedulerData ) { + mpSchedulerData = new ImplSchedulerData; + mpSchedulerData->mpScheduler = this; // insert Scheduler - mpSchedulerData = new ImplSchedulerData; - mpSchedulerData->mpScheduler = this; - mpSchedulerData->mbInScheduler = false; - - // insert last due to SFX! - ImplSchedulerData* pPrev = NULL; - ImplSchedulerData* pData = pSVData->mpFirstSchedulerData; - while ( pData ) - { - pPrev = pData; - pData = pData->mpNext; - } - mpSchedulerData->mpNext = NULL; - if ( pPrev ) - pPrev->mpNext = mpSchedulerData; - else - pSVData->mpFirstSchedulerData = mpSchedulerData; + mbInScheduler = false; + pSVData->maSchedulers->push_back(mpSchedulerData); } - mpSchedulerData->mbDelete = false; - mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks(); - mpSchedulerData->mnUpdateStack = pSVData->mnUpdateStack; + + mpSchedulerData->mbDelete = false; + mnUpdateTime = tools::Time::GetSystemTicks(); + mnUpdateStack = pSVData->mnUpdateStack; } void Scheduler::Stop() @@ -221,7 +191,7 @@ Scheduler& Scheduler::operator=( const Scheduler& rScheduler ) if ( IsActive() ) Stop(); - mbActive = false; + mbActive = false; mePriority = rScheduler.mePriority; if ( rScheduler.IsActive() ) @@ -233,16 +203,18 @@ Scheduler& Scheduler::operator=( const Scheduler& rScheduler ) Scheduler::Scheduler(const sal_Char *pDebugName): mpSchedulerData(NULL), mpDebugName(pDebugName), - mePriority(SchedulerPriority::HIGH), - mbActive(false) + mePriority(SchedulerPriority::HIGH),
+ mbActive(false),
+ mnUpdateTime(0) { } Scheduler::Scheduler( const Scheduler& rScheduler ): mpSchedulerData(NULL), mpDebugName(rScheduler.mpDebugName), - mePriority(rScheduler.mePriority), - mbActive(false) + mePriority(SchedulerPriority::HIGH),
+ mbActive(false),
+ mnUpdateTime(0) { if ( rScheduler.IsActive() ) Start(); @@ -257,3 +229,44 @@ Scheduler::~Scheduler() } } +bool Scheduler::ImplIsScheduleReady(sal_uInt32 nUpdateStack) +{ + return !mpSchedulerData->mbDelete && (mnUpdateStack <= nUpdateStack); +} + +void Scheduler::ImplDispose() +{ + mpSchedulerData->mpScheduler = NULL; + delete mpSchedulerData; + mpSchedulerData = NULL; +} + +void Scheduler::ImplInitScheduler() +{ + ImplSVData* pSVData = ImplGetSVData(); + + if(pSVData->maSchedulers == NULL) + pSVData->maSchedulers = new ImplScheduler_t; +} + + +bool Scheduler::ImplHandleTaskScheduling(sal_uInt64 &nMinPeriod, sal_uInt64 nTime) +{ + // process all pending Tasks + if( !mbInScheduler ) + { + // Should Task be released from scheduling? + if ( !mpSchedulerData->mbDelete ) + { + mnUpdateStack = 0; + nMinPeriod = UpdateMinPeriod( nMinPeriod, nTime ); + } + else + { + ImplDispose(); + return true; + } + } + + return false; +} diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index 8b1a2a60e380..a7c184a65167 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -81,7 +81,8 @@ SalSystem* ImplGetSalSystem() ImplSVData::ImplSVData() { // init global instance data - memset( this, 0, sizeof( ImplSVData ) ); + memset( this, 0, sizeof( ImplSVData )); + maHelpData.mbAutoHelpId = true; maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT ); } diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index 3f9026ed976e..dda1e291c00a 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -251,6 +251,8 @@ bool InitVCL() // remember Main-Thread-Id pSVData->mnMainThreadId = ::osl::Thread::getCurrentIdentifier(); + Scheduler::ImplInitScheduler(); + // Initialize Sal pSVData->mpDefInst = CreateSalInstance(); if ( !pSVData->mpDefInst ) @@ -371,6 +373,7 @@ void DeInitVCL() if ( pSVData->maAppData.mpIdleMgr ) delete pSVData->maAppData.mpIdleMgr; + Scheduler::ImplDeInitScheduler(); if ( pSVData->maWinData.mpMsgBoxImgList ) diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index 7d92283b6466..b6c2abaacb6f 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -23,7 +23,6 @@ #include <svdata.hxx> #include <salinst.hxx> -#define MAX_TIMER_PERIOD SAL_MAX_UINT64 void Timer::ImplStartTimer( ImplSVData* pSVData, sal_uInt64 nMS ) { @@ -45,23 +44,23 @@ void Timer::SetDeletionFlags() // if no AutoTimer than stop if ( !mbAuto ) { - mpSchedulerData->mbDelete = true; - mbActive = false; + Scheduler::SetDeletionFlags(); } } bool Timer::ReadyForSchedule( bool bTimer ) { (void)bTimer; - return (mpSchedulerData->mnUpdateTime + mnTimeout) <= tools::Time::GetSystemTicks(); + return (mnUpdateTime + mnTimeout) <= tools::Time::GetSystemTicks(); } sal_uInt64 Timer::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) { sal_uInt64 nNewTime = tools::Time::GetSystemTicks(); sal_uInt64 nDeltaTime; + //determine smallest time slot - if( mpSchedulerData->mnUpdateTime == nTime ) + if( mnUpdateTime == nTime ) { nDeltaTime = mnTimeout; if( nDeltaTime < nMinPeriod ) @@ -69,7 +68,7 @@ sal_uInt64 Timer::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) } else { - nDeltaTime = mpSchedulerData->mnUpdateTime + mnTimeout; + nDeltaTime = mnUpdateTime + mnTimeout; if( nDeltaTime < nNewTime ) nMinPeriod = 1; else |