summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2023-02-22 10:19:02 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2023-02-22 12:43:55 +0000
commit7cfe7f23efb97f6b42dcb1589b3d66d4b881092d (patch)
tree290e0da9d56aef151ee28722b713de55d8629c71
parent1f49d8ad7a520975f611023f77f3fc9c0e32ed77 (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.mk1
-rw-r--r--comphelper/source/property/propmultiplex2.cxx149
-rw-r--r--include/comphelper/propmultiplex2.hxx115
-rw-r--r--svx/source/form/tabwin.cxx16
-rw-r--r--svx/source/inc/tabwin.hxx8
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);