summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2017-01-25 15:49:44 +0100
committerJan-Marek Glogowski <glogow@fbihome.de>2017-07-13 12:10:22 +0200
commitb22526b8ad88f5061b1901914e280ba9c8db1fe7 (patch)
treed91c6d8845e2e37f5c822037cd66edfc441413ab /vcl
parentd93acb77667ecdb78b53a1be626ca2e000813828 (diff)
Introduce a scheduler stack
While the stack removes all invoked tasks from the queue, which actively removes it from scheduling, it also helps to faster handle nested calls, as we don't have to look for the previous position to move the task to the end of the queue for the round robin. Change-Id: I358cf2492e9630f67685a2b780509edb56691830
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/svdata.hxx1
-rw-r--r--vcl/source/app/scheduler.cxx108
2 files changed, 69 insertions, 40 deletions
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index dcbbc00ea9bc..844f564c425f 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -323,6 +323,7 @@ struct ImplSchedulerContext
{
ImplSchedulerData* mpFirstSchedulerData = nullptr; ///< list of all active tasks
ImplSchedulerData* mpLastSchedulerData = nullptr; ///< last item of the mpFirstSchedulerData list
+ ImplSchedulerData* mpSchedulerStack = nullptr; ///< stack of invoked tasks
SalTimer* mpSalTimer = nullptr; ///< interface to sal event loop / system timer
sal_uInt64 mnTimerStart = 0; ///< start time of the timer
sal_uInt64 mnTimerPeriod = SAL_MAX_UINT64; ///< current timer period
diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx
index 8e166a974ac2..8a332b8bb538 100644
--- a/vcl/source/app/scheduler.cxx
+++ b/vcl/source/app/scheduler.cxx
@@ -190,7 +190,7 @@ bool Scheduler::HasPendingTasks()
tools::Time::GetSystemTicks() );
}
-inline void Scheduler::UpdateMinPeriod( ImplSchedulerData *pSchedulerData,
+inline void Scheduler::UpdateMinPeriod( ImplSchedulerData * const pSchedulerData,
const sal_uInt64 nTime, sal_uInt64 &nMinPeriod )
{
if ( nMinPeriod > ImmediateTimeoutMs )
@@ -203,6 +203,37 @@ inline void Scheduler::UpdateMinPeriod( ImplSchedulerData *pSchedulerData,
}
}
+inline void Scheduler::UpdateSystemTimer( ImplSchedulerContext &rSchedCtx,
+ const sal_uInt64 nMinPeriod,
+ const bool bForce, const sal_uInt64 nTime )
+{
+ if ( InfiniteTimeoutMs == nMinPeriod )
+ {
+ if ( rSchedCtx.mpSalTimer )
+ rSchedCtx.mpSalTimer->Stop();
+ SAL_INFO("vcl.schedule", " Stopping system timer");
+ rSchedCtx.mnTimerPeriod = nMinPeriod;
+ }
+ else
+ Scheduler::ImplStartTimer( nMinPeriod, bForce, nTime );
+}
+
+static inline void AppendSchedulerData( ImplSchedulerContext &rSchedCtx,
+ ImplSchedulerData * const pSchedulerData )
+{
+ if ( !rSchedCtx.mpLastSchedulerData )
+ {
+ rSchedCtx.mpFirstSchedulerData = pSchedulerData;
+ rSchedCtx.mpLastSchedulerData = pSchedulerData;
+ }
+ else
+ {
+ rSchedCtx.mpLastSchedulerData->mpNext = pSchedulerData;
+ rSchedCtx.mpLastSchedulerData = pSchedulerData;
+ }
+ pSchedulerData->mpNext = nullptr;
+}
+
bool Scheduler::ProcessTaskScheduling()
{
ImplSVData *pSVData = ImplGetSVData();
@@ -234,23 +265,28 @@ bool Scheduler::ProcessTaskScheduling()
SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
<< pSchedulerData << " " << *pSchedulerData << " (to be deleted)" );
- if ( pSchedulerData->mbInScheduler )
- goto next_entry;
-
- // Should Task be released from scheduling?
- if ( pSchedulerData->mbDelete || !pSchedulerData->mpTask )
+ // Should the Task be released from scheduling or stacked?
+ if ( pSchedulerData->mbDelete || !pSchedulerData->mpTask || pSchedulerData->mbInScheduler )
{
+ ImplSchedulerData * const pSchedulerDataNext = pSchedulerData->mpNext;
if ( pPrevSchedulerData )
- pPrevSchedulerData->mpNext = pSchedulerData->mpNext;
+ pPrevSchedulerData->mpNext = pSchedulerDataNext;
else
- rSchedCtx.mpFirstSchedulerData = pSchedulerData->mpNext;
- if ( !pSchedulerData->mpNext )
+ rSchedCtx.mpFirstSchedulerData = pSchedulerDataNext;
+ if ( !pSchedulerDataNext )
rSchedCtx.mpLastSchedulerData = pPrevSchedulerData;
- if ( pSchedulerData->mpTask )
- pSchedulerData->mpTask->mpSchedulerData = nullptr;
- ImplSchedulerData *pDeleteItem = pSchedulerData;
- pSchedulerData = pSchedulerData->mpNext;
- delete pDeleteItem;
+ if ( pSchedulerData->mbInScheduler )
+ {
+ pSchedulerData->mpNext = rSchedCtx.mpSchedulerStack;
+ rSchedCtx.mpSchedulerStack = pSchedulerData;
+ }
+ else
+ {
+ if ( pSchedulerData->mpTask )
+ pSchedulerData->mpTask->mpSchedulerData = nullptr;
+ delete pSchedulerData;
+ }
+ pSchedulerData = pSchedulerDataNext;
continue;
}
@@ -272,19 +308,9 @@ next_entry:
pSchedulerData = pSchedulerData->mpNext;
}
- // delete clock if no more timers available,
- if ( InfiniteTimeoutMs == nMinPeriod )
- {
- if ( pSVData->maSchedCtx.mpSalTimer )
- pSVData->maSchedCtx.mpSalTimer->Stop();
- SAL_INFO("vcl.schedule", " Stopping system timer");
- pSVData->maSchedCtx.mnTimerPeriod = nMinPeriod;
- }
- else
- {
- Scheduler::ImplStartTimer( nMinPeriod, true, nTime );
+ if ( InfiniteTimeoutMs != nMinPeriod )
SAL_INFO("vcl.schedule", "Calculated minimum timeout as " << nMinPeriod );
- }
+ UpdateSystemTimer( rSchedCtx, nMinPeriod, true, nTime );
if ( pMostUrgent )
{
@@ -298,12 +324,25 @@ next_entry:
// prepare Scheduler object for deletion after handling
pTask->SetDeletionFlags();
- // invoke it
+ // invoke the task
+ // defer pushing the scheduler stack to next run, as most tasks will
+ // not run a nested Scheduler loop and don't need a stack push!
pMostUrgent->mbInScheduler = true;
pTask->Invoke();
pMostUrgent->mbInScheduler = false;
- if ( pMostUrgent->mpTask && !pMostUrgent->mbDelete )
+ // eventually pop the scheduler stack
+ // this just happens for nested calls, which renders all accounting
+ // invalid, so we just enforce a rescheduling!
+ if ( pMostUrgent == pSVData->maSchedCtx.mpSchedulerStack )
+ {
+ pSchedulerData = pSVData->maSchedCtx.mpSchedulerStack;
+ pSVData->maSchedCtx.mpSchedulerStack = pSchedulerData->mpNext;
+ AppendSchedulerData( rSchedCtx, pSchedulerData );
+ UpdateSystemTimer( rSchedCtx, ImmediateTimeoutMs, true,
+ tools::Time::GetSystemTicks() );
+ }
+ else if ( pMostUrgent->mpTask && !pMostUrgent->mbDelete )
pMostUrgent->mnUpdateTime = tools::Time::GetSystemTicks();
}
@@ -341,20 +380,9 @@ void Task::Start()
ImplSchedulerData* pSchedulerData = new ImplSchedulerData;
pSchedulerData->mpTask = this;
pSchedulerData->mbInScheduler = false;
- pSchedulerData->mpNext = nullptr;
mpSchedulerData = pSchedulerData;
- // insert last due to SFX!
- if ( !rSchedCtx.mpLastSchedulerData )
- {
- rSchedCtx.mpFirstSchedulerData = pSchedulerData;
- rSchedCtx.mpLastSchedulerData = pSchedulerData;
- }
- else
- {
- rSchedCtx.mpLastSchedulerData->mpNext = pSchedulerData;
- rSchedCtx.mpLastSchedulerData = pSchedulerData;
- }
+ AppendSchedulerData( rSchedCtx, pSchedulerData );
SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
<< " " << mpSchedulerData << " added " << *this );
}