summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuergen Funk <juergen.funk_ml@cib.de>2015-06-03 09:23:44 +0200
committerAshod Nakashian <ashod.nakashian@collabora.co.uk>2016-02-06 09:09:53 -0500
commit65feac834aa6a9360f18bdddf94bd67c71e807ba (patch)
tree70169652f79b5c9246afda354db365d963a112eb
parent9c035576f1d7c296ef41c1feb983bffce89a01d7 (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> (cherry picked from commit 1289d3c42af66990a2c8e5a7a38e51b6cd51c7eb)
-rw-r--r--include/vcl/idle.hxx1
-rw-r--r--include/vcl/scheduler.hxx39
-rw-r--r--include/vcl/timer.hxx2
-rw-r--r--sfx2/source/appl/appinit.cxx2
-rw-r--r--vcl/inc/svdata.hxx2
-rw-r--r--vcl/source/app/idle.cxx1
-rw-r--r--vcl/source/app/scheduler.cxx219
-rw-r--r--vcl/source/app/svdata.cxx3
-rw-r--r--vcl/source/app/svmain.cxx3
-rw-r--r--vcl/source/app/timer.cxx11
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 28a709f707cd..4a3514c22f0f 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 5c7e3cb985dc..ee271d9821d1 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -317,7 +317,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 901c44e74cab..18ab52a06588 100644
--- a/vcl/source/app/idle.cxx
+++ b/vcl/source/app/idle.cxx
@@ -75,5 +75,4 @@ sal_uInt64 Idle::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 /* nTime */
return nMinPeriod;
}
-
/* 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 7c1fa981b92d..39c34dc31c96 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 );
maNWFData.mbEnableAccel = 1;
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index ec659988e70d..e3ffade453e0 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -261,6 +261,8 @@ bool InitVCL()
// remember Main-Thread-Id
pSVData->mnMainThreadId = ::osl::Thread::getCurrentIdentifier();
+ Scheduler::ImplInitScheduler();
+
// Initialize Sal
pSVData->mpDefInst = CreateSalInstance();
if ( !pSVData->mpDefInst )
@@ -381,6 +383,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