diff --git a/svl/source/inc/poolio.hxx b/svl/source/inc/poolio.hxx index ffff7a3..1ea90d9 100644 --- a/svl/source/inc/poolio.hxx +++ b/svl/source/inc/poolio.hxx @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -52,6 +53,7 @@ struct SfxPoolVersion_Impl }; typedef std::vector SfxPoolItemArrayBase_Impl; +typedef boost::unordered_set< SfxPoolItem * > SfxPoolItemHashBase_Impl; typedef boost::shared_ptr< SfxPoolVersion_Impl > SfxPoolVersion_ImplPtr; typedef std::deque< SfxPoolVersion_ImplPtr > SfxPoolVersionArr_Impl; @@ -59,6 +61,7 @@ typedef std::deque< SfxPoolVersion_ImplPtr > SfxPoolVersionArr_Impl; struct SfxPoolItemArray_Impl: public SfxPoolItemArrayBase_Impl { size_t nFirstFree; + SfxPoolItemHashBase_Impl maHash; // hack for now ... SfxPoolItemArray_Impl () : nFirstFree( 0 ) diff --git a/svl/source/items/itempool.cxx b/svl/source/items/itempool.cxx index 457b946..494d2b6 100644 --- a/svl/source/items/itempool.cxx +++ b/svl/source/items/itempool.cxx @@ -454,6 +454,7 @@ void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool ) bOK = false; break; } + // FIXME: check hash too ... } } } @@ -710,7 +711,8 @@ const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich SfxPoolItemArrayBase_Impl::iterator ppFree; bool ppFreeIsSet = false; - if ( IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ) ) + bool bIsPoolable = IsItemFlag_Impl( nIndex, SFX_ITEM_POOLABLE ); + if ( bIsPoolable ) { // wenn es ueberhaupt gepoolt ist, koennte es schon drin sein if ( IsPooledItem(&rItem) ) @@ -747,27 +749,11 @@ const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich } } } - else - { - // freien Platz suchen - SfxPoolItemArrayBase_Impl::iterator itr = pItemArr->begin(); - std::advance(itr, pItemArr->nFirstFree); - for (; itr != pItemArr->end(); ++itr) - { - if (!*itr) - { - ppFree = itr; - ppFreeIsSet = true; - break; - } - } - // naechstmoeglichen freien Platz merken - pItemArr->nFirstFree = std::distance(pItemArr->begin(), itr); - } // nicht vorhanden, also im PtrArray eintragen SfxPoolItem* pNewItem = rItem.Clone(pImp->mpMaster); pNewItem->SetWhich(nWhich); + #ifdef DBG_UTIL SFX_ASSERT( rItem.Type() == pNewItem->Type(), nWhich, "unequal types in Put(): no Clone()?" ) if ( !rItem.ISA(SfxSetItem) ) @@ -782,12 +768,20 @@ const SfxPoolItem& SfxItemPool::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich #endif AddRef( *pNewItem, pImp->nInitRefCount ); - if ( ppFreeIsSet == false ) - pItemArr->push_back( pNewItem ); - else + if ( bIsPoolable ) { - DBG_ASSERT( *ppFree == 0, "using surrogate in use" ); - *ppFree = pNewItem; + if ( ppFreeIsSet == false ) + pItemArr->push_back( pNewItem ); + else + { + DBG_ASSERT( *ppFree == 0, "using surrogate in use" ); + *ppFree = pNewItem; + } + } + else // not poolable - whack it into the hash + { + assert(pItemArr.size() == 0); + pItemArr->maHash.insert( pNewItem ); } return *pNewItem; } @@ -841,6 +835,9 @@ void SfxItemPool::Remove( const SfxPoolItem& rItem ) // Item im eigenen Pool suchen SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[nIndex]; SFX_ASSERT( pItemArr, rItem.Which(), "removing Item not in Pool" ); + + if ( pItemArr->maHash.size() == 0 ) + { SfxPoolItemArrayBase_Impl::iterator ppHtArrBeg = pItemArr->begin(), ppHtArrEnd = pItemArr->end(); for (SfxPoolItemArrayBase_Impl::iterator ppHtArr = ppHtArrBeg; ppHtArr != ppHtArrEnd; ++ppHtArr) { @@ -857,7 +854,12 @@ void SfxItemPool::Remove( const SfxPoolItem& rItem ) // ggf. kleinstmoegliche freie Position merken size_t nPos = std::distance(ppHtArrBeg, ppHtArr); if ( pItemArr->nFirstFree > nPos ) + { pItemArr->nFirstFree = nPos; + fprintf (stderr, "%p %p: remove item at pos %d -> nFirstFree '%s' (%s)\n", + this, pItemArr, (int) nPos, typeid(*p).name(), + IsPooledItem(p) ? "pooled" : "not-pooled"); + } //! MI: Hack, solange wir das Problem mit dem Outliner haben //! siehe anderes MI-REF @@ -866,6 +868,24 @@ void SfxItemPool::Remove( const SfxPoolItem& rItem ) return; } } + } + else // the hash ! + { + SfxPoolItemHashBase_Impl::iterator it; + it = pItemArr->maHash.find( const_cast< SfxPoolItem *>( &rItem ) ); + if ( it != pItemArr->maHash.end() ) + { + SfxPoolItem* p = *it; + //! MI: Hack, solange wir das Problem mit dem Outliner haben + //! siehe anderes MI-REF + if ( 0 == p->GetRefCount() && nWhich < 4000 ) + delete p; + pItemArr->maHash.erase( it ); + return; + } + else + fprintf (stderr, "Error - request to remove non-existent foo !\n"); + } // nicht vorhanden SFX_ASSERT( false, rItem.Which(), "removing Item not in Pool" ); @@ -960,8 +980,18 @@ const SfxPoolItem *SfxItemPool::GetItem2(sal_uInt16 nWhich, sal_uInt32 nOfst) co return *(pImp->ppStaticDefaults + GetIndex_Impl(nWhich)); SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[GetIndex_Impl(nWhich)]; - if( pItemArr && nOfst < pItemArr->size() ) - return (*pItemArr)[nOfst]; + if ( pItemArr ) + { + if ( nOfst < pItemArr->maHash.size() ) + { + SfxPoolItemHashBase_Impl::iterator it = pItemArr->maHash.begin(); + std::advance( it, nOfst ); // not the best iteration API in the world ... + return *it; + } + + if( nOfst < pItemArr->size() ) + return (*pItemArr)[nOfst]; // FIXME: URGH - what a hash ... + } return 0; } @@ -979,8 +1009,12 @@ sal_uInt32 SfxItemPool::GetItemCount2(sal_uInt16 nWhich) const } SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[GetIndex_Impl(nWhich)]; - if ( pItemArr ) + if ( pItemArr ) + { + if ( pItemArr->maHash.size() ) + return pItemArr->maHash.size(); return pItemArr->size(); + } return 0; }