diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-01-25 15:49:44 +0100 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-07-13 12:10:22 +0200 |
commit | b22526b8ad88f5061b1901914e280ba9c8db1fe7 (patch) | |
tree | d91c6d8845e2e37f5c822037cd66edfc441413ab /vcl | |
parent | d93acb77667ecdb78b53a1be626ca2e000813828 (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.hxx | 1 | ||||
-rw-r--r-- | vcl/source/app/scheduler.cxx | 108 |
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 ); } |