diff options
-rw-r--r-- | include/vcl/idle.hxx | 49 | ||||
-rw-r--r-- | include/vcl/scheduler.hxx | 92 | ||||
-rw-r--r-- | include/vcl/timer.hxx | 43 | ||||
-rw-r--r-- | sfx2/source/appl/appinit.cxx | 6 | ||||
-rw-r--r-- | toolkit/source/awt/vclxtoolkit.cxx | 4 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/svdata.hxx | 3 | ||||
-rw-r--r-- | vcl/source/app/idle.cxx | 205 | ||||
-rw-r--r-- | vcl/source/app/scheduler.cxx | 235 | ||||
-rw-r--r-- | vcl/source/app/svapp.cxx | 14 | ||||
-rw-r--r-- | vcl/source/app/svmain.cxx | 6 | ||||
-rw-r--r-- | vcl/source/app/timer.cxx | 305 |
12 files changed, 399 insertions, 564 deletions
diff --git a/include/vcl/idle.hxx b/include/vcl/idle.hxx index 3a63e6ef286a..9cb734546fb0 100644 --- a/include/vcl/idle.hxx +++ b/include/vcl/idle.hxx @@ -21,62 +21,23 @@ #define INCLUDED_VCL_IDLE_HXX #include <tools/link.hxx> -#include <tools/solar.h> -#include <vcl/dllapi.h> +#include <vcl/scheduler.hxx> -struct ImplIdleData; -struct ImplSVData; - -enum class IdlePriority { - HIGHEST = 0, - HIGH = 1, - REPAINT = 2, - RESIZE = 3, - MEDIUM = 3, - LOW = 4, - LOWER = 5, - LOWEST = 6 -}; - -class VCL_DLLPUBLIC Idle +class VCL_DLLPUBLIC Idle : public Scheduler { protected: - ImplIdleData* mpIdleData; // Pointer to element in idle list - sal_Int32 miPriority; // Idle priority ( maybe divergent to default) - IdlePriority meDefaultPriority; // Default idle priority - bool mbActive; // Currently in the scheduler Link maIdleHdl; // Callback Link - friend struct ImplIdleData; - public: Idle(); Idle( const Idle& rIdle ); - virtual ~Idle(); - - void SetPriority( IdlePriority ePriority ); - void SetSchedulingPriority( sal_Int32 iPriority ); - sal_Int32 GetPriority() const { return miPriority; } - IdlePriority GetDefaultPriority() const { return meDefaultPriority; } /// Make it possible to associate a callback with this idle handler - /// of course, you can also sub-class and override 'DoIdle' + /// of course, you can also sub-class and override 'Invoke' void SetIdleHdl( const Link& rLink ) { maIdleHdl = rLink; } const Link& GetIdleHdl() const { return maIdleHdl; } - - // Call idle handler - virtual void DoIdle(); - - void Start(); - void Stop(); - - bool IsActive() const { return mbActive; } - - Idle& operator=( const Idle& rIdle ); - static void ImplDeInitIdle(); - - /// Process all pending idle tasks ahead of time in priority order. - static void ProcessAllIdleHandlers(); + virtual void Invoke() SAL_OVERRIDE; + Idle& operator=( const Idle& rIdle ); }; #endif // INCLUDED_VCL_IDLE_HXX diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx new file mode 100644 index 000000000000..a18aa71e815a --- /dev/null +++ b/include/vcl/scheduler.hxx @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_VCL_SCHEDULER_HXX +#define INCLUDED_VCL_SCHEDULER_HXX + +#include <vcl/dllapi.h> + +struct ImplSVData; +class Scheduler; +struct ImplSchedulerData +{ + ImplSchedulerData* mpNext; // Pointer to the next element in list + Scheduler* mpScheduler; // Pointer to VCL Idle instance + bool mbDelete; // Destroy this idle? + bool mbInScheduler; // Idle handler currently processed? + sal_uLong mnUpdateTime; // Last Update Time + sal_uLong mnUpdateStack; // Update Stack on stack + + void Invoke(); + + static ImplSchedulerData *GetMostImportantTask( bool bTimer ); +}; + +enum class SchedulerPriority { + HIGHEST = 0, + HIGH = 1, + REPAINT = 2, + RESIZE = 3, + MEDIUM = 3, + LOW = 4, + LOWER = 5, + LOWEST = 6 +}; + +class VCL_DLLPUBLIC Scheduler +{ +protected: + ImplSchedulerData* mpSchedulerData; // Pointer to element in idle list + sal_Int32 miPriority; // Idle priority ( maybe divergent to default) + SchedulerPriority meDefaultPriority; // Default idle priority + bool mbActive; // Currently in the scheduler + + friend struct ImplSchedulerData; + virtual void SetDeletionFlags(); + virtual bool ReadyForSchedule( bool bTimer ) { return !bTimer; } + +public: + Scheduler(); + Scheduler( const Scheduler& rScheduler ); + virtual ~Scheduler(); + + void SetPriority( SchedulerPriority ePriority ); + void SetSchedulingPriority( sal_Int32 iPriority ); + sal_Int32 GetPriority() const { return miPriority; } + SchedulerPriority GetDefaultPriority() const { return meDefaultPriority; } + + // Call idle handler + virtual void Invoke() = 0; + + virtual void Start(); + virtual void Stop(); + + bool IsActive() const { return mbActive; } + + Scheduler& operator=( const Scheduler& Scheduler ); + static void ImplDeInitScheduler(); + + /// Process all pending idle tasks ahead of time in priority order. + static void CallbackTaskScheduling(); + static void ProcessTaskScheduling( bool bTimer ); +}; + +#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 2d0f31076db0..01fd36c82a16 100644 --- a/include/vcl/timer.hxx +++ b/include/vcl/timer.hxx @@ -21,50 +21,32 @@ #define INCLUDED_VCL_TIMER_HXX #include <tools/link.hxx> -#include <tools/solar.h> -#include <vcl/dllapi.h> +#include <vcl/scheduler.hxx> -struct ImplTimerData; -struct ImplSVData; - -/// Base-class for timers - usually a simple, one-shot timeout -class VCL_DLLPUBLIC Timer +class VCL_DLLPUBLIC Timer : public Scheduler { protected: - ImplTimerData* mpTimerData; + Link maTimeoutHdl; // Callback Link sal_uLong mnTimeout; - bool mbActive; bool mbAuto; - Link maTimeoutHdl; - friend struct ImplTimerData; + void SetDeletionFlags() SAL_OVERRIDE; + bool ReadyForSchedule( bool bTimer ) SAL_OVERRIDE; public: - Timer(); - Timer( const Timer& rTimer ); - virtual ~Timer(); - - virtual void Timeout(); + Timer(); + Timer( const Timer& rTimer ); - void Start(); - void Stop(); - - /// set the timeout in milliseconds + /// Make it possible to associate a callback with this timer handler + /// of course, you can also sub-class and override 'Invoke' void SetTimeout( sal_uLong nTimeoutMs ); sal_uLong GetTimeout() const { return mnTimeout; } - bool IsActive() const { return mbActive; } - - /// Make it possible to associate a callback with this timeout void SetTimeoutHdl( const Link& rLink ) { maTimeoutHdl = rLink; } const Link& GetTimeoutHdl() const { return maTimeoutHdl; } - + virtual void Invoke() SAL_OVERRIDE; + virtual void Timeout() { Invoke(); } Timer& operator=( const Timer& rTimer ); - - /// @internal - static void ImplDeInitTimer(); - static void ImplTimerCallbackProc(); - static bool TimerReady(); - static bool CheckExpiredTimer(const bool bDoInvoke); + void Start() SAL_OVERRIDE; }; /// An auto-timer is a multi-shot timer re-emitting itself at @@ -77,6 +59,7 @@ public: AutoTimer& operator=( const AutoTimer& rTimer ); }; + #endif // INCLUDED_VCL_TIMER_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/appl/appinit.cxx b/sfx2/source/appl/appinit.cxx index edc31e094955..270ef7aa28a7 100644 --- a/sfx2/source/appl/appinit.cxx +++ b/sfx2/source/appl/appinit.cxx @@ -46,8 +46,7 @@ #include <cppuhelper/supportsservice.hxx> #include <vcl/edit.hxx> -#include <vcl/timer.hxx> -#include <vcl/idle.hxx> +#include <vcl/scheduler.hxx> #include <sfx2/unoctitm.hxx> #include "app.hrc" @@ -110,8 +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! - Timer::ImplDeInitTimer(); - Idle::ImplDeInitIdle(); + Scheduler::ImplDeInitScheduler(); SfxApplication* pApp = SfxGetpApp(); pApp->Broadcast( SfxSimpleHint( SFX_HINT_DEINITIALIZING ) ); diff --git a/toolkit/source/awt/vclxtoolkit.cxx b/toolkit/source/awt/vclxtoolkit.cxx index b720f96c7aab..006a216fa634 100644 --- a/toolkit/source/awt/vclxtoolkit.cxx +++ b/toolkit/source/awt/vclxtoolkit.cxx @@ -91,7 +91,7 @@ #include <vcl/fixed.hxx> #include <vcl/floatwin.hxx> #include <vcl/group.hxx> -#include <vcl/idle.hxx> +#include <vcl/scheduler.hxx> #include <vcl/imgctrl.hxx> #include <vcl/longcurr.hxx> #include <vcl/lstbox.hxx> @@ -1869,7 +1869,7 @@ void SAL_CALL VCLXToolkit::processEventsToIdle() throw (::com::sun::star::uno::RuntimeException, std::exception) { SolarMutexGuard aSolarGuard; - Idle::ProcessAllIdleHandlers(); + Scheduler::ProcessTaskScheduling(false); } } diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index e468df4e102d..08b08e9c022d 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -329,6 +329,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/app/idle \ vcl/source/app/idlemgr \ vcl/source/app/salvtables \ + vcl/source/app/scheduler \ vcl/source/app/session \ vcl/source/app/settings \ vcl/source/app/IconThemeInfo \ diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index b22717386d31..132c27289b9f 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -311,8 +311,7 @@ struct ImplSVData bool mbDeInit; // Is VCL deinitializing sal_uLong mnThreadCount; // is VCL MultiThread enabled ImplConfigData* mpFirstConfigData; // pointer to the first config block - ImplTimerData* mpFirstTimerData; // list of all running timers - ImplIdleData* mpFirstIdleData; // list of all running idles + ImplSchedulerData* mpFirstSchedulerData; // 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 09ffbc77af92..7fe239d199f7 100644 --- a/vcl/source/app/idle.cxx +++ b/vcl/source/app/idle.cxx @@ -17,220 +17,27 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include <vcl/svapp.hxx> #include <vcl/idle.hxx> -#include <vcl/timer.hxx> -#include <svdata.hxx> -#include <salinst.hxx> - -struct ImplIdleData -{ - ImplIdleData* mpNext; // Pointer to the next element in list - Idle* mpIdle; // Pointer to VCL Idle instance - bool mbDelete; // Destroy this idle? - bool mbInIdle; // Idle handler currently processed? - - void Invoke() - { - if (mbDelete || mbInIdle ) - return; - - mpIdle->SetSchedulingPriority(static_cast<sal_Int32>(mpIdle->GetDefaultPriority())); - mbDelete = true; - mpIdle->mbActive = false; - - // invoke it - mbInIdle = true; - mpIdle->DoIdle(); - mbInIdle = false; - } - - static ImplIdleData *GetFirstIdle() - { - ImplSVData* pSVData = ImplGetSVData(); - ImplIdleData *pMostUrgent = NULL; - - for ( ImplIdleData *p = pSVData->mpFirstIdleData; p; p = p->mpNext ) - { - if ( !p->mpIdle || p->mbDelete ) - continue; - if (!pMostUrgent) - pMostUrgent = p; - else - { - // Find the highest priority. - // If the priority of the current idle is higher (numerical value is lower) than - // the priority of the most urgent, the priority of most urgent is increased and - // the current is the new most urgent. So starving is impossible. - if ( p->mpIdle->GetPriority() < pMostUrgent->mpIdle->GetPriority() ) - { - pMostUrgent->mpIdle->SetSchedulingPriority( pMostUrgent->mpIdle->GetPriority() - 1); - pMostUrgent = p; - } - else - p->mpIdle->SetSchedulingPriority( p->mpIdle->GetPriority() - 1); - } - } - - return pMostUrgent; - } -}; - -void Idle::ImplDeInitIdle() -{ - ImplSVData* pSVData = ImplGetSVData(); - ImplIdleData* pIdleData = pSVData->mpFirstIdleData; - - if ( pIdleData ) - { - do - { - ImplIdleData* pTempIdleData = pIdleData; - if ( pIdleData->mpIdle ) - { - pIdleData->mpIdle->mbActive = false; - pIdleData->mpIdle->mpIdleData = NULL; - } - pIdleData = pIdleData->mpNext; - delete pTempIdleData; - } - while ( pIdleData ); - - pSVData->mpFirstIdleData = NULL; - } -} - -void Idle::ProcessAllIdleHandlers() -{ - // process all pending idle - ImplIdleData* pIdleData = NULL; - ImplIdleData* pPrevIdleData = NULL; - ImplSVData* pSVData = ImplGetSVData(); - // timer can interrupt idle - while (!Timer::TimerReady() && (pIdleData = ImplIdleData::GetFirstIdle())) - { - pIdleData->Invoke(); - } - - pIdleData = pSVData->mpFirstIdleData; - while ( pIdleData ) - { - // Should idle be released from scheduling? - if ( pIdleData->mbDelete ) - { - if ( pPrevIdleData ) - pPrevIdleData->mpNext = pIdleData->mpNext; - else - pSVData->mpFirstIdleData = pIdleData->mpNext; - if ( pIdleData->mpIdle ) - pIdleData->mpIdle->mpIdleData = NULL; - ImplIdleData* pTempIdleData = pIdleData; - pIdleData = pIdleData->mpNext; - delete pTempIdleData; - } - else - { - pPrevIdleData = pIdleData; - pIdleData = pIdleData->mpNext; - } - } -} - -void Idle::SetPriority( IdlePriority ePriority ) -{ - meDefaultPriority = ePriority; -} - -void Idle::SetSchedulingPriority( sal_Int32 iPriority ) -{ - miPriority = iPriority; -} - -void Idle::DoIdle() +void Idle::Invoke() { maIdleHdl.Call( this ); } -void Idle::Start() -{ - // Mark timer active - mbActive = true; - - ImplSVData* pSVData = ImplGetSVData(); - if ( !mpIdleData ) - { - // insert Idle - mpIdleData = new ImplIdleData; - mpIdleData->mpIdle = this; - mpIdleData->mbInIdle = false; - - // insert last due to SFX! - ImplIdleData* pPrev = NULL; - ImplIdleData* pData = pSVData->mpFirstIdleData; - while ( pData ) - { - pPrev = pData; - pData = pData->mpNext; - } - mpIdleData->mpNext = NULL; - if ( pPrev ) - pPrev->mpNext = mpIdleData; - else - pSVData->mpFirstIdleData = mpIdleData; - } - mpIdleData->mbDelete = false; -} - -void Idle::Stop() -{ - mbActive = false; - - if ( mpIdleData ) - mpIdleData->mbDelete = true; -} - Idle& Idle::operator=( const Idle& rIdle ) { - if ( IsActive() ) - Stop(); - - mbActive = false; - miPriority = rIdle.miPriority; - meDefaultPriority = rIdle.meDefaultPriority; - maIdleHdl = rIdle.maIdleHdl; - - if ( rIdle.IsActive() ) - Start(); - + Scheduler::operator=(rIdle); + maIdleHdl = rIdle.maIdleHdl; return *this; } -Idle::Idle(): - mpIdleData(NULL), - miPriority(static_cast<sal_Int32>(IdlePriority::HIGH)), - meDefaultPriority(IdlePriority::HIGH), - mbActive(false) +Idle::Idle() : Scheduler() { } -Idle::Idle( const Idle& rIdle ): - mpIdleData(NULL), - miPriority(rIdle.miPriority), - meDefaultPriority(rIdle.meDefaultPriority), - mbActive(false), - maIdleHdl(rIdle.maIdleHdl) +Idle::Idle( const Idle& rIdle ) : Scheduler(rIdle) { - if ( rIdle.IsActive() ) - Start(); + maIdleHdl = rIdle.maIdleHdl; } -Idle::~Idle() -{ - if ( mpIdleData ) - { - mpIdleData->mbDelete = true; - mpIdleData->mpIdle = NULL; - } -} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx new file mode 100644 index 000000000000..e2465fecfda2 --- /dev/null +++ b/vcl/source/app/scheduler.cxx @@ -0,0 +1,235 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svdata.hxx> +#include <tools/time.hxx> +#include <vcl/scheduler.hxx> + +void ImplSchedulerData::Invoke() +{ + if (mbDelete || mbInScheduler ) + return; + + mpScheduler->SetSchedulingPriority(static_cast<sal_Int32>(mpScheduler->GetDefaultPriority())); + mpScheduler->SetDeletionFlags(); + + // invoke it + mbInScheduler = true; + mpScheduler->Invoke(); + mbInScheduler = false; +} + +ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimer ) +{ + ImplSVData* pSVData = ImplGetSVData(); + ImplSchedulerData *pMostUrgent = NULL; + + for ( ImplSchedulerData *p = pSVData->mpFirstSchedulerData; p; p = p->mpNext ) + { + if ( !p->mpScheduler || p->mbDelete || p->mnUpdateStack >= pSVData->mnTimerUpdate || !p->mpScheduler->ReadyForSchedule( bTimer ) ) + continue; + if (!pMostUrgent) + pMostUrgent = p; + else + { + // Find the highest priority. + // If the priority of the current idle is higher (numerical value is lower) than + // the priority of the most urgent, the priority of most urgent is increased and + // the current is the new most urgent. So starving is impossible. + if ( p->mpScheduler->GetPriority() < pMostUrgent->mpScheduler->GetPriority() ) + { + pMostUrgent->mpScheduler->SetSchedulingPriority( pMostUrgent->mpScheduler->GetPriority()); + pMostUrgent = p; + } + else + p->mpScheduler->SetSchedulingPriority( p->mpScheduler->GetPriority()); + } + } + + return pMostUrgent; +} + +void Scheduler::SetDeletionFlags() +{ + mpSchedulerData->mbDelete = true; + mbActive = false; +} + +void Scheduler::ImplDeInitScheduler() +{ + ImplSVData* pSVData = ImplGetSVData(); + ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData; + + if ( pSchedulerData ) + { + do + { + ImplSchedulerData* pTempSchedulerData = pSchedulerData; + if ( pSchedulerData->mpScheduler ) + { + pSchedulerData->mpScheduler->mbActive = false; + pSchedulerData->mpScheduler->mpSchedulerData = NULL; + } + pSchedulerData = pSchedulerData->mpNext; + delete pTempSchedulerData; + } + while ( pSchedulerData ); + + pSVData->mpFirstSchedulerData = NULL; + } +} + +void Scheduler::CallbackTaskScheduling() +{ + Scheduler::ProcessTaskScheduling( true ); +} + +void Scheduler::ProcessTaskScheduling( bool bTimer ) +{ + // process all pending Tasks + ImplSchedulerData* pSchedulerData = NULL; + ImplSchedulerData* pPrevSchedulerData = NULL; + ImplSVData* pSVData = ImplGetSVData(); + pSVData->mnTimerUpdate++; + + if ((pSchedulerData = ImplSchedulerData::GetMostImportantTask(bTimer))) + { + pSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks(); + pSchedulerData->Invoke(); + } + + pSchedulerData = pSVData->mpFirstSchedulerData; + while ( pSchedulerData ) + { + // Should Task be released from scheduling? + 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; + } + else + { + if( !pSchedulerData->mbInScheduler ) + pSchedulerData->mnUpdateStack = 0; + pPrevSchedulerData = pSchedulerData; + pSchedulerData = pSchedulerData->mpNext; + } + } + pSVData->mnTimerUpdate--; +} + +void Scheduler::SetPriority( SchedulerPriority ePriority ) +{ + meDefaultPriority = ePriority; +} + +void Scheduler::SetSchedulingPriority( sal_Int32 iPriority ) +{ + miPriority = iPriority; +} + +void Scheduler::Start() +{ + // Mark timer active + mbActive = true; + + ImplSVData* pSVData = ImplGetSVData(); + if ( !mpSchedulerData ) + { + // insert Idle + 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; + } + mpSchedulerData->mbDelete = false; + mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks(); + mpSchedulerData->mnUpdateStack = pSVData->mnTimerUpdate; +} + +void Scheduler::Stop() +{ + mbActive = false; + + if ( mpSchedulerData ) + mpSchedulerData->mbDelete = true; +} + +Scheduler& Scheduler::operator=( const Scheduler& rScheduler ) +{ + if ( IsActive() ) + Stop(); + + mbActive = false; + miPriority = rScheduler.miPriority; + meDefaultPriority = rScheduler.meDefaultPriority; + + if ( rScheduler.IsActive() ) + Start(); + + return *this; +} + +Scheduler::Scheduler(): + mpSchedulerData(NULL), + miPriority(static_cast<sal_Int32>(SchedulerPriority::HIGH)), + meDefaultPriority(SchedulerPriority::HIGH), + mbActive(false) +{ +} + +Scheduler::Scheduler( const Scheduler& rScheduler ): + mpSchedulerData(NULL), + miPriority(rScheduler.miPriority), + meDefaultPriority(rScheduler.meDefaultPriority), + mbActive(false) +{ + if ( rScheduler.IsActive() ) + Start(); +} + +Scheduler::~Scheduler() +{ + if ( mpSchedulerData ) + { + mpSchedulerData->mbDelete = true; + mpSchedulerData->mpScheduler = NULL; + } +} + diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index f569bf90aece..33fbf0a55c1e 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -45,7 +45,7 @@ #include "vcl/cvtgrf.hxx" #include "vcl/unowrap.hxx" #include "vcl/timer.hxx" -#include "vcl/idle.hxx" +#include "vcl/scheduler.hxx" #include "vcl/unohelp.hxx" #include "vcl/lazydelete.hxx" @@ -343,11 +343,11 @@ inline void ImplYield( bool i_bWait, bool i_bAllEvents ) ImplSVData* pSVData = ImplGetSVData(); // run timers that have timed out - while ( pSVData->mbNotAllTimerCalled ) - Timer::ImplTimerCallbackProc(); + //while ( pSVData->mbNotAllTimerCalled ) + // Timer::ImplTimerCallbackProc(); //Process all idles - Idle::Idle::ProcessAllIdleHandlers(); + Scheduler::ProcessTaskScheduling(false); pSVData->maAppData.mnDispatchLevel++; // do not wait for events if application was already quit; in that @@ -367,11 +367,7 @@ inline void ImplYield( bool i_bWait, bool i_bAllEvents ) // e.g. on OS X; need to trigger timer checks manually if( pSVData->maAppData.mbNoYield ) { - do - { - Timer::ImplTimerCallbackProc( !i_bWait ); - } - while( pSVData->mbNotAllTimerCalled ); + Scheduler::ProcessTaskScheduling(true); } // call post yield listeners diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index 96302e8ca23f..43f76be04b79 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -33,7 +33,7 @@ #include "vcl/svapp.hxx" #include "vcl/wrkwin.hxx" #include "vcl/cvtgrf.hxx" -#include "vcl/idle.hxx" +#include "vcl/scheduler.hxx" #include "vcl/image.hxx" #include "vcl/settings.hxx" #include "vcl/unowrap.hxx" @@ -387,8 +387,8 @@ void DeInitVCL() if ( pSVData->maAppData.mpIdleMgr ) delete pSVData->maAppData.mpIdleMgr; - Timer::ImplDeInitTimer(); - Idle::ImplDeInitIdle(); + //Timer::ImplDeInitTimer(); + Scheduler::ImplDeInitScheduler(); if ( pSVData->maWinData.mpMsgBoxImgList ) { diff --git a/vcl/source/app/timer.cxx b/vcl/source/app/timer.cxx index 97ab45c9fbd9..b8be2d7ef40b 100644 --- a/vcl/source/app/timer.cxx +++ b/vcl/source/app/timer.cxx @@ -18,83 +18,14 @@ */ #include <tools/time.hxx> - -#include <vcl/svapp.hxx> #include <vcl/timer.hxx> - #include <saltimer.hxx> #include <svdata.hxx> #include <salinst.hxx> +#include <vcl/scheduler.hxx> #define MAX_TIMER_PERIOD ((sal_uLong)0xFFFFFFFF) -struct ImplTimerData -{ - ImplTimerData* mpNext; // Pointer to the next Instance - Timer* mpTimer; // Pointer to VCL Timer instance - sal_uLong mnUpdateTime; // Last Update Time - sal_uLong mnTimerUpdate; // TimerCallbackProcs on stack - bool mbDelete; // Was timer deleted during Update()? - bool mbInTimeout; // Are we in a timeout handler? - - void Invoke() - { - if (mbDelete || mbInTimeout ) - return; - - // if no AutoTimer than stop - if ( !mpTimer->mbAuto ) - { - mbDelete = true; - mpTimer->mbActive = false; - } - - // invoke it - mbInTimeout = true; - mpTimer->Timeout(); - mbInTimeout = false; - } - - sal_uLong GetDeadline() - { - return mnUpdateTime + mpTimer->mnTimeout; - } -}; - -void Timer::ImplDeInitTimer() -{ - ImplSVData* pSVData = ImplGetSVData(); - ImplTimerData* pTimerData = pSVData->mpFirstTimerData; - - // on WNT the timer queue thread needs killing - if (pSVData->mpSalTimer) - { - pSVData->mpSalTimer->Stop(); - } - - if ( pTimerData ) - { - do - { - ImplTimerData* pTempTimerData = pTimerData; - if ( pTimerData->mpTimer ) - { - pTimerData->mpTimer->mbActive = false; - pTimerData->mpTimer->mpTimerData = NULL; - } - pTimerData = pTimerData->mpNext; - delete pTempTimerData; - } - while ( pTimerData ); - - pSVData->mpFirstTimerData = NULL; - pSVData->mnTimerPeriod = 0; - } - - delete pSVData->mpSalTimer; - pSVData->mpSalTimer = 0; -} - static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS ) { if ( !nMS ) @@ -108,159 +39,59 @@ static void ImplStartTimer( ImplSVData* pSVData, sal_uLong nMS ) } } -void Timer::ImplTimerCallbackProc( bool idle ) +void Timer::SetDeletionFlags() { - ImplSVData* pSVData = ImplGetSVData(); - ImplTimerData* pTimerData; - ImplTimerData* pPrevTimerData; - sal_uLong nMinPeriod = MAX_TIMER_PERIOD; - sal_uLong nDeltaTime; - sal_uLong nTime = tools::Time::GetSystemTicks(); - - pSVData->mnTimerUpdate++; - pSVData->mbNotAllTimerCalled = true; - - Timer::CheckExpiredTimer(true); - - // determine new time - sal_uLong nNewTime = tools::Time::GetSystemTicks(); - pPrevTimerData = NULL; - pTimerData = pSVData->mpFirstTimerData; - while ( pTimerData ) - { - // ignore if timer is still in timeout handler - if ( pTimerData->mbInTimeout ) - { - pPrevTimerData = pTimerData; - pTimerData = pTimerData->mpNext; - } - // Was timer destroyed in the meantime? - else if ( pTimerData->mbDelete ) - { - if ( pPrevTimerData ) - pPrevTimerData->mpNext = pTimerData->mpNext; - else - pSVData->mpFirstTimerData = pTimerData->mpNext; - if ( pTimerData->mpTimer ) - pTimerData->mpTimer->mpTimerData = NULL; - ImplTimerData* pTempTimerData = pTimerData; - pTimerData = pTimerData->mpNext; - delete pTempTimerData; - } - else + // if no AutoTimer than stop + if ( !mbAuto ) { - pTimerData->mnTimerUpdate = 0; - // determine smallest time slot - if ( pTimerData->mnUpdateTime == nTime ) - { - nDeltaTime = pTimerData->mpTimer->mnTimeout; - if ( nDeltaTime < nMinPeriod ) - nMinPeriod = nDeltaTime; - } - else - { - nDeltaTime = pTimerData->mnUpdateTime + pTimerData->mpTimer->mnTimeout; - if ( nDeltaTime < nNewTime ) - nMinPeriod = 1; - else - { - nDeltaTime -= nNewTime; - if ( nDeltaTime < nMinPeriod ) - nMinPeriod = nDeltaTime; - } - } - pPrevTimerData = pTimerData; - pTimerData = pTimerData->mpNext; + mpSchedulerData->mbDelete = true; + mbActive = false; } - } - - // delete clock if no more timers available - if ( !pSVData->mpFirstTimerData ) - { - pSVData->mpSalTimer->Stop(); - pSVData->mnTimerPeriod = MAX_TIMER_PERIOD; - } - else - ImplStartTimer( pSVData, nMinPeriod ); - - pSVData->mnTimerUpdate--; - pSVData->mbNotAllTimerCalled = false; } -bool Timer::TimerReady() +bool Timer::ReadyForSchedule( bool bTimer ) { - return Timer::CheckExpiredTimer(false); + (void)bTimer; + return (mpSchedulerData->mnUpdateTime + mnTimeout) <= tools::Time::GetSystemTicks(); } -bool Timer::CheckExpiredTimer(bool bDoInvoke) +Timer::Timer() : Scheduler() { -// find timer where the timer handler needs to be called - ImplSVData* pSVData = ImplGetSVData(); - ImplTimerData* pTimerData = pSVData->mpFirstTimerData; - sal_uLong nTime = tools::Time::GetSystemTicks(); - bool timerExpired = false; - while ( pTimerData ) - { - // If the timer is not new, was not deleted, and if it is not in the timeout handler, then - // call the handler as soon as the time is up. - if ( (pTimerData->mnTimerUpdate < pSVData->mnTimerUpdate) && - !pTimerData->mbDelete && !pTimerData->mbInTimeout) - { - // time has expired - if ( pTimerData->GetDeadline() <= nTime ) - { - if(bDoInvoke) - { - //Set new update Timer - pTimerData->mnUpdateTime = nTime; - pTimerData->Invoke(); - } - timerExpired = true; - } - } - - pTimerData = pTimerData->mpNext; - } - return timerExpired; + mnTimeout = 1; + mbAuto = false; + miPriority= static_cast<sal_Int32>(SchedulerPriority::HIGHEST); + meDefaultPriority = SchedulerPriority::HIGHEST; } -Timer::Timer(): - mpTimerData(NULL), - mnTimeout(1), - mbActive(false), - mbAuto(false) +Timer::Timer( const Timer& rTimer ) : Scheduler(rTimer) { + mnTimeout = rTimer.mnTimeout; + mbAuto = rTimer.mbAuto; + maTimeoutHdl = rTimer.maTimeoutHdl; } -Timer::Timer( const Timer& rTimer ): - mpTimerData(NULL), - mnTimeout(rTimer.mnTimeout), - mbActive(false), - mbAuto(false), - maTimeoutHdl(rTimer.maTimeoutHdl) +void Timer::Invoke() { - if ( rTimer.IsActive() ) - Start(); + maTimeoutHdl.Call( this ); } -Timer::~Timer() +void Timer::Start() { - if ( mpTimerData ) + Scheduler::Start(); + ImplSVData* pSVData = ImplGetSVData(); + if( ! pSVData->mpSalTimer ) { - mpTimerData->mbDelete = true; - mpTimerData->mpTimer = NULL; - } -} - -void Timer::Timeout() -{ - maTimeoutHdl.Call( this ); + pSVData->mnTimerPeriod = MAX_TIMER_PERIOD; + pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer(); + pSVData->mpSalTimer->SetCallback( CallbackTaskScheduling ); + } + if ( mnTimeout < pSVData->mnTimerPeriod ) + ImplStartTimer( pSVData, mnTimeout ); } void Timer::SetTimeout( sal_uLong nNewTimeout ) { mnTimeout = nNewTimeout; - // if timer is active then renew clock if ( mbActive ) { @@ -270,80 +101,12 @@ void Timer::SetTimeout( sal_uLong nNewTimeout ) } } -void Timer::Start() -{ - mbActive = true; - - ImplSVData* pSVData = ImplGetSVData(); - if ( !mpTimerData ) - { - if ( !pSVData->mpFirstTimerData ) - { - pSVData->mnTimerPeriod = MAX_TIMER_PERIOD; - if( ! pSVData->mpSalTimer ) - { - pSVData->mpSalTimer = pSVData->mpDefInst->CreateSalTimer(); - pSVData->mpSalTimer->SetCallback( ImplTimerCallbackProc ); - } - } - - // insert timer and start - mpTimerData = new ImplTimerData; - mpTimerData->mpTimer = this; - mpTimerData->mnUpdateTime = tools::Time::GetSystemTicks(); - mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate; - mpTimerData->mbDelete = false; - mpTimerData->mbInTimeout = false; - - // insert last due to SFX! - ImplTimerData* pPrev = NULL; - ImplTimerData* pData = pSVData->mpFirstTimerData; - while ( pData ) - { - pPrev = pData; - pData = pData->mpNext; - } - mpTimerData->mpNext = NULL; - if ( pPrev ) - pPrev->mpNext = mpTimerData; - else - pSVData->mpFirstTimerData = mpTimerData; - - if ( mnTimeout < pSVData->mnTimerPeriod ) - ImplStartTimer( pSVData, mnTimeout ); - } - else if( !mpTimerData->mpTimer ) // TODO: remove when guilty found - { - OSL_FAIL( "Timer::Start() on a destroyed Timer!" ); - } - else - { - mpTimerData->mnUpdateTime = tools::Time::GetSystemTicks(); - mpTimerData->mnTimerUpdate = pSVData->mnTimerUpdate; - mpTimerData->mbDelete = false; - } -} - -void Timer::Stop() -{ - mbActive = false; - - if ( mpTimerData ) - mpTimerData->mbDelete = true; -} - Timer& Timer::operator=( const Timer& rTimer ) { - if ( IsActive() ) - Stop(); - - mbActive = false; - mnTimeout = rTimer.mnTimeout; - maTimeoutHdl = rTimer.maTimeoutHdl; - - if ( rTimer.IsActive() ) - Start(); - + Scheduler::operator=(rTimer); + maTimeoutHdl = rTimer.maTimeoutHdl; + mnTimeout = rTimer.mnTimeout; + mbAuto = rTimer.mbAuto; return *this; } |