summaryrefslogtreecommitdiffstats
path: root/comphelper
diff options
context:
space:
mode:
authorNoel Grandin <noelgrandin@gmail.com>2016-01-19 19:45:45 +0200
committerNoel Grandin <noel@peralex.com>2016-01-25 08:52:03 +0200
commit752cd07d085ac0aadc99bd512d49072843139032 (patch)
tree21ff2f55761b34bfdd721b5e1ed43333e8874e46 /comphelper
parenttdf#86567 Dropdown for conditional formatting (diff)
downloadcore-752cd07d085ac0aadc99bd512d49072843139032.tar.gz
core-752cd07d085ac0aadc99bd512d49072843139032.zip
InterfaceContainer2 with vector instead of Sequence
create an InterfaceContainer2 class to replace InterfaceContainer. It uses a std::vector instead of a Sequence for the mutable listener list, which provides far better performance. Switch all our internal use-sites to the new class. Change-Id: I6b56cfa511ded2395faa22e68fab3b2f16c3cb88
Diffstat (limited to 'comphelper')
-rw-r--r--comphelper/CppunitTest_comphelper_ifcontainer.mk29
-rw-r--r--comphelper/CppunitTest_comphelper_test.mk1
-rw-r--r--comphelper/Library_comphelper.mk1
-rw-r--r--comphelper/Module_comphelper.mk1
-rw-r--r--comphelper/qa/container/comphelper_ifcontainer.cxx212
-rw-r--r--comphelper/qa/container/testifcontainer.cxx145
-rw-r--r--comphelper/source/container/interfacecontainer2.cxx307
-rw-r--r--comphelper/source/eventattachermgr/eventattachermgr.cxx8
-rw-r--r--comphelper/source/misc/accessibleeventnotifier.cxx19
-rw-r--r--comphelper/source/misc/instancelocker.cxx2
-rw-r--r--comphelper/source/misc/instancelocker.hxx4
-rw-r--r--comphelper/source/misc/listenernotification.cxx4
-rw-r--r--comphelper/source/property/opropertybag.hxx3
13 files changed, 715 insertions, 21 deletions
diff --git a/comphelper/CppunitTest_comphelper_ifcontainer.mk b/comphelper/CppunitTest_comphelper_ifcontainer.mk
new file mode 100644
index 000000000000..d336c5546ab2
--- /dev/null
+++ b/comphelper/CppunitTest_comphelper_ifcontainer.mk
@@ -0,0 +1,29 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,comphelper_ifcontainer))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,comphelper_ifcontainer,\
+ comphelper/qa/container/comphelper_ifcontainer \
+))
+
+$(eval $(call gb_CppunitTest_use_api,comphelper_ifcontainer,\
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,comphelper_ifcontainer,\
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ $(gb_UWINAPI) \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/comphelper/CppunitTest_comphelper_test.mk b/comphelper/CppunitTest_comphelper_test.mk
index 89e071044ed7..47843c6ba8ad 100644
--- a/comphelper/CppunitTest_comphelper_test.mk
+++ b/comphelper/CppunitTest_comphelper_test.mk
@@ -11,6 +11,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,comphelper_test))
$(eval $(call gb_CppunitTest_add_exception_objects,comphelper_test, \
comphelper/qa/string/test_string \
+ comphelper/qa/container/testifcontainer \
))
$(eval $(call gb_CppunitTest_use_api,comphelper_test, \
diff --git a/comphelper/Library_comphelper.mk b/comphelper/Library_comphelper.mk
index 6f2cc4c8f137..155d293b600e 100644
--- a/comphelper/Library_comphelper.mk
+++ b/comphelper/Library_comphelper.mk
@@ -60,6 +60,7 @@ $(eval $(call gb_Library_add_exception_objects,comphelper,\
comphelper/source/container/NamedPropertyValuesContainer \
comphelper/source/container/container \
comphelper/source/container/containermultiplexer \
+ comphelper/source/container/interfacecontainer2 \
comphelper/source/container/embeddedobjectcontainer \
comphelper/source/container/enumerablemap \
comphelper/source/container/enumhelper \
diff --git a/comphelper/Module_comphelper.mk b/comphelper/Module_comphelper.mk
index acd50c6827be..2eba43df73f8 100644
--- a/comphelper/Module_comphelper.mk
+++ b/comphelper/Module_comphelper.mk
@@ -30,6 +30,7 @@ $(eval $(call gb_Module_add_subsequentcheck_targets,comphelper,\
$(eval $(call gb_Module_add_check_targets,comphelper,\
CppunitTest_comphelper_syntaxhighlight_test \
CppunitTest_comphelper_variadictemplates_test \
+ CppunitTest_comphelper_ifcontainer \
CppunitTest_comphelper_test \
))
diff --git a/comphelper/qa/container/comphelper_ifcontainer.cxx b/comphelper/qa/container/comphelper_ifcontainer.cxx
new file mode 100644
index 000000000000..ba9af495eaf0
--- /dev/null
+++ b/comphelper/qa/container/comphelper_ifcontainer.cxx
@@ -0,0 +1,212 @@
+/* -*- 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 <sal/types.h>
+
+#include <string.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <com/sun/star/lang/XEventListener.hpp>
+#include <comphelper/interfacecontainer2.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+
+class ContainerListener;
+
+struct ContainerStats {
+ int m_nAlive;
+ int m_nDisposed;
+ ContainerStats() : m_nAlive(0), m_nDisposed(0) {}
+};
+
+class ContainerListener : public ::cppu::WeakImplHelper1< XEventListener >
+{
+ ContainerStats *m_pStats;
+public:
+ explicit ContainerListener(ContainerStats *pStats)
+ : m_pStats(pStats) { m_pStats->m_nAlive++; }
+ virtual ~ContainerListener() { m_pStats->m_nAlive--; }
+ virtual void SAL_CALL disposing( const EventObject& )
+ throw (RuntimeException, std::exception) override
+ {
+ m_pStats->m_nDisposed++;
+ }
+};
+
+namespace comphelper_ifcontainer
+{
+ static const int nTests = 10;
+ class IfTest : public CppUnit::TestFixture
+ {
+ osl::Mutex m_aGuard;
+ public:
+ void testCreateDispose()
+ {
+ ContainerStats aStats;
+ comphelper::OInterfaceContainerHelper2 *pContainer;
+
+ pContainer = new comphelper::OInterfaceContainerHelper2(m_aGuard);
+
+ CPPUNIT_ASSERT_MESSAGE("Empty container not empty",
+ pContainer->getLength() == 0);
+
+ int i;
+ for (i = 0; i < nTests; i++)
+ {
+ Reference<XEventListener> xRef = new ContainerListener(&aStats);
+ int nNewLen = pContainer->addInterface(xRef);
+
+ CPPUNIT_ASSERT_MESSAGE("addition length mismatch",
+ nNewLen == i + 1);
+ CPPUNIT_ASSERT_MESSAGE("addition length mismatch",
+ pContainer->getLength() == i + 1);
+ }
+ CPPUNIT_ASSERT_MESSAGE("alive count mismatch",
+ aStats.m_nAlive == nTests);
+
+ EventObject aObj;
+ pContainer->disposeAndClear(aObj);
+
+ CPPUNIT_ASSERT_MESSAGE("dispose count mismatch",
+ aStats.m_nDisposed == nTests);
+ CPPUNIT_ASSERT_MESSAGE("leaked container left alive",
+ aStats.m_nAlive == 0);
+
+ delete pContainer;
+ }
+
+ void testEnumerate()
+ {
+ int i;
+ ContainerStats aStats;
+ comphelper::OInterfaceContainerHelper2 *pContainer;
+ pContainer = new comphelper::OInterfaceContainerHelper2(m_aGuard);
+
+ std::vector< Reference< XEventListener > > aListeners;
+ for (i = 0; i < nTests; i++)
+ {
+ Reference<XEventListener> xRef = new ContainerListener(&aStats);
+ pContainer->addInterface(xRef);
+ aListeners.push_back(xRef);
+ }
+ std::vector< Reference< XInterface > > aElements = pContainer->getElements();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("query contents",
+ (int)aElements.size(), nTests);
+ if ((int)aElements.size() == nTests)
+ {
+ for (i = 0; i < nTests; i++)
+ {
+ CPPUNIT_ASSERT_MESSAGE("mismatching elements",
+ aElements[i] == aListeners[i]);
+ }
+ }
+ pContainer->clear();
+
+ CPPUNIT_ASSERT_MESSAGE("non-empty container post clear",
+ pContainer->getLength() == 0);
+ delete pContainer;
+ }
+
+ template < typename ContainerType, typename ContainedType >
+ void doContainerTest(const ContainedType *pTypes)
+ {
+ ContainerStats aStats;
+ ContainerType *pContainer;
+ pContainer = new ContainerType(m_aGuard);
+
+ int i;
+ Reference<XEventListener> xRefs[nTests * 2];
+
+ // add these interfaces
+ for (i = 0; i < nTests * 2; i++)
+ {
+ xRefs[i] = new ContainerListener(&aStats);
+ pContainer->addInterface(pTypes[i / 2], xRefs[i]);
+ }
+
+ // check it is all there
+ for (i = 0; i < nTests; i++)
+ {
+ cppu::OInterfaceContainerHelper *pHelper;
+
+ pHelper = pContainer->getContainer(pTypes[i]);
+
+ CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != nullptr);
+ Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
+ CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 2);
+ CPPUNIT_ASSERT_MESSAGE("match", aSeq[0] == xRefs[i*2]);
+ CPPUNIT_ASSERT_MESSAGE("match", aSeq[1] == xRefs[i*2+1]);
+ }
+
+ // remove every other interface
+ for (i = 0; i < nTests; i++)
+ pContainer->removeInterface(pTypes[i], xRefs[i*2+1]);
+
+ // check it is half there
+ for (i = 0; i < nTests; i++)
+ {
+ cppu::OInterfaceContainerHelper *pHelper;
+
+ pHelper = pContainer->getContainer(pTypes[i]);
+
+ CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != nullptr);
+ Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
+ CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 1);
+ CPPUNIT_ASSERT_MESSAGE("match", aSeq[0] == xRefs[i*2]);
+ }
+
+ // remove the 1st half of the rest
+ for (i = 0; i < nTests / 2; i++)
+ pContainer->removeInterface(pTypes[i], xRefs[i*2]);
+
+ // check it is half there
+ for (i = 0; i < nTests / 2; i++)
+ {
+ cppu::OInterfaceContainerHelper *pHelper;
+
+ pHelper = pContainer->getContainer(pTypes[i]);
+ CPPUNIT_ASSERT_MESSAGE("no helper", pHelper != nullptr);
+ Sequence<Reference< XInterface > > aSeq = pHelper->getElements();
+ CPPUNIT_ASSERT_MESSAGE("wrong num elements", aSeq.getLength() == 0);
+ }
+
+ delete pContainer;
+ }
+
+ // Automatic registration code
+ CPPUNIT_TEST_SUITE(IfTest);
+ CPPUNIT_TEST(testCreateDispose);
+ CPPUNIT_TEST(testEnumerate);
+ CPPUNIT_TEST_SUITE_END();
+ };
+} // namespace cppu_ifcontainer
+
+CPPUNIT_TEST_SUITE_REGISTRATION(comphelper_ifcontainer::IfTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/comphelper/qa/container/testifcontainer.cxx b/comphelper/qa/container/testifcontainer.cxx
new file mode 100644
index 000000000000..7533695640d0
--- /dev/null
+++ b/comphelper/qa/container/testifcontainer.cxx
@@ -0,0 +1,145 @@
+/* -*- 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 <osl/mutex.hxx>
+
+#include <cppuhelper/interfacecontainer.hxx>
+#include <cppuhelper/implbase1.hxx>
+
+#include <com/sun/star/beans/XVetoableChangeListener.hpp>
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+
+
+class TestListener : public WeakImplHelper1< XVetoableChangeListener >
+{
+public:
+ // Methods
+ virtual void SAL_CALL disposing( const css::lang::EventObject& /*Source*/ ) throw(css::uno::RuntimeException)
+ {
+
+ }
+
+ virtual void SAL_CALL vetoableChange( const css::beans::PropertyChangeEvent& /*aEvent*/ )
+ throw(css::beans::PropertyVetoException, css::uno::RuntimeException)
+ {
+
+ }
+};
+
+void test_interfacecontainer()
+{
+ Mutex mutex;
+
+ {
+ OInterfaceContainerHelper helper( mutex );
+
+ Reference< XVetoableChangeListener > r1 = new TestListener();
+ Reference< XVetoableChangeListener > r2 = new TestListener();
+ Reference< XVetoableChangeListener > r3 = new TestListener();
+
+ helper.addInterface( r1 );
+ helper.addInterface( r2 );
+ helper.addInterface( r3 );
+
+ helper.disposeAndClear( EventObject() );
+ }
+
+ {
+ OInterfaceContainerHelper helper( mutex );
+
+ Reference< XVetoableChangeListener > r1 = new TestListener();
+ Reference< XVetoableChangeListener > r2 = new TestListener();
+ Reference< XVetoableChangeListener > r3 = new TestListener();
+
+ helper.addInterface( r1 );
+ helper.addInterface( r2 );
+ helper.addInterface( r3 );
+
+ OInterfaceIteratorHelper iterator( helper );
+
+ while( iterator.hasMoreElements() )
+ ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
+
+ helper.disposeAndClear( EventObject() );
+ }
+
+ {
+ OInterfaceContainerHelper helper( mutex );
+
+ Reference< XVetoableChangeListener > r1 = new TestListener();
+ Reference< XVetoableChangeListener > r2 = new TestListener();
+ Reference< XVetoableChangeListener > r3 = new TestListener();
+
+ helper.addInterface( r1 );
+ helper.addInterface( r2 );
+ helper.addInterface( r3 );
+
+ OInterfaceIteratorHelper iterator( helper );
+
+ ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
+ iterator.remove();
+ ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
+ iterator.remove();
+ ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
+ iterator.remove();
+
+ OSL_ASSERT( helper.getLength() == 0 );
+ helper.disposeAndClear( EventObject() );
+ }
+
+ {
+ OInterfaceContainerHelper helper( mutex );
+
+ Reference< XVetoableChangeListener > r1 = new TestListener();
+ Reference< XVetoableChangeListener > r2 = new TestListener();
+ Reference< XVetoableChangeListener > r3 = new TestListener();
+
+ helper.addInterface( r1 );
+ helper.addInterface( r2 );
+ helper.addInterface( r3 );
+
+ {
+ OInterfaceIteratorHelper iterator( helper );
+ while( iterator.hasMoreElements() )
+ {
+ Reference< XVetoableChangeListener > r = ((XVetoableChangeListener*)iterator.next());
+ if( r == r1 )
+ iterator.remove();
+ }
+ }
+ OSL_ASSERT( helper.getLength() == 2 );
+ {
+ OInterfaceIteratorHelper iterator( helper );
+ while( iterator.hasMoreElements() )
+ {
+ Reference< XVetoableChangeListener > r = ((XVetoableChangeListener*)iterator.next());
+ OSL_ASSERT( r != r1 && ( r == r2 || r == r3 ) );
+ }
+ }
+
+ helper.disposeAndClear( EventObject() );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/comphelper/source/container/interfacecontainer2.cxx b/comphelper/source/container/interfacecontainer2.cxx
new file mode 100644
index 000000000000..90f4e01b476e
--- /dev/null
+++ b/comphelper/source/container/interfacecontainer2.cxx
@@ -0,0 +1,307 @@
+/* -*- 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 <cppuhelper/interfacecontainer.hxx>
+#include <comphelper/interfacecontainer2.hxx>
+#include <cppuhelper/queryinterface.hxx>
+#include <cppuhelper/propshlp.hxx>
+
+#include <osl/diagnose.h>
+#include <osl/mutex.hxx>
+
+#include <memory>
+
+#include <com/sun/star/lang/XEventListener.hpp>
+
+
+using namespace osl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+
+namespace comphelper
+{
+
+OInterfaceIteratorHelper2::OInterfaceIteratorHelper2( OInterfaceContainerHelper2 & rCont_ )
+ : rCont( rCont_ )
+{
+ MutexGuard aGuard( rCont.rMutex );
+ if( rCont.bInUse )
+ // worst case, two iterators at the same time
+ rCont.copyAndResetInUse();
+ bIsList = rCont_.bIsList;
+ aData = rCont_.aData;
+ if( bIsList )
+ {
+ rCont.bInUse = true;
+ nRemain = aData.pAsVector->size();
+ }
+ else if( aData.pAsInterface )
+ {
+ aData.pAsInterface->acquire();
+ nRemain = 1;
+ }
+ else
+ nRemain = 0;
+}
+
+OInterfaceIteratorHelper2::~OInterfaceIteratorHelper2()
+{
+ bool bShared;
+ {
+ MutexGuard aGuard( rCont.rMutex );
+ // bResetInUse protect the iterator against recursion
+ bShared = aData.pAsVector == rCont.aData.pAsVector && rCont.bIsList;
+ if( bShared )
+ {
+ OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper2 must be in use" );
+ rCont.bInUse = false;
+ }
+ }
+
+ if( !bShared )
+ {
+ if( bIsList )
+ // Sequence owned by the iterator
+ delete aData.pAsVector;
+ else if( aData.pAsInterface )
+ // Interface is acquired by the iterator
+ aData.pAsInterface->release();
+ }
+}
+
+XInterface * OInterfaceIteratorHelper2::next()
+{
+ if( nRemain )
+ {
+ nRemain--;
+ if( bIsList )
+ return (*aData.pAsVector)[nRemain].get();
+ else if( aData.pAsInterface )
+ return aData.pAsInterface;
+ }
+ // exception
+ return nullptr;
+}
+
+void OInterfaceIteratorHelper2::remove()
+{
+ if( bIsList )
+ {
+ OSL_ASSERT( nRemain >= 0 &&
+ nRemain < (sal_Int32)aData.pAsVector->size() );
+ rCont.removeInterface( (*aData.pAsVector)[nRemain] );
+ }
+ else
+ {
+ OSL_ASSERT( 0 == nRemain );
+ rCont.removeInterface( aData.pAsInterface );
+ }
+}
+
+OInterfaceContainerHelper2::OInterfaceContainerHelper2( Mutex & rMutex_ )
+ : rMutex( rMutex_ )
+ , bInUse( false )
+ , bIsList( false )
+{
+}
+
+OInterfaceContainerHelper2::~OInterfaceContainerHelper2()
+{
+ OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper2 but is in use" );
+ if( bIsList )
+ delete aData.pAsVector;
+ else if( aData.pAsInterface )
+ aData.pAsInterface->release();
+}
+
+sal_Int32 OInterfaceContainerHelper2::getLength() const
+{
+ MutexGuard aGuard( rMutex );
+ if( bIsList )
+ return aData.pAsVector->size();
+ else if( aData.pAsInterface )
+ return 1;
+ return 0;
+}
+
+std::vector< Reference<XInterface> > OInterfaceContainerHelper2::getElements() const
+{
+ std::vector< Reference<XInterface> > rVec;
+ MutexGuard aGuard( rMutex );
+ if( bIsList )
+ rVec = *aData.pAsVector;
+ else if( aData.pAsInterface )
+ {
+ rVec.push_back( Reference<XInterface>( aData.pAsInterface ) );
+ }
+ return rVec;
+}
+
+void OInterfaceContainerHelper2::copyAndResetInUse()
+{
+ OSL_ENSURE( bInUse, "OInterfaceContainerHelper2 not in use" );
+ if( bInUse )
+ {
+ // this should be the worst case. If a iterator is active
+ // and a new Listener is added.
+ if( bIsList )
+ aData.pAsVector = new std::vector< Reference< XInterface > >( *aData.pAsVector );
+ else if( aData.pAsInterface )
+ aData.pAsInterface->acquire();
+
+ bInUse = false;
+ }
+}
+
+sal_Int32 OInterfaceContainerHelper2::addInterface( const Reference<XInterface> & rListener )
+{
+ OSL_ASSERT( rListener.is() );
+ MutexGuard aGuard( rMutex );
+ if( bInUse )
+ copyAndResetInUse();
+
+ if( bIsList )
+ {
+ aData.pAsVector->push_back( rListener );
+ return aData.pAsVector->size();
+ }
+ else if( aData.pAsInterface )
+ {
+ std::vector< Reference< XInterface > > * pVec = new std::vector< Reference< XInterface > >( 2 );
+ (*pVec)[0] = aData.pAsInterface;
+ (*pVec)[1] = rListener;
+ aData.pAsInterface->release();
+ aData.pAsVector = pVec;
+ bIsList = true;
+ return 2;
+ }
+ else
+ {
+ aData.pAsInterface = rListener.get();
+ if( rListener.is() )
+ rListener->acquire();
+ return 1;
+ }
+}
+
+sal_Int32 OInterfaceContainerHelper2::removeInterface( const Reference<XInterface> & rListener )
+{
+ OSL_ASSERT( rListener.is() );
+ MutexGuard aGuard( rMutex );
+ if( bInUse )
+ copyAndResetInUse();
+
+ if( bIsList )
+ {
+ sal_Int32 nLen = aData.pAsVector->size();
+ sal_Int32 i;
+ for( i = 0; i < nLen; i++ )
+ {
+ // It is not valid to compare the pointer directly, but it's faster.
+ if( (*aData.pAsVector)[i].get() == rListener.get() )
+ {
+ aData.pAsVector->erase(aData.pAsVector->begin()+i);
+ break;
+ }
+ }
+
+ // interface not found, use the correct compare method
+ if( i == nLen )
+ {
+ for( i = 0; i < nLen; i++ )
+ {
+ if( (*aData.pAsVector)[i] == rListener )
+ {
+ aData.pAsVector->erase(aData.pAsVector->begin()+i);
+ break;
+ }
+ }
+ }
+
+ if( aData.pAsVector->size() == 1 )
+ {
+ XInterface * p = (*aData.pAsVector)[0].get();
+ p->acquire();
+ delete aData.pAsVector;
+ aData.pAsInterface = p;
+ bIsList = false;
+ return 1;
+ }
+ else
+ return aData.pAsVector->size();
+ }
+ else if( aData.pAsInterface && Reference<XInterface>( aData.pAsInterface ) == rListener )
+ {
+ aData.pAsInterface->release();
+ aData.pAsInterface = nullptr;
+ }
+ return aData.pAsInterface ? 1 : 0;
+}
+
+void OInterfaceContainerHelper2::disposeAndClear( const EventObject & rEvt )
+{
+ ClearableMutexGuard aGuard( rMutex );
+ OInterfaceIteratorHelper2 aIt( *this );
+ // Release container, in case new entries come while disposing
+ OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper2 not in use" );
+ if( !bIsList && aData.pAsInterface )
+ aData.pAsInterface->release();
+ // set the member to null, use the iterator to delete the values
+ aData.pAsInterface = nullptr;
+ bIsList = false;
+ bInUse = false;
+ aGuard.clear();
+ while( aIt.hasMoreElements() )
+ {
+ try
+ {
+ Reference<XEventListener > xLst( aIt.next(), UNO_QUERY );
+ if( xLst.is() )
+ xLst->disposing( rEvt );
+ }
+ catch ( RuntimeException & )
+ {
+ // be robust, if e.g. a remote bridge has disposed already.
+ // there is no way to delegate the error to the caller :o(.
+ }
+ }
+}
+
+
+void OInterfaceContainerHelper2::clear()
+{
+ ClearableMutexGuard aGuard( rMutex );
+ OInterfaceIteratorHelper2 aIt( *this );
+ // Release container, in case new entries come while disposing
+ OSL_ENSURE( !bIsList || bInUse, "OInterfaceContainerHelper2 not in use" );
+ if( !bIsList && aData.pAsInterface )
+ aData.pAsInterface->release();
+ // set the member to null, use the iterator to delete the values
+ aData.pAsInterface = nullptr;
+ bIsList = false;
+ bInUse = false;
+ // release mutex before aIt destructor call
+ aGuard.clear();
+}
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/comphelper/source/eventattachermgr/eventattachermgr.cxx b/comphelper/source/eventattachermgr/eventattachermgr.cxx
index 0717ea136130..2f2fb5d03883 100644
--- a/comphelper/source/eventattachermgr/eventattachermgr.cxx
+++ b/comphelper/source/eventattachermgr/eventattachermgr.cxx
@@ -40,7 +40,7 @@
#include <com/sun/star/script/XEventAttacherManager.hpp>
#include <com/sun/star/script/XScriptListener.hpp>
#include <cppuhelper/weak.hxx>
-#include <cppuhelper/interfacecontainer.hxx>
+#include <comphelper/interfacecontainer2.hxx>
#include <cppuhelper/implbase.hxx>
#include <deque>
@@ -82,7 +82,7 @@ class ImplEventAttacherManager
::std::deque< AttacherIndex_Impl > aIndex;
Mutex aLock;
// Container for the ScriptListener
- OInterfaceContainerHelper aScriptListeners;
+ OInterfaceContainerHelper2 aScriptListeners;
// Instance of EventAttacher
Reference< XEventAttacher2 > xAttacher;
Reference< XComponentContext > mxContext;
@@ -193,7 +193,7 @@ void SAL_CALL AttacherAllListener_Impl::firing(const AllEventObject& Event)
aScriptEvent.ScriptCode = aScriptCode;
// Iterate over all listeners and pass events.
- OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
+ OInterfaceIteratorHelper2 aIt( mpManager->aScriptListeners );
while( aIt.hasMoreElements() )
static_cast<XScriptListener *>(aIt.next())->firing( aScriptEvent );
}
@@ -259,7 +259,7 @@ Any SAL_CALL AttacherAllListener_Impl::approveFiring( const AllEventObject& Even
Any aRet;
// Iterate over all listeners and pass events.
- OInterfaceIteratorHelper aIt( mpManager->aScriptListeners );
+ OInterfaceIteratorHelper2 aIt( mpManager->aScriptListeners );
while( aIt.hasMoreElements() )
{
aRet = static_cast<XScriptListener *>(aIt.next())->approveFiring( aScriptEvent );
diff --git a/comphelper/source/misc/accessibleeventnotifier.cxx b/comphelper/source/misc/accessibleeventnotifier.cxx
index 0d2cb848d34d..348fb555941a 100644
--- a/comphelper/source/misc/accessibleeventnotifier.cxx
+++ b/comphelper/source/misc/accessibleeventnotifier.cxx
@@ -20,7 +20,7 @@
#include <comphelper/accessibleeventnotifier.hxx>
#include <osl/diagnose.h>
#include <rtl/instance.hxx>
-#include <cppuhelper/interfacecontainer.h>
+#include <comphelper/interfacecontainer2.hxx>
#include <comphelper/guarding.hxx>
#include <map>
@@ -37,7 +37,7 @@ namespace
AccessibleEventObject > ClientEvent;
typedef ::std::map< AccessibleEventNotifier::TClientId,
- ::cppu::OInterfaceContainerHelper*,
+ ::comphelper::OInterfaceContainerHelper2*,
::std::less< AccessibleEventNotifier::TClientId > > ClientMap;
/// key is the end of the interval, value is the start of the interval
@@ -153,8 +153,8 @@ namespace comphelper
TClientId nNewClientId = generateId( );
// the event listeners for the new client
- ::cppu::OInterfaceContainerHelper *const pNewListeners =
- new ::cppu::OInterfaceContainerHelper( lclMutex::get() );
+ ::comphelper::OInterfaceContainerHelper2 *const pNewListeners =
+ new ::comphelper::OInterfaceContainerHelper2( lclMutex::get() );
// note that we're using our own mutex here, so the listener containers for all
// our clients share this same mutex.
// this is a reminiscence to the days where the notifier was asynchronous. Today this is
@@ -187,7 +187,7 @@ namespace comphelper
void AccessibleEventNotifier::revokeClientNotifyDisposing( const TClientId _nClient,
const Reference< XInterface >& _rxEventSource )
{
- ::cppu::OInterfaceContainerHelper* pListeners(nullptr);
+ ::comphelper::OInterfaceContainerHelper2* pListeners(nullptr);
{
// rhbz#1001768 drop the mutex before calling disposeAndClear
@@ -255,7 +255,7 @@ namespace comphelper
void AccessibleEventNotifier::addEvent( const TClientId _nClient, const AccessibleEventObject& _rEvent )
{
- Sequence< Reference< XInterface > > aListeners;
+ std::vector< Reference< XInterface > > aListeners;
// --- <mutex lock> -------------------------------
{
@@ -272,20 +272,17 @@ namespace comphelper
// --- </mutex lock> ------------------------------
// default handling: loop through all listeners, and notify them
- const Reference< XInterface >* pListeners = aListeners.getConstArray();
- const Reference< XInterface >* pListenersEnd = pListeners + aListeners.getLength();
- while ( pListeners != pListenersEnd )
+ for ( const auto& rListener : aListeners )
{
try
{
- static_cast< XAccessibleEventListener* >( pListeners->get() )->notifyEvent( _rEvent );
+ static_cast< XAccessibleEventListener* >( rListener.get() )->notifyEvent( _rEvent );
}
catch( const Exception& )
{
// no assertion, because a broken access remote bridge or something like this
// can cause this exception
}
- ++pListeners;
}
}
diff --git a/comphelper/source/misc/instancelocker.cxx b/comphelper/source/misc/instancelocker.cxx
index 131efb7e2935..01937dd4c95b 100644
--- a/comphelper/source/misc/instancelocker.cxx
+++ b/comphelper/source/misc/instancelocker.cxx
@@ -104,7 +104,7 @@ void SAL_CALL OInstanceLocker::addEventListener( const uno::Reference< lang::XEv
throw lang::DisposedException(); // TODO
if ( !m_pListenersContainer )
- m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex );
+ m_pListenersContainer = new ::comphelper::OInterfaceContainerHelper2( m_aMutex );
m_pListenersContainer->addInterface( xListener );
}
diff --git a/comphelper/source/misc/instancelocker.hxx b/comphelper/source/misc/instancelocker.hxx
index de9064d280a9..3ac86e534715 100644
--- a/comphelper/source/misc/instancelocker.hxx
+++ b/comphelper/source/misc/instancelocker.hxx
@@ -31,7 +31,7 @@
#include <cppuhelper/weakref.hxx>
#include <osl/mutex.hxx>
#include <cppuhelper/implbase.hxx>
-#include <cppuhelper/interfacecontainer.h>
+#include <comphelper/interfacecontainer2.hxx>
class OLockListener;
@@ -47,7 +47,7 @@ class OInstanceLocker : public ::cppu::WeakImplHelper< css::lang::XComponent,
css::uno::Reference< css::uno::XInterface > m_xLockListener;
OLockListener* m_pLockListener;
- ::cppu::OInterfaceContainerHelper* m_pListenersContainer; // list of listeners
+ ::comphelper::OInterfaceContainerHelper2* m_pListenersContainer; // list of listeners
bool m_bDisposed;
bool m_bInitialized;
diff --git a/comphelper/source/misc/listenernotification.cxx b/comphelper/source/misc/listenernotification.cxx
index 7dc4332ff43e..5c0c56de2458 100644
--- a/comphelper/source/misc/listenernotification.cxx
+++ b/comphelper/source/misc/listenernotification.cxx
@@ -48,7 +48,7 @@ namespace comphelper
void OListenerContainer::impl_removeListener( const Reference< XEventListener >& _rxListener )
{
#if OSL_DEBUG_LEVEL > 0
- ::cppu::OInterfaceIteratorHelper aIter( m_aListeners );
+ ::comphelper::OInterfaceIteratorHelper2 aIter( m_aListeners );
bool bFound = false;
while ( aIter.hasMoreElements() && !bFound )
{
@@ -74,7 +74,7 @@ namespace comphelper
bool OListenerContainer::impl_notify( const EventObject& _rEvent )
{
- ::cppu::OInterfaceIteratorHelper aIter( m_aListeners );
+ ::comphelper::OInterfaceIteratorHelper2 aIter( m_aListeners );
bool bCancelled = false;
while ( aIter.hasMoreElements() && !bCancelled )
{
diff --git a/comphelper/source/property/opropertybag.hxx b/comphelper/source/property/opropertybag.hxx
index a939ded5ea38..e2246f4a39cb 100644
--- a/comphelper/source/property/opropertybag.hxx
+++ b/comphelper/source/property/opropertybag.hxx
@@ -30,6 +30,7 @@
#include <boost/noncopyable.hpp>
#include <cppuhelper/implbase5.hxx>
+#include <comphelper/interfacecontainer2.hxx>
#include <comphelper/propstate.hxx>
#include <comphelper/broadcasthelper.hxx>
#include <comphelper/propertybag.hxx>
@@ -84,7 +85,7 @@ namespace comphelper
bool m_bAutoAddProperties;
/// for notification
- ::cppu::OInterfaceContainerHelper m_NotifyListeners;
+ ::comphelper::OInterfaceContainerHelper2 m_NotifyListeners;
/// modify flag
bool m_isModified;