comphelper/Library_comphelper.mk              |    1 
 comphelper/source/property/propmultiplex2.cxx |  149 ++++++++++++++++++++++++++
 include/comphelper/propmultiplex2.hxx         |  115 ++++++++++++++++++++
 svx/source/form/tabwin.cxx                    |   16 +-
 svx/source/inc/tabwin.hxx                     |    8 -
 5 files changed, 279 insertions(+), 10 deletions(-)

New commits:
commit 7cfe7f23efb97f6b42dcb1589b3d66d4b881092d
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Wed Feb 22 10:19:02 2023 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Wed Feb 22 12:43:55 2023 +0000

    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.gran...@collabora.co.uk>

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);

Reply via email to