From 10a451e97992ce42db3cefa3bffb883f310767c9 Mon Sep 17 00:00:00 2001 From: Michael Meeks Date: Wed, 25 Nov 2015 21:33:15 +0000 Subject: [PATCH] vcl: don't treat non-ready timers as idle handlers. Fixes the busy-loop - 100% CPU all the time. Change-Id: I965f62d6a6f2ec1830c0897dd97179a739c70afc Reviewed-on: https://gerrit.libreoffice.org/20186 Reviewed-by: Michael Meeks Tested-by: Michael Meeks --- include/vcl/idle.hxx | 3 ++- include/vcl/scheduler.hxx | 11 +++++++++-- include/vcl/timer.hxx | 3 ++- vcl/source/app/idle.cxx | 10 ++++++++-- vcl/source/app/scheduler.cxx | 21 ++++++++++++++++++--- vcl/source/app/timer.cxx | 9 +++++++-- 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx index d746cf45e775..5460d3302635 100644 --- a/include/vcl/idle.hxx +++ b/include/vcl/idle.hxx @@ -39,7 +39,8 @@ public: void SetIdleHdl( const Link& rLink ) { maIdleHdl = rLink; } const Link& GetIdleHdl() const { return maIdleHdl; } virtual void Invoke() override; - virtual bool ReadyForSchedule( bool bTimer ) const override; + virtual bool ReadyForSchedule( bool bTimerOnly, sal_uInt64 nTimeNow ) const override; + virtual bool IsIdle() const override; virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) const override; Idle& operator=( const Idle& rIdle ); }; diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index b1152a012251..da9af643069f 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -56,8 +56,15 @@ protected: friend struct ImplSchedulerData; virtual void SetDeletionFlags(); - virtual bool ReadyForSchedule( bool bTimer ) const = 0; - virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) const = 0; + /// Is this item ready to be dispatched at @nTimeNow + virtual bool ReadyForSchedule( bool bTimerOnly, sal_uInt64 nTimeNow ) const = 0; + /// Schedule only when other timers and events are processed + virtual bool IsIdle() const = 0; + /** + * Adjust @nMinPeriod downwards if we want to be notified before + * then, @nTimeNow is the current time. + */ + virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTimeNow ) const = 0; public: Scheduler( const sal_Char *pDebugName = nullptr ); diff --git a/include/vcl/timer.hxx b/include/vcl/timer.hxx index 94a025ecd697..149ba9099ac9 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -31,7 +31,8 @@ protected: bool mbAuto; virtual void SetDeletionFlags() override; - virtual bool ReadyForSchedule( bool bTimer ) const override; + virtual bool ReadyForSchedule( bool bTimerOnly, sal_uInt64 nTimeNow ) const override; + virtual bool IsIdle() const override; virtual sal_uInt64 UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) const override; public: diff --git a/vcl/source/app/idle.cxx b/vcl/source/app/idle.cxx index 198ccfc1b96e..123f37a13e4f 100644 --- a/vcl/source/app/idle.cxx +++ b/vcl/source/app/idle.cxx @@ -47,9 +47,15 @@ void Idle::Start() Scheduler::ImplStartTimer(Scheduler::ImmediateTimeoutMs); } -bool Idle::ReadyForSchedule( bool bTimer ) const +bool Idle::ReadyForSchedule( bool bTimerOnly, sal_uInt64 /* nTimeNow */ ) const { - return !bTimer; + // always ready if not only looking for timers. + return !bTimerOnly; +} + +bool Idle::IsIdle() const +{ + return true; } sal_uInt64 Idle::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 /* nTime */ ) const diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index 8e548bc5cb42..265d6f64c332 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -46,10 +46,11 @@ ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimerOnly ) ImplSVData* pSVData = ImplGetSVData(); ImplSchedulerData *pMostUrgent = nullptr; + sal_uInt64 nTimeNow = tools::Time::GetSystemTicks(); for ( ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData; pSchedulerData; pSchedulerData = pSchedulerData->mpNext ) { if ( !pSchedulerData->mpScheduler || pSchedulerData->mbDelete || - !pSchedulerData->mpScheduler->ReadyForSchedule( bTimerOnly ) || + !pSchedulerData->mpScheduler->ReadyForSchedule( bTimerOnly, nTimeNow ) || !pSchedulerData->mpScheduler->IsActive()) continue; if (!pMostUrgent) @@ -207,10 +208,24 @@ sal_uInt64 Scheduler::CalculateMinimumTimeout( bool &bHasActiveIdles ) { if (!pSchedulerData->mbInScheduler) { - if ( pSchedulerData->mpScheduler->ReadyForSchedule( true ) ) - nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( nMinPeriod, nTime ); + // FIXME: move into a helper. + const char *pSchedulerName = pSchedulerData->mpScheduler->mpDebugName; + if (!pSchedulerName) + pSchedulerName = "unknown"; + + if ( !pSchedulerData->mpScheduler->IsIdle() ) + { + sal_uInt64 nOldMinPeriod = nMinPeriod; + nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( + nOldMinPeriod, nTime ); + SAL_INFO("vcl.schedule", "Have active timer " << pSchedulerName << + "update min period from " << nOldMinPeriod << " to " << nMinPeriod); + } else + { + SAL_INFO("vcl.schedule", "Have active idle " << pSchedulerName); bHasActiveIdles = true; + } } pPrevSchedulerData = pSchedulerData; } diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index cb00fabb4efb..1766d7f0efe1 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -31,9 +31,14 @@ void Timer::SetDeletionFlags() } } -bool Timer::ReadyForSchedule( bool /* bTimerOnly */ ) const +bool Timer::ReadyForSchedule( bool /* bTimerOnly */, sal_uInt64 nTimeNow ) const { - return (mpSchedulerData->mnUpdateTime + mnTimeout) <= tools::Time::GetSystemTicks(); + return (mpSchedulerData->mnUpdateTime + mnTimeout) <= nTimeNow; +} + +bool Timer::IsIdle() const +{ + return false; } sal_uInt64 Timer::UpdateMinPeriod( sal_uInt64 nMinPeriod, sal_uInt64 nTime ) const