From ec94926665ef70fdd2c0901e104b43f8bea8b888 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Thu, 16 Jan 2020 15:56:52 +0200 Subject: Use std::vector in OInterfaceContainerHelper instead of Sequence instead of fighting the fact that Sequence is intended to be immutable getSequence() will become a little slower, but since getSequence() is called 5k times during 'make check', while add/remove are called 3M times, I think it's safe to say mutation is dominant. Change-Id: I23d127c93c589050d6c06c0da47871e1ebe7b52d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86929 Tested-by: Jenkins Reviewed-by: Noel Grandin --- cppuhelper/source/interfacecontainer.cxx | 87 ++++++++++++-------------------- 1 file changed, 31 insertions(+), 56 deletions(-) (limited to 'cppuhelper') diff --git a/cppuhelper/source/interfacecontainer.cxx b/cppuhelper/source/interfacecontainer.cxx index a496b93fc372..38cca295755b 100644 --- a/cppuhelper/source/interfacecontainer.cxx +++ b/cppuhelper/source/interfacecontainer.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -36,24 +37,6 @@ using namespace com::sun::star::lang; namespace cppu { -/** - * Remove an element from an interface sequence. - */ -static void sequenceRemoveElementAt( Sequence< Reference< XInterface > > & rSeq, sal_Int32 index ) -{ - sal_Int32 nNewLen = rSeq.getLength() - 1; - - Sequence< Reference< XInterface > > aDestSeq( rSeq.getLength() - 1 ); - // getArray on a const sequence is faster - const Reference< XInterface > * pSource = rSeq.getConstArray(); - Reference< XInterface > * pDest = aDestSeq.getArray(); - sal_Int32 i = 0; - for( ; i < index; i++ ) - pDest[i] = pSource[i]; - for( sal_Int32 j = i ; j < nNewLen; j++ ) - pDest[j] = pSource[j+1]; - rSeq = aDestSeq; -} OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper & rCont_ ) : rCont( rCont_ ) @@ -67,7 +50,7 @@ OInterfaceIteratorHelper::OInterfaceIteratorHelper( OInterfaceContainerHelper & if( bIsList ) { rCont.bInUse = true; - nRemain = aData.pAsSequence->getLength(); + nRemain = aData.pAsVector->size(); } else if( aData.pAsInterface ) { @@ -84,7 +67,7 @@ OInterfaceIteratorHelper::~OInterfaceIteratorHelper() { MutexGuard aGuard( rCont.rMutex ); // bResetInUse protect the iterator against recursion - bShared = aData.pAsSequence == rCont.aData.pAsSequence && rCont.bIsList; + bShared = aData.pAsVector == rCont.aData.pAsVector && rCont.bIsList; if( bShared ) { OSL_ENSURE( rCont.bInUse, "OInterfaceContainerHelper must be in use" ); @@ -96,7 +79,7 @@ OInterfaceIteratorHelper::~OInterfaceIteratorHelper() { if( bIsList ) // Sequence owned by the iterator - delete aData.pAsSequence; + delete aData.pAsVector; else if( aData.pAsInterface ) // Interface is acquired by the iterator aData.pAsInterface->release(); @@ -110,7 +93,7 @@ XInterface * OInterfaceIteratorHelper::next() nRemain--; if( bIsList ) // typecase to const,so the getArray method is faster - return aData.pAsSequence->getConstArray()[nRemain].get(); + return (*aData.pAsVector)[nRemain].get(); if( aData.pAsInterface ) return aData.pAsInterface; } @@ -123,8 +106,8 @@ void OInterfaceIteratorHelper::remove() if( bIsList ) { OSL_ASSERT( nRemain >= 0 && - nRemain < aData.pAsSequence->getLength() ); - XInterface * p = aData.pAsSequence->getConstArray()[nRemain].get(); + nRemain < static_cast(aData.pAsVector->size()) ); + XInterface * p = (*aData.pAsVector)[nRemain].get(); rCont.removeInterface( * reinterpret_cast< const Reference< XInterface > * >( &p ) ); } else @@ -145,7 +128,7 @@ OInterfaceContainerHelper::~OInterfaceContainerHelper() { OSL_ENSURE( !bInUse, "~OInterfaceContainerHelper but is in use" ); if( bIsList ) - delete aData.pAsSequence; + delete aData.pAsVector; else if( aData.pAsInterface ) aData.pAsInterface->release(); } @@ -154,7 +137,7 @@ sal_Int32 OInterfaceContainerHelper::getLength() const { MutexGuard aGuard( rMutex ); if( bIsList ) - return aData.pAsSequence->getLength(); + return aData.pAsVector->size(); if( aData.pAsInterface ) return 1; return 0; @@ -164,7 +147,7 @@ Sequence< Reference > OInterfaceContainerHelper::getElements() const { MutexGuard aGuard( rMutex ); if( bIsList ) - return *aData.pAsSequence; + return comphelper::containerToSequence(*aData.pAsVector); if( aData.pAsInterface ) { Reference x( aData.pAsInterface ); @@ -181,7 +164,7 @@ void OInterfaceContainerHelper::copyAndResetInUse() // this should be the worst case. If an iterator is active // and a new Listener is added. if( bIsList ) - aData.pAsSequence = new Sequence< Reference< XInterface > >( *aData.pAsSequence ); + aData.pAsVector= new std::vector< Reference< XInterface > >( *aData.pAsVector ); else if( aData.pAsInterface ) aData.pAsInterface->acquire(); @@ -198,19 +181,16 @@ sal_Int32 OInterfaceContainerHelper::addInterface( const Reference & if( bIsList ) { - sal_Int32 nLen = aData.pAsSequence->getLength(); - aData.pAsSequence->realloc( nLen +1 ); - aData.pAsSequence->getArray()[ nLen ] = rListener; - return nLen +1; + aData.pAsVector->push_back(rListener); + return aData.pAsVector->size(); } if( aData.pAsInterface ) { - Sequence< Reference< XInterface > > * pSeq = new Sequence< Reference< XInterface > >( 2 ); - Reference * pArray = pSeq->getArray(); - pArray[0] = aData.pAsInterface; - pArray[1] = rListener; + Reference tmp(aData.pAsInterface); aData.pAsInterface->release(); - aData.pAsSequence = pSeq; + aData.pAsVector = new std::vector>(2); + (*aData.pAsVector)[0] = std::move(tmp); + (*aData.pAsVector)[1] = rListener; bIsList = true; return 2; } @@ -229,42 +209,37 @@ sal_Int32 OInterfaceContainerHelper::removeInterface( const Reference * pL = aData.pAsSequence->getConstArray(); - sal_Int32 nLen = aData.pAsSequence->getLength(); - sal_Int32 i; - for( i = 0; i < nLen; i++ ) + // It is not valid to compare the pointer directly, but it's faster. + auto findIt = std::find_if(aData.pAsVector->begin(), aData.pAsVector->end(), + [&](const Reference& r) + { return r.get() == rListener.get(); }); + if (findIt != aData.pAsVector->end()) { - // It is not valid to compare the pointer directly, but it's faster. - if( pL[i].get() == rListener.get() ) - { - sequenceRemoveElementAt( *aData.pAsSequence, i ); - break; - } + aData.pAsVector->erase(findIt); } - - if( i == nLen ) + else { // interface not found, use the correct compare method - for( i = 0; i < nLen; i++ ) + for( auto it = aData.pAsVector->begin(); it != aData.pAsVector->end(); ++it ) { - if( pL[i] == rListener ) + if( *it == rListener ) { - sequenceRemoveElementAt(*aData.pAsSequence, i ); + aData.pAsVector->erase(it); break; } } } - if( aData.pAsSequence->getLength() == 1 ) + if( aData.pAsVector->size() == 1 ) { - XInterface * p = aData.pAsSequence->getConstArray()[0].get(); + XInterface * p = (*aData.pAsVector)[0].get(); p->acquire(); - delete aData.pAsSequence; + delete aData.pAsVector; aData.pAsInterface = p; bIsList = false; return 1; } - return aData.pAsSequence->getLength(); + return aData.pAsVector->size(); } if( aData.pAsInterface && Reference( aData.pAsInterface ) == rListener ) { -- cgit