diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-02-22 10:19:02 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2023-02-22 12:43:55 +0000 |
commit | 7cfe7f23efb97f6b42dcb1589b3d66d4b881092d (patch) | |
tree | 290e0da9d56aef151ee28722b713de55d8629c71 | |
parent | 1f49d8ad7a520975f611023f77f3fc9c0e32ed77 (diff) |
create new OPropertyChangeListener2 and use it in FmFieldWin
create OPropertyChangeListener2 as a modified copy of
OPropertyChangeListener which uses std::mutex instead of osl::Mutex
Change-Id: Ic6be1c62992749e4f0dd23a8c95de63dc45eba3d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147430
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
-rw-r--r-- | comphelper/Library_comphelper.mk | 1 | ||||
-rw-r--r-- | comphelper/source/property/propmultiplex2.cxx | 149 | ||||
-rw-r--r-- | include/comphelper/propmultiplex2.hxx | 115 | ||||
-rw-r--r-- | svx/source/form/tabwin.cxx | 16 | ||||
-rw-r--r-- | svx/source/inc/tabwin.hxx | 8 |
5 files changed, 279 insertions, 10 deletions
diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk index b6d1d7e39ccf..5238cb65e968 100644 --- a/comphelper/Library_comphelper.mk +++ b/comphelper/Library_comphelper.mk @@ -154,6 +154,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\ comphelper/source/property/propertysetinfo \ comphelper/source/property/propertystatecontainer \ comphelper/source/property/propmultiplex \ + comphelper/source/property/propmultiplex2 \ comphelper/source/property/propstate \ comphelper/source/streaming/basicio \ comphelper/source/streaming/memorystream \ diff --git a/comphelper/source/property/propmultiplex2.cxx b/comphelper/source/property/propmultiplex2.cxx new file mode 100644 index 000000000000..72e801524de8 --- /dev/null +++ b/comphelper/source/property/propmultiplex2.cxx @@ -0,0 +1,149 @@ +/* -*- 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 <com/sun/star/beans/XPropertySet.hpp> +#include <comphelper/propmultiplex2.hxx> +#include <osl/diagnose.h> + +namespace comphelper +{ +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; + +OPropertyChangeListener2::~OPropertyChangeListener2() +{ + if (m_xAdapter.is()) + m_xAdapter->onListenerDestruction(); +} + +void OPropertyChangeListener2::_disposing(const EventObject&) +{ + // nothing to do here +} + +void OPropertyChangeListener2::disposeAdapter(std::unique_lock<std::mutex>& rGuard) +{ + if (m_xAdapter.is()) + m_xAdapter->dispose(rGuard); + + // will automatically set a new adapter + OSL_ENSURE(!m_xAdapter.is(), "OPropertyChangeListener::disposeAdapter: what did dispose do?"); +} + +void OPropertyChangeListener2::setAdapter(std::unique_lock<std::mutex>& /*rGuard*/, + OPropertyChangeMultiplexer2* pAdapter) +{ + m_xAdapter = pAdapter; +} + +OPropertyChangeMultiplexer2::OPropertyChangeMultiplexer2(std::mutex& rMutex, + std::unique_lock<std::mutex>& rGuard, + OPropertyChangeListener2* _pListener, + const Reference<XPropertySet>& _rxSet, + bool _bAutoReleaseSet) + : m_rMutex(rMutex) + , m_xSet(_rxSet) + , m_pListener(_pListener) + , m_nLockCount(0) + , m_bListening(false) + , m_bAutoSetRelease(_bAutoReleaseSet) +{ + m_pListener->setAdapter(rGuard, this); +} + +OPropertyChangeMultiplexer2::~OPropertyChangeMultiplexer2() {} + +void OPropertyChangeMultiplexer2::lock() { ++m_nLockCount; } + +void OPropertyChangeMultiplexer2::unlock() { --m_nLockCount; } + +void OPropertyChangeMultiplexer2::dispose(std::unique_lock<std::mutex>& rGuard) +{ + if (!m_bListening) + return; + + Reference<XPropertyChangeListener> xPreventDelete(this); + + for (const OUString& rProp : m_aProperties) + m_xSet->removePropertyChangeListener(rProp, static_cast<XPropertyChangeListener*>(this)); + + m_pListener->setAdapter(rGuard, nullptr); + + m_pListener = nullptr; + m_bListening = false; + + if (m_bAutoSetRelease) + m_xSet = nullptr; +} + +void OPropertyChangeMultiplexer2::onListenerDestruction() +{ + if (!m_bListening) + return; + + Reference<XPropertyChangeListener> xPreventDelete(this); + + for (const OUString& rProp : m_aProperties) + m_xSet->removePropertyChangeListener(rProp, static_cast<XPropertyChangeListener*>(this)); +} + +// XEventListener + +void SAL_CALL OPropertyChangeMultiplexer2::disposing(const EventObject& _rSource) +{ + std::unique_lock g(m_rMutex); + if (m_pListener) + { + // tell the listener + if (!locked()) + m_pListener->_disposing(_rSource); + // disconnect the listener + if (m_pListener) // may have been reset whilst calling into _disposing + m_pListener->setAdapter(g, nullptr); + } + + m_pListener = nullptr; + m_bListening = false; + + if (m_bAutoSetRelease) + m_xSet = nullptr; +} + +// XPropertyChangeListener + +void SAL_CALL OPropertyChangeMultiplexer2::propertyChange(const PropertyChangeEvent& _rEvent) +{ + if (m_pListener && !locked()) + m_pListener->_propertyChanged(_rEvent); +} + +void OPropertyChangeMultiplexer2::addProperty(const OUString& _sPropertyName) +{ + if (m_xSet.is()) + { + m_xSet->addPropertyChangeListener(_sPropertyName, + static_cast<XPropertyChangeListener*>(this)); + m_aProperties.push_back(_sPropertyName); + m_bListening = true; + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/propmultiplex2.hxx b/include/comphelper/propmultiplex2.hxx new file mode 100644 index 000000000000..3c3c5065945e --- /dev/null +++ b/include/comphelper/propmultiplex2.hxx @@ -0,0 +1,115 @@ +/* -*- 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 . + */ +#pragma once + +#include <com/sun/star/beans/XPropertyChangeListener.hpp> +#include <cppuhelper/implbase.hxx> +#include <comphelper/comphelperdllapi.h> +#include <rtl/ref.hxx> +#include <mutex> +#include <vector> + +namespace com::sun::star::beans +{ +class XPropertySet; +} + +//= property helper classes + +namespace comphelper +{ +class OPropertyChangeMultiplexer2; + +//= OPropertyChangeListener + +/// simple listener adapter for property sets +class COMPHELPER_DLLPUBLIC OPropertyChangeListener2 +{ + friend class OPropertyChangeMultiplexer2; + + rtl::Reference<OPropertyChangeMultiplexer2> m_xAdapter; + +public: + virtual ~OPropertyChangeListener2(); + + /// @throws css::uno::RuntimeException + virtual void _propertyChanged(const css::beans::PropertyChangeEvent& _rEvent) = 0; + /// @throws css::uno::RuntimeException + virtual void _disposing(const css::lang::EventObject& _rSource); + +protected: + /** If the derivee also owns the mutex which we know as reference, then call this within your + derivee's dtor. + */ + void disposeAdapter(std::unique_lock<std::mutex>& rGuard); + +private: + void setAdapter(std::unique_lock<std::mutex>& rGuard, OPropertyChangeMultiplexer2* _pAdapter); +}; + +//= OPropertyChangeMultiplexer2 +// A copy of OPropertyChangeMultiplexer except that it uses std::mutex instead osl::Mutex + +/// multiplexer for property changes +// workaround for incremental linking bugs in MSVC2019 +class SAL_DLLPUBLIC_TEMPLATE OPropertyChangeMultiplexer_Base2 + : public cppu::WeakImplHelper<css::beans::XPropertyChangeListener> +{ +}; +class COMPHELPER_DLLPUBLIC OPropertyChangeMultiplexer2 final + : public OPropertyChangeMultiplexer_Base2 +{ + friend class OPropertyChangeListener2; + std::mutex& m_rMutex; + std::vector<OUString> m_aProperties; + css::uno::Reference<css::beans::XPropertySet> m_xSet; + OPropertyChangeListener2* m_pListener; + sal_Int32 m_nLockCount; + bool m_bListening : 1; + bool const m_bAutoSetRelease : 1; + + void onListenerDestruction(); + virtual ~OPropertyChangeMultiplexer2() override; + +public: + OPropertyChangeMultiplexer2(std::mutex& rMutex, std::unique_lock<std::mutex>& rGuard, + OPropertyChangeListener2* _pListener, + const css::uno::Reference<css::beans::XPropertySet>& _rxSet, + bool _bAutoReleaseSet = true); + + // XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; + + // XPropertyChangeListener + virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override; + + /// incremental lock + void lock(); + /// incremental unlock + void unlock(); + /// get the lock count + sal_Int32 locked() const { return m_nLockCount; } + + void addProperty(const OUString& aPropertyName); + void dispose(std::unique_lock<std::mutex>& rGuard); +}; + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/form/tabwin.cxx b/svx/source/form/tabwin.cxx index 91322b45fc3c..4c534ef7c35b 100644 --- a/svx/source/form/tabwin.cxx +++ b/svx/source/form/tabwin.cxx @@ -112,7 +112,7 @@ IMPL_LINK(FmFieldWin, DragBeginHdl, bool&, rUnsetDragIcon, bool) FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, weld::Window* _pParent) : SfxModelessDialogController(_pBindings, _pMgr, _pParent, "svx/ui/formfielddialog.ui", "FormFieldDialog") , SfxControllerItem(SID_FM_FIELDS_CONTROL, *_pBindings) - , comphelper::OPropertyChangeListener(m_aMutex) + , comphelper::OPropertyChangeListener2() , m_xListBox(m_xBuilder->weld_tree_view("treeview")) , m_nObjectType(0) { @@ -133,10 +133,13 @@ FmFieldWin::FmFieldWin(SfxBindings* _pBindings, SfxChildWindow* _pMgr, weld::Win FmFieldWin::~FmFieldWin() { - if (m_xChangeListener.is()) { - m_xChangeListener->dispose(); - m_xChangeListener.clear(); + std::unique_lock g(m_aMutex); + if (m_xChangeListener.is()) + { + m_xChangeListener->dispose(g); + m_xChangeListener.clear(); + } } ::SfxControllerItem::dispose(); } @@ -265,12 +268,13 @@ void FmFieldWin::UpdateContent(const css::uno::Reference< css::form::XForm > & x } // listen for changes at ControlSource in PropertySet + std::unique_lock g(m_aMutex); if (m_xChangeListener.is()) { - m_xChangeListener->dispose(); + m_xChangeListener->dispose(g); m_xChangeListener.clear(); } - m_xChangeListener = new ::comphelper::OPropertyChangeMultiplexer(this, xSet); + m_xChangeListener = new ::comphelper::OPropertyChangeMultiplexer2(m_aMutex, g, this, xSet); m_xChangeListener->addProperty(FM_PROP_DATASOURCE); m_xChangeListener->addProperty(FM_PROP_COMMAND); m_xChangeListener->addProperty(FM_PROP_COMMANDTYPE); diff --git a/svx/source/inc/tabwin.hxx b/svx/source/inc/tabwin.hxx index c1cf70664bcc..0209f3d31654 100644 --- a/svx/source/inc/tabwin.hxx +++ b/svx/source/inc/tabwin.hxx @@ -25,7 +25,7 @@ #include <svx/dbaexchange.hxx> #include <com/sun/star/form/XForm.hpp> -#include <comphelper/propmultiplex.hxx> +#include <comphelper/propmultiplex2.hxx> #include <connectivity/dbtools.hxx> class FmFormShell; @@ -33,9 +33,9 @@ struct ColumnInfo; class FmFieldWin final : public SfxModelessDialogController , public SfxControllerItem - , public ::comphelper::OPropertyChangeListener + , public ::comphelper::OPropertyChangeListener2 { - ::osl::Mutex m_aMutex; + std::mutex m_aMutex; std::unique_ptr<weld::TreeView> m_xListBox; std::vector<std::unique_ptr<ColumnInfo>> m_aListBoxData; ::dbtools::SharedConnection @@ -44,7 +44,7 @@ class FmFieldWin final : public SfxModelessDialogController m_aObjectName; sal_Int32 m_nObjectType; - rtl::Reference<comphelper::OPropertyChangeMultiplexer> m_xChangeListener; + rtl::Reference<comphelper::OPropertyChangeMultiplexer2> m_xChangeListener; rtl::Reference<svx::OColumnTransferable> m_xHelper; void addToList(const css::uno::Reference<css::container::XNameAccess>& i_xColumns); |