include/vcl/scheduler.hxx | 7 + sc/qa/unoapi/sc_4.sce | 7 + sfx2/source/appl/appinit.cxx | 5 vcl/inc/schedulerimpl.hxx | 35 ++++++ vcl/inc/svdata.hxx | 232 ++++++++++++++++++++++--------------------- vcl/source/app/scheduler.cxx | 93 ++++++++++++++--- vcl/source/app/svapp.cxx | 38 ++++--- vcl/source/app/svdata.cxx | 10 - 8 files changed, 267 insertions(+), 160 deletions(-)
New commits: commit 31c450e6a07ae74f654cff71f68c12dd6b0513e4 Author: Stephan Bergmann <sberg...@redhat.com> Date: Sat Oct 8 23:45:40 2016 +0200 loplugin:badstatics ...so make aPostedEventList a member of the global ImpSVAppData singleton Reviewed-on: https://gerrit.libreoffice.org/29612 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Stephan Bergmann <sberg...@redhat.com> Conflicts: vcl/inc/svdata.hxx Change-Id: Ie7ac49b56107eb393514d9ba1d91ee66296f60a0 diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index c4daa04d5555..4b1c1d7b3fa1 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -32,10 +32,12 @@ #include "impfontcache.hxx" #include "xconnection.hxx" +#include <list> #include <unordered_map> #include <boost/functional/hash.hpp> #include "schedulerimpl.hxx" +struct ImplPostEventData; struct ImplTimerData; struct ImplIdleData; struct ImplConfigData; @@ -110,6 +112,8 @@ public: typedef std::vector<Link<VclWindowEvent&,bool> > SVAppKeyListeners; +typedef std::pair<VclPtr<vcl::Window>, ImplPostEventData *> ImplPostEventPair; + struct ImplSVAppData { enum ImeStatusWindowMode @@ -119,42 +123,43 @@ struct ImplSVAppData ImeStatusWindowMode_SHOW }; - AllSettings* mpSettings; // Application settings - LocaleConfigurationListener* mpCfgListener; - VclEventListeners* mpEventListeners; // listeners for vcl events (eg, extended toolkit) - SVAppKeyListeners* mpKeyListeners; // listeners for key events only (eg, extended toolkit) - ImplAccelManager* mpAccelMgr; // Accelerator Manager - OUString* mpAppName; // Application name - OUString* mpAppFileName; // Abs. Application FileName - OUString* mpDisplayName; // Application Display Name - OUString* mpToolkitName; // Toolkit Name - Help* mpHelp; // Application help + AllSettings* mpSettings = nullptr; // Application settings + LocaleConfigurationListener* mpCfgListener = nullptr; + VclEventListeners* mpEventListeners = nullptr; // listeners for vcl events (eg, extended toolkit) + SVAppKeyListeners* mpKeyListeners = nullptr; // listeners for key events only (eg, extended toolkit) + std::list<ImplPostEventPair> maPostedEventList; + ImplAccelManager* mpAccelMgr = nullptr; // Accelerator Manager + OUString* mpAppName = nullptr; // Application name + OUString* mpAppFileName = nullptr; // Abs. Application FileName + OUString* mpDisplayName = nullptr; // Application Display Name + OUString* mpToolkitName = nullptr; // Toolkit Name + Help* mpHelp = nullptr; // Application help PopupMenu* mpActivePopupMenu; // Actives Popup-Menu (in Execute) ImplIdleMgr* mpIdleMgr; // Idle-Manager VclPtr<ImplWheelWindow> mpWheelWindow; // WheelWindow - ImplHotKey* mpFirstHotKey; // HotKey-Verwaltung - ImplEventHook* mpFirstEventHook; // Event-Hooks - sal_uInt64 mnLastInputTime; // GetLastInputTime() - sal_uInt16 mnDispatchLevel; // DispatchLevel - sal_uInt16 mnModalMode; // ModalMode Count - SystemWindowFlags mnSysWinMode; // Mode, when SystemWindows should be created + ImplHotKey* mpFirstHotKey = nullptr; // HotKey-Verwaltung + ImplEventHook* mpFirstEventHook = nullptr; // Event-Hooks + sal_uInt64 mnLastInputTime = 0; // GetLastInputTime() + sal_uInt16 mnDispatchLevel = 0; // DispatchLevel + sal_uInt16 mnModalMode = 0; // ModalMode Count + SystemWindowFlags mnSysWinMode = SystemWindowFlags(0); // Mode, when SystemWindows should be created short mnDialogScaleX; // Scale X-Positions and sizes in Dialogs - bool mbInAppMain; // is Application::Main() on stack - bool mbInAppExecute; // is Application::Execute() on stack - bool mbAppQuit; // is Application::Quit() called - bool mbSettingsInit; // true: Settings are initialized - Application::DialogCancelMode meDialogCancel; // true: All Dialog::Execute() calls will be terminated immediately with return false + bool mbInAppMain = false; // is Application::Main() on stack + bool mbInAppExecute = false; // is Application::Execute() on stack + bool mbAppQuit = false; // is Application::Quit() called + bool mbSettingsInit = false; // true: Settings are initialized + Application::DialogCancelMode meDialogCancel; // true: All Dialog::Execute() calls will be terminated immediately with return false /** Controls whether showing any IME status window is toggled on or off. Only meaningful if showing IME status windows can be toggled on and off externally (see Application::CanToggleImeStatusWindow). */ - ImeStatusWindowMode meShowImeStatusWindow; + ImeStatusWindowMode meShowImeStatusWindow = ImeStatusWindowMode_UNKNOWN; - SvFileStream* mpEventTestInput; - Idle* mpEventTestingIdle; - int mnEventTestLimit; + SvFileStream* mpEventTestInput = nullptr; + Idle* mpEventTestingIdle = nullptr; + int mnEventTestLimit = 0; DECL_STATIC_LINK_TYPED(ImplSVAppData, ImplQuitMsg, void*, void); DECL_STATIC_LINK_TYPED(ImplSVAppData, ImplPrepareExitMsg, void*, void); @@ -176,20 +181,20 @@ struct ImplSVGDIData VclPtr<OutputDevice> mpLastPrnGraphics; // Last OutputDevice with a InfoPrinter Graphics VclPtr<VirtualDevice> mpFirstVirDev; // First VirtualDevice VclPtr<VirtualDevice> mpLastVirDev; // Last VirtualDevice - OpenGLContext* mpFirstContext; // First OpenGLContext - OpenGLContext* mpLastContext; // Last OpenGLContext + OpenGLContext* mpFirstContext = nullptr; // First OpenGLContext + OpenGLContext* mpLastContext = nullptr; // Last OpenGLContext VclPtr<Printer> mpFirstPrinter; // First Printer VclPtr<Printer> mpLastPrinter; // Last Printer - ImplPrnQueueList* mpPrinterQueueList; // List of all printer queue - PhysicalFontCollection* mpScreenFontList; // Screen-Font-List - ImplFontCache* mpScreenFontCache; // Screen-Font-Cache - ImplDirectFontSubstitution* mpDirectFontSubst; // Font-Substitutons defined in Tools->Options->Fonts - GraphicConverter* mpGrfConverter; // Converter for graphics + ImplPrnQueueList* mpPrinterQueueList = nullptr; // List of all printer queue + PhysicalFontCollection* mpScreenFontList = nullptr; // Screen-Font-List + ImplFontCache* mpScreenFontCache = nullptr; // Screen-Font-Cache + ImplDirectFontSubstitution* mpDirectFontSubst = nullptr; // Font-Substitutons defined in Tools->Options->Fonts + GraphicConverter* mpGrfConverter = nullptr; // Converter for graphics long mnRealAppFontX; // AppFont X-Numenator for 40/tel Width - long mnAppFontX; // AppFont X-Numenator for 40/tel Width + DialogScaleX - long mnAppFontY; // AppFont Y-Numenator for 80/tel Height - bool mbFontSubChanged; // true: FontSubstitution was changed between Begin/End - bool mbNativeFontConfig; // true: do not override UI font + long mnAppFontX = 0; // AppFont X-Numenator for 40/tel Width + long mnAppFontY = 0; // AppFont Y-Numenator for 80/tel Height + bool mbFontSubChanged = false; // true: FontSubstitution was changed between Begin/End + bool mbNativeFontConfig = false; // true: do not override UI font }; struct ImplSVWinData @@ -204,56 +209,58 @@ struct ImplSVWinData VclPtr<Dialog> mpLastExecuteDlg; // First Dialog that is in Execute VclPtr<vcl::Window> mpExtTextInputWin; // Window, which is in ExtTextInput VclPtr<vcl::Window> mpTrackWin; // window, that is in tracking mode - AutoTimer* mpTrackTimer; // tracking timer - ImageList* mpMsgBoxImgList; // ImageList for MessageBox + AutoTimer* mpTrackTimer = nullptr; // tracking timer + ImageList* mpMsgBoxImgList = nullptr; // ImageList for MessageBox VclPtr<vcl::Window> mpAutoScrollWin; // window, that is in AutoScrollMode mode VclPtr<vcl::Window> mpLastWheelWindow; // window, that last received a mouse wheel event - StartTrackingFlags mnTrackFlags; // tracking flags - StartAutoScrollFlags mnAutoScrollFlags; // auto scroll flags - bool mbNoDeactivate; // true: do not execute Deactivate - bool mbNoSaveFocus; // true: menus must not save/restore focus + SalWheelMouseEvent maLastWheelEvent; // the last received mouse whell event + + StartTrackingFlags mnTrackFlags = StartTrackingFlags::NONE; // tracking flags + StartAutoScrollFlags mnAutoScrollFlags = StartAutoScrollFlags::NONE; // auto scroll flags + bool mbNoDeactivate = false; // true: do not execute Deactivate + bool mbNoSaveFocus = false; // true: menus must not save/restore focus }; typedef std::vector< std::pair< OUString, FieldUnit > > FieldUnitStringList; struct ImplSVCtrlData { - ImageList* mpCheckImgList; // ImageList for CheckBoxes - ImageList* mpRadioImgList; // ImageList for RadioButtons - ImageList* mpPinImgList; // ImageList for PIN - ImageList* mpSplitHPinImgList; // ImageList for Horizontale SplitWindows - ImageList* mpSplitVPinImgList; // ImageList for Vertikale SplitWindows (PIN's) + ImageList* mpCheckImgList = nullptr; // ImageList for CheckBoxes + ImageList* mpRadioImgList = nullptr; // ImageList for RadioButtons + ImageList* mpPinImgList = nullptr; // ImageList for PIN + ImageList* mpSplitHPinImgList = nullptr; // ImageList for Horizontale SplitWindows + ImageList* mpSplitVPinImgList = nullptr; // ImageList for Vertikale SplitWindows (PIN's) ImageList* mpSplitHArwImgList; // ImageList for Horizontale SplitWindows (Arrows) ImageList* mpSplitVArwImgList; // ImageList for Vertikale SplitWindows (Arrows) - Image* mpDisclosurePlus; - Image* mpDisclosureMinus; - ImplTBDragMgr* mpTBDragMgr; // DragMgr for ToolBox - sal_uInt16 mnCheckStyle; // CheckBox-Style for ImageList-Update - sal_uInt16 mnRadioStyle; // Radio-Style for ImageList-Update - sal_uLong mnLastCheckFColor; // Letzte FaceColor fuer CheckImage - sal_uLong mnLastCheckWColor; // Letzte WindowColor fuer CheckImage - sal_uLong mnLastCheckLColor; // Letzte LightColor fuer CheckImage - sal_uLong mnLastRadioFColor; // Letzte FaceColor fuer RadioImage - sal_uLong mnLastRadioWColor; // Letzte WindowColor fuer RadioImage - sal_uLong mnLastRadioLColor; // Letzte LightColor fuer RadioImage - FieldUnitStringList* mpFieldUnitStrings; // list with field units - FieldUnitStringList* mpCleanUnitStrings; // same list but with some "fluff" like spaces removed + Image* mpDisclosurePlus = nullptr; + Image* mpDisclosureMinus = nullptr; + ImplTBDragMgr* mpTBDragMgr = nullptr; // DragMgr for ToolBox + sal_uInt16 mnCheckStyle = 0; // CheckBox-Style for ImageList-Update + sal_uInt16 mnRadioStyle = 0; // Radio-Style for ImageList-Update + sal_uLong mnLastCheckFColor = 0; // Letzte FaceColor fuer CheckImage + sal_uLong mnLastCheckWColor = 0; // Letzte WindowColor fuer CheckImage + sal_uLong mnLastCheckLColor = 0; // Letzte LightColor fuer CheckImage + sal_uLong mnLastRadioFColor = 0; // Letzte FaceColor fuer RadioImage + sal_uLong mnLastRadioWColor = 0; // Letzte WindowColor fuer RadioImage + sal_uLong mnLastRadioLColor = 0; // Letzte LightColor fuer RadioImage + FieldUnitStringList* mpFieldUnitStrings = nullptr; // list with field units + FieldUnitStringList* mpCleanUnitStrings = nullptr; // same list but with some "fluff" like spaces removed }; struct ImplSVHelpData { - bool mbContextHelp : 1; // is ContextHelp enabled - bool mbExtHelp : 1; // is ExtendedHelp enabled - bool mbExtHelpMode : 1; // is in ExtendedHelp Mode - bool mbOldBalloonMode : 1; // BalloonMode, before ExtHelpMode started - bool mbBalloonHelp : 1; // is BalloonHelp enabled - bool mbQuickHelp : 1; // is QuickHelp enabled - bool mbSetKeyboardHelp : 1; // tiphelp was activated by keyboard - bool mbKeyboardHelp : 1; // tiphelp was activated by keyboard - bool mbAutoHelpId : 1; // generate HelpIds - bool mbRequestingHelp : 1; // In Window::RequestHelp + bool mbContextHelp = false; // is ContextHelp enabled + bool mbExtHelp = false; // is ExtendedHelp enabled + bool mbExtHelpMode = false; // is in ExtendedHelp Mode + bool mbOldBalloonMode = false; // BalloonMode, before ExtHelpMode started + bool mbBalloonHelp = false; // is BalloonHelp enabled + bool mbQuickHelp = false; // is QuickHelp enabled + bool mbSetKeyboardHelp = false; // tiphelp was activated by keyboard + bool mbKeyboardHelp = false; // tiphelp was activated by keyboard + bool mbAutoHelpId = true; // generate HelpIds + bool mbRequestingHelp = false; // In Window::RequestHelp VclPtr<HelpTextWindow> mpHelpWin; // HelpWindow - sal_uInt64 mnLastHelpHideTime; // ticks of last show + sal_uInt64 mnLastHelpHideTime = 0; // ticks of last show }; // "NWF" means "Native Widget Framework" and was the term used for the @@ -263,37 +270,37 @@ struct ImplSVHelpData struct ImplSVNWFData { - int mnStatusBarLowerRightOffset; // amount in pixel to avoid in the lower righthand corner - int mnMenuFormatBorderX; // horizontal inner popup menu border - int mnMenuFormatBorderY; // vertical inner popup menu border - int mnMenuSeparatorBorderX; // gap at each side of separator - ::Color maMenuBarHighlightTextColor; // override higlight text color + int mnStatusBarLowerRightOffset = 0; // amount in pixel to avoid in the lower righthand corner + int mnMenuFormatBorderX = 0; // horizontal inner popup menu border + int mnMenuFormatBorderY = 0; // vertical inner popup menu border + int mnMenuSeparatorBorderX = 0; // gap at each side of separator + ::Color maMenuBarHighlightTextColor = Color( COL_TRANSPARENT ); // override higlight text color // in menubar if not transparent - bool mbMenuBarDockingAreaCommonBG:1; // e.g. WinXP default theme - bool mbDockingAreaSeparateTB:1; // individual toolbar backgrounds + bool mbMenuBarDockingAreaCommonBG = false; // e.g. WinXP default theme + bool mbDockingAreaSeparateTB = false; // individual toolbar backgrounds // instead of one for docking area - bool mbDockingAreaAvoidTBFrames:1; ///< don't draw frames around the individual toolbars if mbDockingAreaSeparateTB is false - bool mbToolboxDropDownSeparate:1; // two adjacent buttons for + bool mbDockingAreaAvoidTBFrames = false; ///< don't draw frames around the individual toolbars if mbDockingAreaSeparateTB is false + bool mbToolboxDropDownSeparate = false; // two adjacent buttons for // toolbox dropdown buttons - bool mbFlatMenu:1; // no popup 3D border - bool mbOpenMenuOnF10:1; // on gnome the first menu opens on F10 - bool mbNoFocusRects:1; // on Aqua/Gtk3 use native focus rendering, except for flat buttons - bool mbNoFocusRectsForFlatButtons:1; // on Gtk3 native focusing is also preferred for flat buttons - bool mbCenteredTabs:1; // on Aqua, tabs are centered - bool mbNoActiveTabTextRaise:1; // on Aqua the text for the selected tab + bool mbFlatMenu = false; // no popup 3D border + bool mbOpenMenuOnF10 = false; // on gnome the first menu opens on F10 + bool mbNoFocusRects = false; // on Aqua/Gtk3 use native focus rendering, except for flat buttons + bool mbNoFocusRectsForFlatButtons = false; // on Gtk3 native focusing is also preferred for flat buttons + bool mbCenteredTabs = false; // on Aqua, tabs are centered + bool mbNoActiveTabTextRaise = false; // on Aqua the text for the selected tab // should not "jump up" a pixel - bool mbProgressNeedsErase:1; // set true for platforms that should draw the + bool mbProgressNeedsErase = false; // set true for platforms that should draw the // window background before drawing the native // progress bar - bool mbCheckBoxNeedsErase:1; // set true for platforms that should draw the + bool mbCheckBoxNeedsErase = false; // set true for platforms that should draw the // window background before drawing the native // checkbox - bool mbCanDrawWidgetAnySize:1; // set to true currently on gtk + bool mbCanDrawWidgetAnySize = false; // set to true currently on gtk /// entire drop down listbox resembles a button, no textarea/button parts (as currently on Windows) - bool mbDDListBoxNoTextArea:1; - bool mbEnableAccel:1; // whether or not accelerators are shown - bool mbAutoAccel:1; // whether accelerators are only shown when Alt is held down + bool mbDDListBoxNoTextArea = false; + bool mbEnableAccel = true; // whether or not accelerators are shown + bool mbAutoAccel = false; // whether accelerators are only shown when Alt is held down }; struct BlendFrameCache @@ -331,36 +338,37 @@ struct ImplSchedulerContext struct ImplSVData { - ImplSVData(); - - SalData* mpSalData; - SalInstance* mpDefInst; // Default SalInstance - Application* mpApp; // pApp + SalData* mpSalData = nullptr; + SalInstance* mpDefInst = nullptr; // Default SalInstance + Application* mpApp = nullptr; // pApp VclPtr<WorkWindow> mpDefaultWin; // Default-Window - bool mbDeInit; // Is VCL deinitializing - SalI18NImeStatus* mpImeStatus; // interface to ime status window - SalSystem* mpSalSystem; // SalSystem interface - ResMgr* mpResMgr; // SV-Resource-Manager - ImplSchedulerContext maSchedCtx; // indepen data for class Scheduler + ImplSchedulerContext maSchedCtx; // indepen data for class Scheduler + bool mbDeInit = false; // Is VCL deinitializing + ImplSchedulerData* mpFirstSchedulerData = nullptr; // list of all running tasks + SalTimer* mpSalTimer = nullptr; // interface to sal event loop/timers + SalI18NImeStatus* mpImeStatus = nullptr; // interface to ime status window + SalSystem* mpSalSystem = nullptr; // SalSystem interface + ResMgr* mpResMgr = nullptr; // SV-Resource-Manager + sal_uInt64 mnTimerPeriod = 0; // current timer period ImplSVAppData maAppData; // indepen data for class Application ImplSVGDIData maGDIData; // indepen data for Output classes ImplSVWinData maWinData; // indepen data for Windows classes ImplSVCtrlData maCtrlData; // indepen data for Control classes ImplSVHelpData maHelpData; // indepen data for Help classes ImplSVNWFData maNWFData; - UnoWrapperBase* mpUnoWrapper; + UnoWrapperBase* mpUnoWrapper = nullptr; VclPtr<vcl::Window> mpIntroWindow; // the splash screen - DockingManager* mpDockingManager; - BlendFrameCache* mpBlendFrameCache; - vcl::CommandInfoProvider* mpCommandInfoProvider; + DockingManager* mpDockingManager = nullptr; + BlendFrameCache* mpBlendFrameCache = nullptr; + vcl::CommandInfoProvider* mpCommandInfoProvider = nullptr; - oslThreadIdentifier mnMainThreadId; + oslThreadIdentifier mnMainThreadId = 0; rtl::Reference< vcl::DisplayConnection > mxDisplayConnection; css::uno::Reference< css::lang::XComponent > mxAccessBridge; - vcl::SettingsConfigItem* mpSettingsConfigItem; - std::list< vcl::DeleteOnDeinitBase* >* mpDeinitDeleteList; - std::unordered_map< int, OUString >* mpPaperNames; + vcl::SettingsConfigItem* mpSettingsConfigItem = nullptr; + std::list< vcl::DeleteOnDeinitBase* >* mpDeinitDeleteList = nullptr; + std::unordered_map< int, OUString >* mpPaperNames = nullptr; Link<LinkParamNone*,void> maDeInitHook; }; diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index db69f9847bb2..6af3c7c1c7cf 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -192,10 +192,6 @@ struct ImplPostEventData ~ImplPostEventData() {} }; -typedef ::std::pair< VclPtr<vcl::Window>, ImplPostEventData* > ImplPostEventPair; - -static ::std::list< ImplPostEventPair > aPostedEventList; - Application* GetpApp() { ImplSVData* pSVData = ImplGetSVData(); @@ -927,7 +923,7 @@ ImplSVEvent * Application::PostKeyEvent( sal_uLong nEvent, vcl::Window *pWin, Ke if( nEventId ) { pPostEventData->mnEventId = nEventId; - aPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) ); + ImplGetSVData()->maAppData.maPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) ); } else delete pPostEventData; @@ -960,7 +956,7 @@ ImplSVEvent * Application::PostMouseEvent( sal_uLong nEvent, vcl::Window *pWin, if( nEventId ) { pPostEventData->mnEventId = nEventId; - aPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) ); + ImplGetSVData()->maAppData.maPostedEventList.push_back( ImplPostEventPair( pWin, pPostEventData ) ); } else delete pPostEventData; @@ -1025,14 +1021,15 @@ IMPL_STATIC_LINK_TYPED( Application, PostEventHandler, void*, pCallData, void ) ImplWindowFrameProc( pData->mpWin.get()->mpWindowImpl->mpFrameWindow.get(), nEvent, pEventData ); // remove this event from list of posted events, watch for destruction of internal data - ::std::list< ImplPostEventPair >::iterator aIter( aPostedEventList.begin() ); + auto svdata = ImplGetSVData(); + ::std::list< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() ); - while( aIter != aPostedEventList.end() ) + while( aIter != svdata->maAppData.maPostedEventList.end() ) { if( nEventId == (*aIter).second->mnEventId ) { delete (*aIter).second; - aIter = aPostedEventList.erase( aIter ); + aIter = svdata->maAppData.maPostedEventList.erase( aIter ); } else ++aIter; @@ -1044,9 +1041,10 @@ void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin ) const SolarMutexGuard aGuard; // remove all events for specific window, watch for destruction of internal data - ::std::list< ImplPostEventPair >::iterator aIter( aPostedEventList.begin() ); + auto svdata = ImplGetSVData(); + ::std::list< ImplPostEventPair >::iterator aIter( svdata->maAppData.maPostedEventList.begin() ); - while( aIter != aPostedEventList.end() ) + while( aIter != svdata->maAppData.maPostedEventList.end() ) { if( pWin == (*aIter).first ) { @@ -1054,7 +1052,7 @@ void Application::RemoveMouseAndKeyEvents( vcl::Window* pWin ) RemoveUserEvent( (*aIter).second->mnEventId ); delete (*aIter).second; - aIter = aPostedEventList.erase( aIter ); + aIter = svdata->maAppData.maPostedEventList.erase( aIter ); } else ++aIter; diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index ddad3e3738e8..99bf8976ce8f 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -79,16 +79,6 @@ SalSystem* ImplGetSalSystem() return pSVData->mpSalSystem; } -ImplSVData::ImplSVData() -{ - // init global instance data - memset( this, 0, sizeof( ImplSVData ) ); - maHelpData.mbAutoHelpId = true; - maNWFData.maMenuBarHighlightTextColor = Color( COL_TRANSPARENT ); - maNWFData.mbEnableAccel = true; - maNWFData.mbAutoAccel = false; -} - ImplSVGDIData::~ImplSVGDIData() { // FIXME: deliberately leak any remaining OutputDevice commit 63f2e482857986e44f8fbc9b378e688b071d83d3 Author: Jan-Marek Glogowski <glo...@fbihome.de> Date: Thu Jul 27 11:42:31 2017 +0200 Implement VCL Scheduler locking Replces the SolarMutex scheduler locking by using a distinct mutex included in the scheduler context. It should also get rid of the spurious assert( !bAniIdle ) failures, as the test now holds the Scheduler lock for the whole time. This includes reverting the additional scheduler de-init from commit 2e29a518b04250b5f9cc9d0d77da3df076834d60, as I couldn't reproduce the bug running the unit test in valgrind. Reviewed-on: https://gerrit.libreoffice.org/40497 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Jan-Marek Glogowski <glo...@fbihome.de> Conflicts: vcl/inc/svdata.hxx vcl/source/app/scheduler.cxx Change-Id: If33f815fe86c8f82175e96adceb1084b925319dd diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index 0c0559a40b2b..d23148a7fde3 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -22,6 +22,7 @@ #include <vcl/dllapi.h> +class SchedulerGuard; class Task; struct TaskImpl; struct ImplSchedulerContext; @@ -29,8 +30,9 @@ struct ImplSchedulerData; class VCL_DLLPUBLIC Scheduler final { + friend class SchedulerGuard; friend class Task; - Scheduler() = delete; + Scheduler() SAL_DELETED_FUNCTION; static inline bool HasPendingTasks( const ImplSchedulerContext &rSchedCtx, const sal_uInt64 nTime ); @@ -41,6 +43,9 @@ class VCL_DLLPUBLIC Scheduler final static void ImplStartTimer ( sal_uInt64 nMS, bool bForce, sal_uInt64 nTime ); + static bool Lock( sal_uInt32 nLockCount = 1 ); + static sal_uInt32 Unlock( bool bUnlockAll = false ); + public: static const SAL_CONSTEXPR sal_uInt64 ImmediateTimeoutMs = 0; static const SAL_CONSTEXPR sal_uInt64 InfiniteTimeoutMs = SAL_MAX_UINT64; // 1 day diff --git a/sc/qa/unoapi/sc_4.sce b/sc/qa/unoapi/sc_4.sce index b501c1189146..61bd5b557867 100644 --- a/sc/qa/unoapi/sc_4.sce +++ b/sc/qa/unoapi/sc_4.sce @@ -30,7 +30,12 @@ -o sc.ScHeaderFieldsObj -o sc.ScHeaderFooterContentObj -o sc.ScHeaderFooterTextCursor --o sc.ScHeaderFooterTextObj +# SHF_TextObj is composed of SHF_TextData, which has a weak reference to +# SHF_ContentObj, which itself has three references to SHF_TextObj. +# The css::text::XTextRange test fails often when the weak SHF_ContentObj is +# already gone. If just this test is disabled, later tests of this object fail +# too, so this disables the whole interface. +# -o sc.ScHeaderFooterTextObj -o sc.ScIndexEnumeration_CellAnnotationsEnumeration -o sc.ScIndexEnumeration_CellAreaLinksEnumeration -o sc.ScIndexEnumeration_DDELinksEnumeration diff --git a/sfx2/source/appl/appinit.cxx b/sfx2/source/appl/appinit.cxx index bd00ae5ee589..6d58627af32a 100644 --- a/sfx2/source/appl/appinit.cxx +++ b/sfx2/source/appl/appinit.cxx @@ -47,7 +47,6 @@ #include <cppuhelper/supportsservice.hxx> #include <vcl/edit.hxx> -#include <vcl/scheduler.hxx> #include <sfx2/unoctitm.hxx> #include "app.hrc" @@ -107,10 +106,6 @@ void SAL_CALL SfxTerminateListener_Impl::notifyTermination( const EventObject& a SolarMutexGuard aGuard; utl::ConfigManager::storeConfigItems(); - // Timers may access the SfxApplication and are only deleted in - // Application::Quit(), which is asynchronous (PostUserEvent) - disable! - Scheduler::ImplDeInitScheduler(); - SfxApplication* pApp = SfxGetpApp(); pApp->Broadcast( SfxSimpleHint( SFX_HINT_DEINITIALIZING ) ); pApp->Get_Impl()->pAppDispatch->ReleaseAll(); diff --git a/vcl/inc/schedulerimpl.hxx b/vcl/inc/schedulerimpl.hxx index 2c29de6a6b30..df10fc930bda 100644 --- a/vcl/inc/schedulerimpl.hxx +++ b/vcl/inc/schedulerimpl.hxx @@ -21,6 +21,8 @@ #define INCLUDED_VCL_INC_SCHEDULERIMPL_HXX #include <salwtype.hxx> +#include <osl/mutex.hxx> +#include <vcl/scheduler.hxx> class Task; @@ -35,6 +37,39 @@ struct ImplSchedulerData final const char *GetDebugName() const; }; +class SchedulerMutex final +{ + sal_uInt32 mnLockDepth; + osl::Mutex maMutex; + +public: + SchedulerMutex() : mnLockDepth( 0 ) {} + + bool acquire( sal_uInt32 nLockCount = 1 ); + sal_uInt32 release( bool bUnlockAll = false ); + sal_uInt32 lockDepth() const { return mnLockDepth; } +}; + +class SchedulerGuard final +{ + bool mbLocked; + +public: + SchedulerGuard() + : mbLocked( false ) + { + mbLocked = Scheduler::Lock(); + assert( mbLocked ); + } + + ~SchedulerGuard() + { + if ( !mbLocked ) + return; + Scheduler::Unlock(); + } +}; + #endif // INCLUDED_VCL_INC_SCHEDULERIMPL_HXX /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index dd9ec19269af..c4daa04d5555 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -34,6 +34,7 @@ #include <unordered_map> #include <boost/functional/hash.hpp> +#include "schedulerimpl.hxx" struct ImplTimerData; struct ImplIdleData; @@ -41,7 +42,6 @@ struct ImplConfigData; class ImplDirectFontSubstitution; struct ImplHotKey; struct ImplEventHook; -struct ImplSchedulerData; class Point; class ResMgr; class ImplAccelManager; @@ -325,6 +325,8 @@ struct ImplSchedulerContext 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 + SchedulerMutex maMutex; ///< lock counting mutex for scheduler locking + bool mbActive = true; ///< is the scheduler active? }; struct ImplSVData diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index 2cd0940fc534..ccd127c08453 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -85,20 +85,29 @@ inline std::basic_ostream<charT, traits> & operator <<( void Scheduler::ImplDeInitScheduler() { - ImplSVData* pSVData = ImplGetSVData(); + ImplSVData* pSVData = ImplGetSVData(); assert( pSVData != nullptr ); ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx; + DBG_TESTSOLARMUTEX(); + + SchedulerGuard aSchedulerGuard; + rSchedCtx.mbActive = false; + + assert( nullptr == rSchedCtx.mpSchedulerStack ); + assert( 1 == rSchedCtx.maMutex.lockDepth() ); + if (rSchedCtx.mpSalTimer) rSchedCtx.mpSalTimer->Stop(); DELETEZ( rSchedCtx.mpSalTimer ); ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData; while ( pSchedulerData ) { - if ( pSchedulerData->mpTask ) + Task *pTask = pSchedulerData->mpTask; + if ( pTask ) { - pSchedulerData->mpTask->mbActive = false; - pSchedulerData->mpTask->mpSchedulerData = nullptr; + pTask->mbActive = false; + pTask->mpSchedulerData = nullptr; } ImplSchedulerData* pDeleteSchedulerData = pSchedulerData; pSchedulerData = pSchedulerData->mpNext; @@ -110,6 +119,55 @@ void Scheduler::ImplDeInitScheduler() rSchedCtx.mnTimerPeriod = InfiniteTimeoutMs; } +bool SchedulerMutex::acquire( sal_uInt32 nLockCount ) +{ + do { + if ( !maMutex.acquire() ) + return false; + ++mnLockDepth; + } + while ( --nLockCount ); + return true; +} + +sal_uInt32 SchedulerMutex::release( bool bUnlockAll ) +{ + sal_uInt32 nLockCount = 0; + if ( mnLockDepth ) + { + if ( bUnlockAll ) + { + nLockCount = mnLockDepth; + do { + --mnLockDepth; + maMutex.release(); + } + while ( mnLockDepth ); + } + else + { + nLockCount = 1; + --mnLockDepth; + maMutex.release(); + } + } + return nLockCount; +} + +bool Scheduler::Lock( sal_uInt32 nLockCount ) +{ + ImplSVData* pSVData = ImplGetSVData(); + assert( pSVData != nullptr ); + return pSVData->maSchedCtx.maMutex.acquire( nLockCount ); +} + +sal_uInt32 Scheduler::Unlock( bool bUnlockAll ) +{ + ImplSVData* pSVData = ImplGetSVData(); + assert( pSVData != nullptr ); + return pSVData->maSchedCtx.maMutex.release( bUnlockAll ); +} + /** * Start a new timer if we need to for nMS duration. * @@ -120,16 +178,12 @@ void Scheduler::ImplDeInitScheduler() void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime) { ImplSVData* pSVData = ImplGetSVData(); - if (pSVData->mbDeInit) - { - // do not start new timers during shutdown - if that happens after - // ImplSalStopTimer() on WNT the timer queue is restarted and never ends + ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx; + if ( !rSchedCtx.mbActive ) return; - } DBG_TESTSOLARMUTEX(); - ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx; if (!rSchedCtx.mpSalTimer) { rSchedCtx.mnTimerStart = 0; @@ -228,10 +282,14 @@ bool Scheduler::ProcessTaskScheduling() { ImplSVData *pSVData = ImplGetSVData(); ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx; - sal_uInt64 nTime = tools::Time::GetSystemTicks(); - if ( pSVData->mbDeInit || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod ) + + DBG_TESTSOLARMUTEX(); + + SchedulerGuard aSchedulerGuard; + if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod ) return false; + sal_uInt64 nTime = tools::Time::GetSystemTicks(); if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod ) { SAL_WARN( "vcl.schedule", "we're too early - restart the timer!" ); @@ -326,7 +384,9 @@ next_entry: // 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; + sal_uInt32 nLockCount = Unlock( true ); pTask->Invoke(); + Lock( nLockCount ); pMostUrgent->mbInScheduler = false; SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " " @@ -379,12 +439,12 @@ void Task::SetDeletionFlags() void Task::Start() { ImplSVData *const pSVData = ImplGetSVData(); - if (pSVData->mbDeInit) - { - return; - } ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx; + SchedulerGuard aSchedulerGuard; + if ( !rSchedCtx.mbActive ) + return; + // Mark timer active mbActive = true; @@ -448,6 +508,7 @@ Task::Task( const Task& rTask ) Task::~Task() { + SchedulerGuard aSchedulerGuard; if ( mpSchedulerData ) mpSchedulerData->mpTask = nullptr; } diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 41e6377c752d..db69f9847bb2 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -519,6 +519,13 @@ bool Application::Reschedule( bool i_bAllEvents ) void Scheduler::ProcessEventsToIdle() { int nSanity = 1; +#if OSL_DEBUG_LEVEL > 0 + const ImplSVData* pSVData = ImplGetSVData(); + bool bIsMainThread = pSVData->mpDefInst->IsMainThread(); + bool mbLocked = false; + if ( bIsMainThread ) + mbLocked = Scheduler::Lock(); +#endif while( Application::Reschedule( true ) ) { if (0 == ++nSanity % 1000) @@ -530,10 +537,9 @@ void Scheduler::ProcessEventsToIdle() // If we yield from a non-main thread we just can guarantee that all idle // events were processed at some point, but our check can't prevent further // processing in the main thread, which may add new events, so skip it. - const ImplSVData* pSVData = ImplGetSVData(); - if ( !pSVData->mpDefInst->IsMainThread() ) + if ( !bIsMainThread ) return; - const ImplSchedulerData* pSchedulerData = ImplGetSVData()->maSchedCtx.mpFirstSchedulerData; + const ImplSchedulerData* pSchedulerData = pSVData->maSchedCtx.mpFirstSchedulerData; bool bAnyIdle = false; while ( pSchedulerData ) { @@ -543,12 +549,14 @@ void Scheduler::ProcessEventsToIdle() if ( pIdle && pIdle->IsActive() ) { bAnyIdle = true; - SAL_WARN( "vcl.schedule", "Unprocessed Idle: " << pIdle->GetDebugName() ); + SAL_WARN( "vcl.schedule", "Unprocessed Idle: " << pIdle->GetDebugName() ); } } pSchedulerData = pSchedulerData->mpNext; } assert( !bAnyIdle ); + if ( mbLocked ) + Scheduler::Unlock(); #endif } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits