diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-10-12 15:42:59 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-10-16 09:54:13 +0200 |
commit | 8a2f7704cd0e43304e54bf2281232335cc0979a3 (patch) | |
tree | a8357d52e613dbff7bd4b6097f75be6871863ce6 | |
parent | 7dc9fb33db45c269fece6cfec993b124491c68f6 (diff) |
drop LazyDeletor
Change-Id: I7d2e00466f321994a46b0529d645e342f229c929
Reviewed-on: https://gerrit.libreoffice.org/61718
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | framework/source/uielement/toolbarmanager.cxx | 9 | ||||
-rw-r--r-- | include/vcl/lazydelete.hxx | 152 | ||||
-rw-r--r-- | include/vcl/window.hxx | 8 | ||||
-rw-r--r-- | svtools/source/uno/popupwindowcontroller.cxx | 3 | ||||
-rw-r--r-- | vcl/README.lifecycle | 2 | ||||
-rw-r--r-- | vcl/source/app/svapp.cxx | 11 | ||||
-rw-r--r-- | vcl/source/helper/lazydelete.cxx | 35 | ||||
-rw-r--r-- | vcl/source/window/menu.cxx | 8 | ||||
-rw-r--r-- | vcl/source/window/menubarwindow.cxx | 4 | ||||
-rw-r--r-- | vcl/source/window/menufloatingwindow.cxx | 4 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 14 | ||||
-rw-r--r-- | vcl/source/window/window2.cxx | 4 |
12 files changed, 28 insertions, 226 deletions
diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx index 5ca1bb8daa69..1ee4797d889b 100644 --- a/framework/source/uielement/toolbarmanager.cxx +++ b/framework/source/uielement/toolbarmanager.cxx @@ -232,13 +232,10 @@ void ToolBarManager::Destroy() delete static_cast< AddonsParams* >( m_pToolBar->GetItemData( nItemId )); } - // Hide toolbar as lazy delete can destroy the toolbar much later. - m_pToolBar->Hide(); - // #i93173# delete toolbar lazily as we can still be in one of its handlers // tdf#119390 this will reparent the toolbar, so focus is restored from a // floating toolbar to the last focused control of the application window. - m_pToolBar->doLazyDelete(); - + m_pToolBar->SetParentToDefaultWindow(); + // #i93173# note we can still be in one of the toolbar's handlers m_pToolBar->SetSelectHdl( Link<ToolBox *, void>() ); m_pToolBar->SetActivateHdl( Link<ToolBox *, void>() ); m_pToolBar->SetDeactivateHdl( Link<ToolBox *, void>() ); @@ -248,7 +245,7 @@ void ToolBarManager::Destroy() m_pToolBar->SetStateChangedHdl( Link<StateChangedType const *, void>() ); m_pToolBar->SetDataChangedHdl( Link<DataChangedEvent const *, void>() ); - m_pToolBar.clear(); + m_pToolBar.disposeAndClear(); SvtMiscOptions().RemoveListenerLink( LINK( this, ToolBarManager, MiscOptionsChanged ) ); } diff --git a/include/vcl/lazydelete.hxx b/include/vcl/lazydelete.hxx index 89c88cbf4cc2..f7d74573de66 100644 --- a/include/vcl/lazydelete.hxx +++ b/include/vcl/lazydelete.hxx @@ -35,158 +35,8 @@ namespace vcl { - /* Helpers for lazy object deletion - - With vcl it is often necessary to delete objects (especially Windows) - in the right order as well as in a way ensuring that the deleted objects - are not still on the stack (e.g. deleting a Window in its key handler). To - make this easier a helper class is given here which takes care of both - sorting as well as lazy deletion. - - The grisly details: - LazyDelete is a class that LazyDeletor register to. When vcl's event - loop (that is Application::Yield or Application::Reschedule) comes out - of the last level, the LazyDelete::flush is called. This will cause - LazyDelete to delete all registered LazyDeletor objects. - - LazyDeletor<T> is a one instance object that contains a list of - <T> objects to be deleted in sorted order. It is derived from - LazyDeletorBase as to be able to register itself in LazyDelete. - - The user calls the static method LazyDeletor<T>::Delete( T* ) with the - object to be destroyed lazy. The static method creates the LazyDeletor<T> - (which in turn registers itself in LazyDelete) if this is the first time - a T* is to be destroyed lazy. It then inserts the object. When the LazyDeletor<T> - gets delete it will delete the stored objects in a fashion - that will ensure the correct order of deletion via the specialized is_less method - (e.g. if a Window is a child of another Window and therefore should be destroyed - first it is "less" in this sense) - - LazyDelete::flush will be called when the top of the nested event loop is - reached again and will then destroy each registered LazyDeletor<T> which - in turn destroys the objects needed to be destroyed lazily. After this - the state is as before entering the event loop. - - Preconditions: - - The class <T> of which objects are to be destroyed needs a virtual - destructor or must be final, else the wrong type will be destroyed. - - The destructor of <T> should call LazyDeletor<T>::Undelete( this ). This - prevents duplicate deletion in case someone destroys the object prematurely. - */ - - class LazyDeletorBase; - class VCL_DLLPUBLIC LazyDelete - { - public: - /** flush all registered object lists - */ - static void flush(); - /** register an object list to be destroyed - */ - static void addDeletor( LazyDeletorBase* pDeletor ); - }; - - class VCL_DLLPUBLIC LazyDeletorBase - { - friend void LazyDelete::flush(); - protected: - LazyDeletorBase(); - virtual ~LazyDeletorBase(); - }; - - class VCL_DLLPUBLIC LazyDeletor : public LazyDeletorBase - { - static LazyDeletor* s_pOneInstance; - - struct DeleteObjectEntry - { - VclPtr<vcl::Window> m_pObject; - bool m_bDeleted; - - DeleteObjectEntry( vcl::Window* i_pObject ) : - m_pObject( i_pObject ), - m_bDeleted( false ) - {} - }; - - std::vector< DeleteObjectEntry > m_aObjects; - typedef std::unordered_map< sal_IntPtr, unsigned int > PtrToIndexMap; - PtrToIndexMap m_aPtrToIndex; - - /** strict weak ordering function to bring objects to be destroyed lazily - in correct order, e.g. for Window objects children before parents - */ - static bool is_less( vcl::Window const * left, vcl::Window const * right ); - - LazyDeletor() { LazyDelete::addDeletor( this ); } - virtual ~LazyDeletor() override - { - SAL_INFO("vcl.lazydelete", typeid(*this).name() << std::hex << this << " deleted"); - if( s_pOneInstance == this ) // sanity check - s_pOneInstance = nullptr; - - // do the actual work - unsigned int nCount = m_aObjects.size(); - std::vector< VclPtr < vcl::Window > > aRealDelete; - aRealDelete.reserve( nCount ); - for( unsigned int i = 0; i < nCount; i++ ) - { - if( ! m_aObjects[i].m_bDeleted ) - { - aRealDelete.push_back( m_aObjects[i].m_pObject ); - } - } - // sort the vector of objects to be destroyed - std::sort( aRealDelete.begin(), aRealDelete.end(), is_less ); - nCount = aRealDelete.size(); - for( unsigned int n = 0; n < nCount; n++ ) - { - SAL_INFO("vcl.lazydelete", typeid(*this).name() << " deletes object " << aRealDelete[n] << " of type " - << typeid(*aRealDelete[n]).name()); - // check if the object to be deleted is not already destroyed - // as a side effect of a previous lazily destroyed object - if( ! m_aObjects[ m_aPtrToIndex[ reinterpret_cast<sal_IntPtr>(aRealDelete[n].get()) ] ].m_bDeleted ) - aRealDelete[n].disposeAndClear(); - } - } - - public: - /** mark an object for lazy deletion - */ - static void Delete( vcl::Window* i_pObject ) - { - if( s_pOneInstance == nullptr ) - s_pOneInstance = new LazyDeletor(); - - // is this object already in the list ? - // if so mark it as not to be deleted; else insert it - PtrToIndexMap::const_iterator dup = s_pOneInstance->m_aPtrToIndex.find( reinterpret_cast<sal_IntPtr>(i_pObject) ); - if( dup != s_pOneInstance->m_aPtrToIndex.end() ) - { - s_pOneInstance->m_aObjects[ dup->second ].m_bDeleted = false; - } - else - { - s_pOneInstance->m_aPtrToIndex[ reinterpret_cast<sal_IntPtr>(i_pObject) ] = s_pOneInstance->m_aObjects.size(); - s_pOneInstance->m_aObjects.push_back( DeleteObjectEntry( i_pObject ) ); - } - } - /** unmark an object already marked for lazy deletion - */ - static void Undelete( vcl::Window* i_pObject ) - { - if( s_pOneInstance ) - { - PtrToIndexMap::const_iterator it = s_pOneInstance->m_aPtrToIndex.find( reinterpret_cast<sal_IntPtr>(i_pObject) ); - if( it != s_pOneInstance->m_aPtrToIndex.end() ) - s_pOneInstance->m_aObjects[ it->second ].m_bDeleted = true; - } - } - }; - /* - class DeleteOnDeinit matches a similar need as LazyDelete for static objects: - you may not access vcl objects after DeInitVCL has been called this includes their destruction + You may not access vcl objects after DeInitVCL has been called this includes their destruction therefore disallowing the existence of static vcl object like e.g. a static BitmapEx To work around this use DeleteOnDeinit<BitmapEx> which will allow you to have a static object container, that will have its contents destroyed on DeinitVCL. The single drawback is that you need to check on the diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx index 3227d6d6c038..e1c49f44de5a 100644 --- a/include/vcl/window.hxx +++ b/include/vcl/window.hxx @@ -1571,14 +1571,16 @@ public: // a helper method for a Control's Draw method void PaintToDevice( ::OutputDevice* pDevice, const Point& rPos, const Size& rSize ); - /* mark Window for deletion in top of event queue + /* tdf#119390 set parent to default window. Typically for use in advance of destroying + * a floating windows which has the current focus so focus will revert to the main + * document window and not the first widget in the current parent of the floating + * window. */ - void doLazyDelete(); + void SetParentToDefaultWindow(); // Keyboard access functions - /** Query the states of keyboard indicators - Caps Lock, Num Lock and Scroll Lock. Use the following mask to retrieve the state of each indicator: diff --git a/svtools/source/uno/popupwindowcontroller.cxx b/svtools/source/uno/popupwindowcontroller.cxx index 9d5b5c98bbdc..14f1cfc382f5 100644 --- a/svtools/source/uno/popupwindowcontroller.cxx +++ b/svtools/source/uno/popupwindowcontroller.cxx @@ -81,7 +81,8 @@ void PopupWindowControllerImpl::SetFloatingWindow() mpFloatingWindow->RemoveEventListener( LINK( this, PopupWindowControllerImpl, WindowEventListener ) ); // tdf#119390 reparent the window, so focus is restored // to the last focused control of the application window. - mpFloatingWindow->doLazyDelete(); + mpFloatingWindow->SetParentToDefaultWindow(); + mpFloatingWindow.disposeAndClear(); } mpFloatingWindow = mpPopupWindow; mpPopupWindow.clear(); diff --git a/vcl/README.lifecycle b/vcl/README.lifecycle index 732b1908d077..dc6286210780 100644 --- a/vcl/README.lifecycle +++ b/vcl/README.lifecycle @@ -189,7 +189,7 @@ ways and often both. ---------- What remains to be done ? ---------- - * Cleanup DogTags and LazyDelete. + * Cleanup DogTags * Expand the VclPtr pattern to many other less than safe VCL types. diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 2cd32996be86..a43b830ded2b 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -458,10 +458,9 @@ static bool ImplYield(bool i_bWait, bool i_bAllEvents) SAL_INFO("vcl.schedule", "Enter ImplYield: " << (i_bWait ? "wait" : "no wait") << ": " << (i_bAllEvents ? "all events" : "one event")); - // TODO: there's a data race here on WNT only because ImplYield may be - // called without SolarMutex; if we can get rid of LazyDelete (with VclPtr) - // then the only remaining use of mnDispatchLevel is in OSX specific code - // so that would effectively eliminate the race on WNT + // there's a data race here on WNT only because ImplYield may be + // called without SolarMutex; but the only remaining use of mnDispatchLevel + // is in OSX specific code pSVData->maAppData.mnDispatchLevel++; // do not wait for events if application was already quit; in that @@ -473,10 +472,6 @@ static bool ImplYield(bool i_bWait, bool i_bAllEvents) DBG_TESTSOLARMUTEX(); // must be locked on return from Yield - // flush lazy deleted objects - if( pSVData->maAppData.mnDispatchLevel == 0 ) - vcl::LazyDelete::flush(); - SAL_INFO("vcl.schedule", "Leave ImplYield with return " << bProcessedEvent ); return bProcessedEvent; } diff --git a/vcl/source/helper/lazydelete.cxx b/vcl/source/helper/lazydelete.cxx index 05e1eef56d92..05c6a316a789 100644 --- a/vcl/source/helper/lazydelete.cxx +++ b/vcl/source/helper/lazydelete.cxx @@ -25,41 +25,6 @@ namespace vcl { -LazyDeletorBase::LazyDeletorBase() -{ -} - -LazyDeletorBase::~LazyDeletorBase() -{ -} - -// instantiate instance pointer for LazyDeletor<Window> -LazyDeletor* LazyDeletor::s_pOneInstance = nullptr; - -// a list for all LazyeDeletor<T> singletons -static std::vector< LazyDeletorBase* > lcl_aDeletors; - -void LazyDelete::addDeletor( LazyDeletorBase* i_pDel ) -{ - lcl_aDeletors.push_back( i_pDel ); -} - -void LazyDelete::flush() -{ - DBG_TESTSOLARMUTEX(); // must be locked - - unsigned int nCount = lcl_aDeletors.size(); - for( unsigned int i = 0; i < nCount; i++ ) - delete lcl_aDeletors[i]; - lcl_aDeletors.clear(); -} - -// specialized is_less function for Window -bool LazyDeletor::is_less( vcl::Window const * left, vcl::Window const * right ) -{ - return left != right && right->IsChild( left, true ); -} - DeleteOnDeinitBase::~DeleteOnDeinitBase() { ImplSVData* pSVData = ImplGetSVData(); diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index 686694e8e0c0..699ba937ee95 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -2952,8 +2952,8 @@ sal_uInt16 PopupMenu::ImplExecute( const VclPtr<vcl::Window>& pW, const tools::R { pWin->StopExecute(); pWin->doShutdown(); - pWindow->doLazyDelete(); - pWindow = nullptr; + pWindow->SetParentToDefaultWindow(); + pWindow.disposeAndClear(); ImplClosePopupToolBox(pW); ImplFlushPendingSelect(); return nSelectedId; @@ -3013,8 +3013,8 @@ sal_uInt16 PopupMenu::ImplExecute( const VclPtr<vcl::Window>& pW, const tools::R } } pWin->doShutdown(); - pWindow->doLazyDelete(); - pWindow = nullptr; + pWindow->SetParentToDefaultWindow(); + pWindow.disposeAndClear(); ImplClosePopupToolBox(pW); ImplFlushPendingSelect(); } diff --git a/vcl/source/window/menubarwindow.cxx b/vcl/source/window/menubarwindow.cxx index 6fbb4af4eac3..a4c33051046b 100644 --- a/vcl/source/window/menubarwindow.cxx +++ b/vcl/source/window/menubarwindow.cxx @@ -377,8 +377,8 @@ void MenuBarWindow::KillActivePopup() } pActivePopup->ImplGetFloatingWindow()->StopExecute(); pActivePopup->ImplGetFloatingWindow()->doShutdown(); - pActivePopup->pWindow->doLazyDelete(); - pActivePopup->pWindow = nullptr; + pActivePopup->pWindow->SetParentToDefaultWindow(); + pActivePopup->pWindow.disposeAndClear(); } pActivePopup = nullptr; } diff --git a/vcl/source/window/menufloatingwindow.cxx b/vcl/source/window/menufloatingwindow.cxx index 67d6d0ce3a8e..38bb20301bef 100644 --- a/vcl/source/window/menufloatingwindow.cxx +++ b/vcl/source/window/menufloatingwindow.cxx @@ -473,8 +473,8 @@ void MenuFloatingWindow::KillActivePopup( PopupMenu* pThisOnly ) { pPopup->ImplGetFloatingWindow()->StopExecute(); pPopup->ImplGetFloatingWindow()->doShutdown(); - pPopup->pWindow->doLazyDelete(); - pPopup->pWindow = nullptr; + pPopup->pWindow->SetParentToDefaultWindow(); + pPopup->pWindow.disposeAndClear(); Update(); } diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 7f229a94eddc..3c1c0aac5f27 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -571,8 +571,6 @@ void Window::dispose() Window::~Window() { - // FIXME: we should kill all LazyDeletor usage. - vcl::LazyDeletor::Undelete( this ); disposeOnce(); } @@ -1758,16 +1756,10 @@ void Window::ImplNewInputContext() pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext ); } -void Window::doLazyDelete() +void Window::SetParentToDefaultWindow() { - SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(this); - DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(this); - if( pSysWin || ( pDockWin && pDockWin->IsFloatingMode() ) ) - { - Show( false ); - SetParent( ImplGetDefaultWindow() ); - } - vcl::LazyDeletor::Delete( this ); + Show(false); + SetParent(ImplGetDefaultWindow()); } KeyIndicatorState Window::GetIndicatorState() const diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx index a105df5f6e36..45bbfaf7ef9a 100644 --- a/vcl/source/window/window2.cxx +++ b/vcl/source/window/window2.cxx @@ -349,8 +349,8 @@ void Window::EndAutoScroll() pSVData->maWinData.mpAutoScrollWin = nullptr; pSVData->maWinData.mnAutoScrollFlags = StartAutoScrollFlags::NONE; pSVData->maAppData.mpWheelWindow->ImplStop(); - pSVData->maAppData.mpWheelWindow->doLazyDelete(); - pSVData->maAppData.mpWheelWindow = nullptr; + pSVData->maAppData.mpWheelWindow->SetParentToDefaultWindow(); + pSVData->maAppData.mpWheelWindow.disposeAndClear(); } } |