From a2eaf99e46f370ffb3b73828c2bdc53dc193b9a4 Mon Sep 17 00:00:00 2001
From: Noel Grandin <noel.grandin@collabora.co.uk>
Date: Fri, 14 Jan 2022 10:56:50 +0200
Subject: make comphelper::OInterfaceContainerHelper4 more threadsafe

(*) make all the methods that require an external mutex take a
std::unique_lock as a parameter, so that call sites cannot forget

(*) make the forEach method drop the lock when firing listener methods,
to reduce the odds of deadlock

Change-Id: I0a80e3b3d1c1c03b7de4a658d31fcc2847690903
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128415
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
---
 include/comphelper/multiinterfacecontainer4.hxx | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

(limited to 'include/comphelper/multiinterfacecontainer4.hxx')

diff --git a/include/comphelper/multiinterfacecontainer4.hxx b/include/comphelper/multiinterfacecontainer4.hxx
index 5d2457669f0d..eeccd20920ca 100644
--- a/include/comphelper/multiinterfacecontainer4.hxx
+++ b/include/comphelper/multiinterfacecontainer4.hxx
@@ -43,13 +43,13 @@ public:
     /**
       Return all id's under which at least one interface is added.
      */
-    inline std::vector<key> getContainedTypes() const
+    inline std::vector<key> getContainedTypes(std::unique_lock<std::mutex>& rGuard) const
     {
         std::vector<key> aInterfaceTypes;
         aInterfaceTypes.reserve(m_aMap.size());
         for (const auto& rPair : m_aMap)
             // are interfaces added to this container?
-            if (rPair.second->getLength())
+            if (rPair.second->getLength(rGuard))
                 // yes, put the type in the array
                 aInterfaceTypes.push_back(rPair.first);
         return aInterfaceTypes;
@@ -91,17 +91,18 @@ public:
         @return
                 the new count of elements in the container
     */
-    inline sal_Int32 addInterface(const key& rKey, const css::uno::Reference<listener>& rListener)
+    inline sal_Int32 addInterface(::std::unique_lock<::std::mutex>& rGuard, const key& rKey,
+                                  const css::uno::Reference<listener>& rListener)
     {
         auto iter = find(rKey);
         if (iter == m_aMap.end())
         {
             auto pLC = new OInterfaceContainerHelper4<listener>();
             m_aMap.emplace_back(rKey, pLC);
-            return pLC->addInterface(rListener);
+            return pLC->addInterface(rGuard, rListener);
         }
         else
-            return (*iter).second->addInterface(rListener);
+            return (*iter).second->addInterface(rGuard, rListener);
     }
     /** Removes an element from the container with the specified key.
         It uses interface equality to remove the interface.
@@ -112,14 +113,14 @@ public:
         @return
                 the new count of elements in the container
     */
-    inline sal_Int32 removeInterface(const key& rKey,
+    inline sal_Int32 removeInterface(::std::unique_lock<::std::mutex>& rGuard, const key& rKey,
                                      const css::uno::Reference<listener>& rListener)
     {
         // search container with id nUik
         auto iter = find(rKey);
         // container found?
         if (iter != m_aMap.end())
-            return (*iter).second->removeInterface(rListener);
+            return (*iter).second->removeInterface(rGuard, rListener);
         // no container with this id. Always return 0
         return 0;
     }
@@ -139,7 +140,7 @@ public:
         rGuard.unlock();
         for (auto& rPair : tempMap)
         {
-            OInterfaceIteratorHelper4<listener> aIt(*rPair.second);
+            OInterfaceIteratorHelper4<listener> aIt(rGuard, *rPair.second);
             while (aIt.hasMoreElements())
             {
                 try
-- 
cgit