compilerplugins/clang/store/staticvar.cxx | 1 cui/source/tabpages/tabarea.cxx | 10 editeng/source/editeng/impedit4.cxx | 8 include/svl/itempool.hxx | 82 +-- include/svl/itemset.hxx | 9 include/svl/poolitem.hxx | 9 sc/inc/fillinfo.hxx | 4 sc/source/core/data/documen9.cxx | 7 sc/source/core/data/document.cxx | 4 sc/source/core/data/document10.cxx | 4 sc/source/core/data/fillinfo.cxx | 15 sc/source/core/data/poolcach.cxx | 2 sc/source/filter/xml/xmlexprt.cxx | 4 sc/source/filter/xml/xmlfonte.cxx | 8 sc/source/ui/view/cellsh1.cxx | 14 sc/source/ui/view/output.cxx | 12 sc/source/ui/view/tabvwshc.cxx | 7 sc/source/ui/view/viewfunc.cxx | 12 sd/source/core/drawdoc2.cxx | 8 sd/source/ui/unoidl/unomodel.cxx | 7 solenv/clang-format/excludelist | 2 svl/CppunitTest_svl_itempool.mk | 34 - svl/Module_svl.mk | 1 svl/qa/unit/items/test_itempool.cxx | 108 --- svl/source/inc/poolio.hxx | 73 -- svl/source/items/itempool.cxx | 734 +++++++++------------------ svl/source/items/itemset.cxx | 276 ++++++---- svl/source/items/poolitem.cxx | 1 svx/source/unodraw/UnoNameItemTable.cxx | 24 svx/source/unodraw/UnoNamespaceMap.cxx | 14 svx/source/unodraw/unomtabl.cxx | 46 + svx/source/unodraw/unoshape.cxx | 4 svx/source/xoutdev/xattr.cxx | 50 + sw/source/core/crsr/crstrvl.cxx | 14 sw/source/core/doc/DocumentFieldsManager.cxx | 7 sw/source/core/doc/doc.cxx | 16 sw/source/core/doc/docbasic.cxx | 4 sw/source/core/doc/docfld.cxx | 12 sw/source/core/doc/docfmt.cxx | 8 sw/source/core/doc/doctxm.cxx | 4 sw/source/core/doc/visiturl.cxx | 4 sw/source/core/docnode/node.cxx | 4 sw/source/core/edit/edfld.cxx | 8 sw/source/core/fields/docufld.cxx | 4 sw/source/core/layout/trvlfrm.cxx | 4 sw/source/core/table/swnewtable.cxx | 4 sw/source/core/table/swtable.cxx | 8 sw/source/core/undo/unattr.cxx | 5 sw/source/core/unocore/unostyle.cxx | 4 sw/source/core/view/vprint.cxx | 7 sw/source/filter/html/htmlflywriter.cxx | 7 sw/source/filter/writer/writer.cxx | 31 - sw/source/filter/ww8/rtfexport.cxx | 25 sw/source/filter/ww8/wrtw8sty.cxx | 4 sw/source/filter/ww8/wrtww8.cxx | 7 sw/source/filter/xml/xmlexp.cxx | 4 sw/source/filter/xml/xmlfonte.cxx | 4 sw/source/uibase/utlui/content.cxx | 10 vcl/win/gdi/gdiimpl.cxx | 2 59 files changed, 806 insertions(+), 999 deletions(-)
New commits: commit ae7807c889c19145f89cec40afac82eee191837c Author: Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de> AuthorDate: Wed Jan 10 20:07:47 2024 +0100 Commit: Armin Le Grand <armin.le.gr...@me.com> CommitDate: Fri Jan 12 12:15:54 2024 +0100 ITEM: No longer register Items at Pool The issue is that the flag RegisteredAtPool at the SfxPoolItem is Pool-dependent: It marks that the Item is registeres at *one* Pool/Model. This makes it Pool-dependent. Due to this there is no way to share Items that need to be registered globally/ in multiple Pools/Models what is one of the goals for optimal sharing. We can also not live without having access to all Items associated with the Pool, due to mechanisms in place like the Surrogate stuff. This again is used for two purposes: (1) Access all Items associated with one Pool/Model, at least that is the assumption. This is not valid since it gets corrupted with a single ItemSet/Holder used that does not host model data, e.g. an open Dialog or the Sidebar (or...). But works in principle. (2) Access extra-Items that are held nowhere and are created using DirectPutItemInPool, e.g. infos for a Dialog. These would need a instance/place to host them, the Pool is (ab)used for that. Both are 'compromizes' (to not use a more bad word) and should not exist. (1) should iterate over the Model and do actions. There are even places that use (1) to *change* Items, by casting them to non-const, even RefCounted ones, so having no control over what all might be changed doing so. Since we talk about ca. 100+ places there is no way to get away from this - I can imagine how this happened: The 'poolable' attr traditionally needed for the old binary format was one day 'used' to not need to iterate over the Model, an API was added to access and this usage was copied. Sigh.. It is even used when ODF is loaded: E.g. the FillStyle is imported from XML, interpreted, and put into an ItemSet. Then it gets set at the XShape using UNO API and a *name* -> that name and the Surrogate mechanism is used to find and set the FillStyle at the Model Object. The FillStyle could probably just be set using UNO API and the data directly. The association between Model/Pool and Item is created by the object hosting the Item, these are ItemSets and ItemHolders. Thus it is possible to register these at the Pool. This allows to iterate and collect the Items associated with the Pool and keep the Surrogate mechanism alive. This is the main change done here. It limits the registrations to Items for which (at the Pool) the NeedsPoolRegistration is set, also Item-independent. Speed is okay, I saw no big changes in my tests here. The registration is just pointers, no ownership or RefCounting needed here. The advantage is that Items get closer to be shared office-wide, they can be referenced by multiple ItemSets (RefCnt) associated with different Pools/Models. NOTE: This is not true for SfxSetItems, these are and will stay Pool-dependent due to their need to a Pool in the contained ItemSet. Note that we have ca. six deivations of SfxSetItem, but ca. 500+ Item derivations, so not too bad. For the usages of Surrogates to change existing, RefCounted Items: These can now at least be changed - if they show up to be problematic - to iterate over the registered ItemSets and change Items there the correct way: Set a changed one at the ItemSet. That also allows Objects to *react* on ItemChanges, there is no way to do that with the existing 'compromize'... UnitTests show that this already works well for SC and SD, but SW has still some issues. I will put this to gerrit now, but there will be additional work. A involved problem is the current DefaultItem handling and the state the Pool implementation is in. E.g. StaticDefaults are not really static, Pools hard-delete the DefaultItems (forcing the RefCnt to zero to not have the destructor complain) and other quirks. Looking at that right now, hoping to get this change done without having to change that too much. I thought about adapting PoolItemTest to this, but it is only related to DirectPutItemInPool which is mostly gone and hopefully completely soon. Nonetheless I adapted that mechanism to use a list of SfxPoolItemHolder at the Pool. That makes it safe and abandons the need for indirect garbage collection removal at the Pool. Change-Id: Ib47f21dafa989202930919eace5f7e9c5632ce96 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161896 Tested-by: Jenkins Reviewed-by: Armin Le Grand <armin.le.gr...@me.com> diff --git a/compilerplugins/clang/store/staticvar.cxx b/compilerplugins/clang/store/staticvar.cxx index 21cbd0f08172..774ab92245bb 100644 --- a/compilerplugins/clang/store/staticvar.cxx +++ b/compilerplugins/clang/store/staticvar.cxx @@ -53,7 +53,6 @@ public: || fn == SRCDIR "/sal/qa/rtl/digest/rtl_digest.cxx" || fn == SRCDIR "/sal/qa/rtl/strings/test_oustring_endswith.cxx" || fn == SRCDIR "/sal/qa/rtl/strings/test_oustring_convert.cxx" - || fn == SRCDIR "/svl/qa/unit/items/test_itempool.cxx" // contains mutable state || fn == SRCDIR "/vcl/unx/generic/dtrans/X11_selection.cxx" || fn == SRCDIR "/sax/qa/cppunit/xmlimport.cxx" diff --git a/cui/source/tabpages/tabarea.cxx b/cui/source/tabpages/tabarea.cxx index 4b50b74b8b68..b4ef7edb6791 100644 --- a/cui/source/tabpages/tabarea.cxx +++ b/cui/source/tabpages/tabarea.cxx @@ -83,7 +83,7 @@ void SvxAreaTabDialog::SavePalettes() if ( pShell ) pShell->PutItem( aColorListItem ); else - mpDrawModel->GetItemPool().DirectPutItemInPool(aColorListItem,SID_COLOR_TABLE); + mpDrawModel->GetItemPool().DirectPutItemInPool(aColorListItem); mpColorList = mpDrawModel->GetColorList(); } if( mpNewGradientList != mpDrawModel->GetGradientList() ) @@ -93,7 +93,7 @@ void SvxAreaTabDialog::SavePalettes() if ( pShell ) pShell->PutItem( aItem ); else - mpDrawModel->GetItemPool().DirectPutItemInPool(aItem,SID_GRADIENT_LIST); + mpDrawModel->GetItemPool().DirectPutItemInPool(aItem); mpGradientList = mpDrawModel->GetGradientList(); } if( mpNewHatchingList != mpDrawModel->GetHatchList() ) @@ -103,7 +103,7 @@ void SvxAreaTabDialog::SavePalettes() if ( pShell ) pShell->PutItem( aItem ); else - mpDrawModel->GetItemPool().DirectPutItemInPool(aItem,SID_HATCH_LIST); + mpDrawModel->GetItemPool().DirectPutItemInPool(aItem); mpHatchingList = mpDrawModel->GetHatchList(); } if( mpNewBitmapList != mpDrawModel->GetBitmapList() ) @@ -113,7 +113,7 @@ void SvxAreaTabDialog::SavePalettes() if ( pShell ) pShell->PutItem( aItem ); else - mpDrawModel->GetItemPool().DirectPutItemInPool(aItem,SID_BITMAP_LIST); + mpDrawModel->GetItemPool().DirectPutItemInPool(aItem); mpBitmapList = mpDrawModel->GetBitmapList(); } if( mpNewPatternList != mpDrawModel->GetPatternList() ) @@ -123,7 +123,7 @@ void SvxAreaTabDialog::SavePalettes() if( pShell ) pShell->PutItem( aItem ); else - mpDrawModel->GetItemPool().DirectPutItemInPool(aItem,SID_PATTERN_LIST); + mpDrawModel->GetItemPool().DirectPutItemInPool(aItem); mpPatternList = mpDrawModel->GetPatternList(); } diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index d63522a555c1..7fa5389475e3 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -306,7 +306,9 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) else if ( nScriptType == 2 ) nWhich = EE_CHAR_FONTINFO_CTL; - for (const SfxPoolItem* pItem : maEditDoc.GetItemPool().GetItemSurrogates(nWhich)) + ItemSurrogates aSurrogates; + maEditDoc.GetItemPool().GetItemSurrogates(aSurrogates, nWhich); + for (const SfxPoolItem* pItem : aSurrogates) { SvxFontItem const*const pFontItem = static_cast<const SvxFontItem*>(pItem); bool bAlreadyExist = false; @@ -390,7 +392,9 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) { aColorList.push_back(rDefault.GetValue()); } - for (const SfxPoolItem* pItem : maEditDoc.GetItemPool().GetItemSurrogates(EE_CHAR_COLOR)) + ItemSurrogates aSurrogates; + maEditDoc.GetItemPool().GetItemSurrogates(aSurrogates, EE_CHAR_COLOR); + for (const SfxPoolItem* pItem : aSurrogates) { auto pColorItem(dynamic_cast<SvxColorItem const*>(pItem)); if (pColorItem && pColorItem->GetValue() != COL_AUTO) // may be null! diff --git a/include/svl/itempool.hxx b/include/svl/itempool.hxx index 2e6c5a9a38d3..0a2153c33267 100644 --- a/include/svl/itempool.hxx +++ b/include/svl/itempool.hxx @@ -29,9 +29,7 @@ #include <unordered_set> #include <o3tl/sorted_vector.hxx> #include <salhelper/simplereferenceobject.hxx> - -class SfxBroadcaster; -struct SfxItemPool_Impl; +#include <svl/SfxBroadcaster.hxx> struct SfxItemInfo { @@ -52,14 +50,17 @@ struct SfxItemInfo bool _bShareable : 1; }; -class SfxItemPool; -typedef std::unordered_set<const SfxPoolItem*> registeredSfxPoolItems; - #ifdef DBG_UTIL SVL_DLLPUBLIC size_t getAllDirectlyPooledSfxPoolItemCount(); SVL_DLLPUBLIC size_t getRemainingDirectlyPooledSfxPoolItemCount(); #endif +typedef std::unordered_set<const SfxItemSet*> registeredSfxItemSets; +class SfxPoolItemHolder; +typedef std::unordered_set<const SfxPoolItemHolder*> registeredSfxPoolItemHolders; +typedef std::unordered_set<SfxPoolItemHolder*> directPutSfxPoolItemHolders; +typedef std::vector<const SfxPoolItem*> ItemSurrogates; + /** Base class for providers of defaults of SfxPoolItems. * * The derived classes hold the concrete (const) instances which are referenced in several places @@ -69,21 +70,33 @@ SVL_DLLPUBLIC size_t getRemainingDirectlyPooledSfxPoolItemCount(); */ class SVL_DLLPUBLIC SfxItemPool : public salhelper::SimpleReferenceObject { - friend struct SfxItemPool_Impl; friend class SfxItemSet; + friend class SfxPoolItemHolder; friend class SfxAllItemSet; // allow ItemSetTooling to access friend SfxPoolItem const* implCreateItemEntry(SfxItemPool&, SfxPoolItem const*, sal_uInt16, bool); - friend void implCleanupItemEntry(SfxItemPool&, SfxPoolItem const*); + friend void implCleanupItemEntry(SfxPoolItem const*); // unit testing friend class PoolItemTest; const SfxItemInfo* pItemInfos; - std::unique_ptr<SfxItemPool_Impl> pImpl; - - registeredSfxPoolItems** ppRegisteredSfxPoolItems; + SfxBroadcaster aBC; + OUString aName; + std::vector<SfxPoolItem*> maPoolDefaults; + std::vector<SfxPoolItem*>* mpStaticDefaults; + SfxItemPool* mpMaster; + rtl::Reference<SfxItemPool> mpSecondary; + WhichRangesContainer mpPoolRanges; + sal_uInt16 mnStart; + sal_uInt16 mnEnd; + MapUnit eDefMetric; + + registeredSfxItemSets maRegisteredSfxItemSets; + registeredSfxPoolItemHolders maRegisteredSfxPoolItemHolders; + directPutSfxPoolItemHolders maDirectPutItems; + bool mbPreDeleteDone; private: sal_uInt16 GetIndex_Impl(sal_uInt16 nWhich) const; @@ -94,6 +107,14 @@ private: SVL_DLLPRIVATE bool Shareable_Impl(sal_uInt16 nPos) const { return pItemInfos[nPos]._bShareable; } + void registerItemSet(SfxItemSet& rSet); + void unregisterItemSet(SfxItemSet& rSet); + + void registerPoolItemHolder(SfxPoolItemHolder& rHolder); + void unregisterPoolItemHolder(SfxPoolItemHolder& rHolder); + + void CollectSurrogates(std::unordered_set<const SfxPoolItem*>& rTarget, sal_uInt16 nWhich) const; + public: // for default SfxItemSet::CTOR, set default WhichRanges void FillItemIdRanges_Impl( WhichRangesContainer& pWhichRanges ) const; @@ -112,7 +133,6 @@ public: const SfxItemInfo *pItemInfos, std::vector<SfxPoolItem*> *pDefaults = nullptr ); -public: virtual ~SfxItemPool(); SfxBroadcaster& BC(); @@ -167,34 +187,24 @@ public: virtual rtl::Reference<SfxItemPool> Clone() const; const OUString& GetName() const; - template<class T> const T& DirectPutItemInPool( std::unique_ptr<T> xItem, sal_uInt16 nWhich = 0 ) - { return static_cast<const T&>(DirectPutItemInPoolImpl( *xItem.release(), nWhich, /*bPassingOwnership*/true)); } - template<class T> const T& DirectPutItemInPool( const T& rItem, sal_uInt16 nWhich = 0 ) - { return static_cast<const T&>(DirectPutItemInPoolImpl( rItem, nWhich, /*bPassingOwnership*/false)); } - void DirectRemoveItemFromPool( const SfxPoolItem& ); + const SfxPoolItem& DirectPutItemInPool(const SfxPoolItem&); + void DirectRemoveItemFromPool(const SfxPoolItem&); const SfxPoolItem& GetDefaultItem( sal_uInt16 nWhich ) const; template<class T> const T& GetDefaultItem( TypedWhichId<T> nWhich ) const { return static_cast<const T&>(GetDefaultItem(sal_uInt16(nWhich))); } - - struct Item2Range - { - o3tl::sorted_vector<SfxPoolItem*>::const_iterator m_begin; - o3tl::sorted_vector<SfxPoolItem*>::const_iterator m_end; - o3tl::sorted_vector<SfxPoolItem*>::const_iterator const & begin() const { return m_begin; } - o3tl::sorted_vector<SfxPoolItem*>::const_iterator const & end() const { return m_end; } - }; const SfxPoolItem * GetItem2Default(sal_uInt16 nWhich) const; template<class T> const T* GetItem2Default( TypedWhichId<T> nWhich ) const { return static_cast<const T*>(GetItem2Default(sal_uInt16(nWhich))); } - const registeredSfxPoolItems& GetItemSurrogates(sal_uInt16 nWhich) const; +public: + void GetItemSurrogates(ItemSurrogates& rTarget, sal_uInt16 nWhich) const; /* This is only valid for SfxPoolItem that override IsSortable and operator<. Returns a range of items defined by using operator<. @param rNeedle must be the same type or a supertype of the pool items for nWhich. */ - std::vector<const SfxPoolItem*> FindItemSurrogate(sal_uInt16 nWhich, SfxPoolItem const & rNeedle) const; + void FindItemSurrogate(ItemSurrogates& rTarget, sal_uInt16 nWhich, SfxPoolItem const & rNeedle) const; sal_uInt16 GetFirstWhich() const; sal_uInt16 GetLastWhich() const; @@ -230,24 +240,6 @@ public: static bool IsSlot(sal_uInt16 nId) { return nId && nId > SFX_WHICH_MAX; } - // This method will try to register the Item at this Pool. - void registerSfxPoolItem(const SfxPoolItem& rItem); - - // this method will unregister an Item from this Pool - void unregisterSfxPoolItem(const SfxPoolItem& rItem); - - // check if this Item is registered at this Pool, needed to detect - // if an Item is to be set at another Pool and needs to be cloned - bool isSfxPoolItemRegisteredAtThisPool(const SfxPoolItem& rItem) const; - - // try to find an equal existing Item to given one in pool - const SfxPoolItem* tryToGetEqualItem(const SfxPoolItem& rItem, sal_uInt16 nWhich) const; - - void dumpAsXml(xmlTextWriterPtr pWriter) const; - -protected: - const SfxPoolItem& DirectPutItemInPoolImpl( const SfxPoolItem&, sal_uInt16 nWhich = 0, bool bPassingOwnership = false ); - private: const SfxItemPool& operator=(const SfxItemPool &) = delete; diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx index f3470098d42f..ae97ec991445 100644 --- a/include/svl/itemset.hxx +++ b/include/svl/itemset.hxx @@ -40,7 +40,7 @@ SVL_DLLPUBLIC size_t getUsedSfxPoolItemHolderCount(); // ItemSet/ItemPool helpers SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource, sal_uInt16 nWhich, bool bPassingOwnership); -void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource); +void implCleanupItemEntry(SfxPoolItem const* pSource); class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxPoolItemHolder { @@ -79,11 +79,12 @@ class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet // allow ItemSetTooling to access friend SfxPoolItem const* implCreateItemEntry(SfxItemPool&, SfxPoolItem const*, sal_uInt16, bool); - friend void implCleanupItemEntry(SfxItemPool&, SfxPoolItem const*); + friend void implCleanupItemEntry(SfxPoolItem const*); SfxItemPool* m_pPool; ///< pool that stores the items const SfxItemSet* m_pParent; ///< derivation sal_uInt16 m_nCount; ///< number of items + sal_uInt16 m_nRegister; ///< number of items with NeedsPoolRegistration sal_uInt16 m_nTotalCount; ///< number of WhichIDs, also size of m_ppItems array // bitfield (better packaging if a bool needs to be added) @@ -95,6 +96,10 @@ class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet // Notification-Callback mechanism for SwAttrSet in SW, functionPtr for callback std::function<void(const SfxPoolItem*, const SfxPoolItem*)> m_aCallback; + // helpers to keep m_nRegister up-to-date + void checkRemovePoolRegistration(const SfxPoolItem* pItem); + void checkAddPoolRegistration(const SfxPoolItem* pItem); + protected: // Notification-Callback mechanism for SwAttrSet in SW void setCallback(const std::function<void(const SfxPoolItem*, const SfxPoolItem*)> &func) { m_aCallback = func; } diff --git a/include/svl/poolitem.hxx b/include/svl/poolitem.hxx index ce65d63709cf..d2165a49a446 100644 --- a/include/svl/poolitem.hxx +++ b/include/svl/poolitem.hxx @@ -115,7 +115,7 @@ class SVL_DLLPUBLIC SfxPoolItem // allow ItemSetTooling to access friend SfxPoolItem const* implCreateItemEntry(SfxItemPool&, SfxPoolItem const*, sal_uInt16, bool); - friend void implCleanupItemEntry(SfxItemPool&, SfxPoolItem const*); + friend void implCleanupItemEntry(SfxPoolItem const*); mutable sal_uInt32 m_nRefCount; sal_uInt16 m_nWhich; @@ -133,13 +133,12 @@ class SVL_DLLPUBLIC SfxPoolItem bool m_bIsVoidItem : 1; // bit 0 bool m_bStaticDefault : 1; // bit 1 bool m_bPoolDefault : 1; // bit 2 - bool m_bRegisteredAtPool : 1; // bit 3 - bool m_bIsSetItem : 1; // bit 5 + bool m_bIsSetItem : 1; // bit 3 protected: #ifdef DBG_UTIL // this flag will make debugging item stuff much simpler - bool m_bDeleted : 1; // bit 6 + bool m_bDeleted : 1; // bit 4 #endif private: @@ -153,7 +152,6 @@ protected: void setIsVoidItem() { m_bIsVoidItem = true; } void setStaticDefault() { m_bStaticDefault = true; } void setPoolDefault() { m_bPoolDefault = true; } - void setRegisteredAtPool(bool bNew) { m_bRegisteredAtPool = bNew; } void setIsSetItem() { m_bIsSetItem = true; } public: @@ -171,7 +169,6 @@ public: bool isVoidItem() const { return m_bIsVoidItem; } bool isStaticDefault() const { return m_bStaticDefault; } bool isPoolDefault() const { return m_bPoolDefault; } - bool isRegisteredAtPool() const { return m_bRegisteredAtPool; } bool isSetItem() const { return m_bIsSetItem; } // version that allows nullptrs diff --git a/sc/inc/fillinfo.hxx b/sc/inc/fillinfo.hxx index 81086ed358ba..7d75defe957a 100644 --- a/sc/inc/fillinfo.hxx +++ b/sc/inc/fillinfo.hxx @@ -119,7 +119,7 @@ struct ScCellInfo , pConditionSet(nullptr) , pDataBar(nullptr) , pIconSet(nullptr) - , pBackground(nullptr) // TODO: omit? + , maBackground() , pLinesAttr(nullptr) , mpTLBRLine(nullptr) , mpBLTRLine(nullptr) @@ -156,7 +156,7 @@ struct ScCellInfo const ScDataBarInfo* pDataBar; const ScIconSetInfo* pIconSet; - const SvxBrushItem* pBackground; + SfxPoolItemHolder maBackground; const SvxBoxItem* pLinesAttr; /// original item from document. const SvxLineItem* mpTLBRLine; /// original item from document. diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx index a9f04943c0d1..c4c569557ffb 100644 --- a/sc/source/core/data/documen9.cxx +++ b/sc/source/core/data/documen9.cxx @@ -546,7 +546,9 @@ void ScDocument::UpdateFontCharSet() return; ScDocumentPool* pPool = mxPoolHelper->GetDocPool(); - for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(ATTR_FONT)) + ItemSurrogates aSurrogates; + pPool->GetItemSurrogates(aSurrogates, ATTR_FONT); + for (const SfxPoolItem* pItem : aSurrogates) { auto pFontItem = const_cast<SvxFontItem*>(dynamic_cast<const SvxFontItem*>(pItem)); if ( pFontItem && ( pFontItem->GetCharSet() == eSrcSet || @@ -557,7 +559,8 @@ void ScDocument::UpdateFontCharSet() if ( mpDrawLayer ) { SfxItemPool& rDrawPool = mpDrawLayer->GetItemPool(); - for (const SfxPoolItem* pItem : rDrawPool.GetItemSurrogates(EE_CHAR_FONTINFO)) + rDrawPool.GetItemSurrogates(aSurrogates, EE_CHAR_FONTINFO); + for (const SfxPoolItem* pItem : aSurrogates) { SvxFontItem* pFontItem = const_cast<SvxFontItem*>(dynamic_cast<const SvxFontItem*>(pItem)); if ( pFontItem && ( pFontItem->GetCharSet() == eSrcSet || diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 04e20ce4b8ac..c44672048b39 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -5175,7 +5175,9 @@ static HasAttrFlags OptimizeHasAttrib( HasAttrFlags nMask, const ScDocumentPool* // (as in fillinfo) bool bAnyItem = false; - for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(ATTR_ROTATE_VALUE)) + ItemSurrogates aSurrogates; + pPool->GetItemSurrogates(aSurrogates, ATTR_ROTATE_VALUE); + for (const SfxPoolItem* pItem : aSurrogates) { // 90 or 270 degrees is former SvxOrientationItem - only look for other values // (see ScPatternAttr::GetCellOrientation) diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx index a1aeef5d7e7b..61c75b5e2cc5 100644 --- a/sc/source/core/data/document10.cxx +++ b/sc/source/core/data/document10.cxx @@ -191,7 +191,9 @@ std::set<Color> ScDocument::GetDocColors() const sal_uInt16 pAttribs[] = {ATTR_BACKGROUND, ATTR_FONT_COLOR}; for (sal_uInt16 nAttrib : pAttribs) { - for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(nAttrib)) + ItemSurrogates aSurrogates; + pPool->GetItemSurrogates(aSurrogates, nAttrib); + for (const SfxPoolItem* pItem : aSurrogates) { const SvxColorItem *pColorItem = static_cast<const SvxColorItem*>(pItem); Color aColor( pColorItem->GetValue() ); diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx index 544c58a65e46..8e84d045ff72 100644 --- a/sc/source/core/data/fillinfo.cxx +++ b/sc/source/core/data/fillinfo.cxx @@ -186,7 +186,9 @@ public: bool isRotateItemUsed(const ScDocumentPool *pPool) { - return pPool->GetItemSurrogates(ATTR_ROTATE_VALUE).size() > 0; + ItemSurrogates aSurrogates; + pPool->GetItemSurrogates(aSurrogates, ATTR_ROTATE_VALUE); + return aSurrogates.size() > 0; } void initRowInfo(const ScDocument* pDoc, RowInfo* pRowInfo, const SCSIZE nMaxRow, @@ -543,7 +545,7 @@ void ScDocument::FillInfo( ScCellInfo* pInfo = &pThisRowInfo->cellInfo(nCol); ScBasicCellInfo* pBasicInfo = &pThisRowInfo->basicCellInfo(nCol); - pInfo->pBackground = pBackground; + pInfo->maBackground = SfxPoolItemHolder(*pPool, pBackground); pInfo->pPatternAttr = pPattern; pInfo->bMerged = bMerged; pInfo->bHOverlapped = bHOverlapped; @@ -563,7 +565,7 @@ void ScDocument::FillInfo( if (bScenario) { - pInfo->pBackground = ScGlobal::GetButtonBrushItem(); + pInfo->maBackground = SfxPoolItemHolder(*pPool, ScGlobal::GetButtonBrushItem()); pThisRowInfo->bEmptyBack = false; } @@ -664,7 +666,7 @@ void ScDocument::FillInfo( // Background if ( const SvxBrushItem* pItem = pCondSet->GetItemIfSet( ATTR_BACKGROUND ) ) { - pInfo->pBackground = pItem; + pInfo->maBackground = SfxPoolItemHolder(*pPool, pItem); pRowInfo[nArrRow].bEmptyBack = false; } @@ -687,7 +689,8 @@ void ScDocument::FillInfo( if( bAnyCondition && pInfo->mxColorScale) { pRowInfo[nArrRow].bEmptyBack = false; - pInfo->pBackground = &pPool->DirectPutItemInPool(SvxBrushItem(*pInfo->mxColorScale, ATTR_BACKGROUND)); + const SvxBrushItem aBrushItem(*pInfo->mxColorScale, ATTR_BACKGROUND); + pInfo->maBackground = SfxPoolItemHolder(*pPool, &aBrushItem); } } } @@ -725,7 +728,7 @@ void ScDocument::FillInfo( if ( !pStartCond || !(pBrushItem = pStartCond->GetItemIfSet(ATTR_BACKGROUND)) ) pBrushItem = &pStartPattern->GetItem(ATTR_BACKGROUND); - pInfo->pBackground = pBrushItem; + pInfo->maBackground = SfxPoolItemHolder(*pPool, pBrushItem); pRowInfo[nArrRow].bEmptyBack = false; // Shadow diff --git a/sc/source/core/data/poolcach.cxx b/sc/source/core/data/poolcach.cxx index 3ab41d416c49..6db714bb7c12 100644 --- a/sc/source/core/data/poolcach.cxx +++ b/sc/source/core/data/poolcach.cxx @@ -26,7 +26,7 @@ ScItemPoolCache::ScItemPoolCache(CellAttributeHelper& _rHelper, const SfxPoolItem& rPutItem) : rHelper(_rHelper) , pSetToPut(nullptr) -, aItemToPut(_rHelper.GetPool(), &rPutItem) +, aItemToPut(rHelper.GetPool(), &rPutItem) { } diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 9da5da65b7e6..4ec6ab6cdbb6 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -5329,7 +5329,9 @@ XMLNumberFormatAttributesExportHelper* ScXMLExport::GetNumberFormatAttributesExp void ScXMLExport::CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib) { - for (const SfxPoolItem* pItem : pPool->GetItemSurrogates(nAttrib)) + ItemSurrogates aSurrogates; + pPool->GetItemSurrogates(aSurrogates, nAttrib); + for (const SfxPoolItem* pItem : aSurrogates) { const SvXMLAttrContainerItem *pUnknown(static_cast<const SvXMLAttrContainerItem *>(pItem)); if( pUnknown->GetAttrCount() > 0 ) diff --git a/sc/source/filter/xml/xmlfonte.cxx b/sc/source/filter/xml/xmlfonte.cxx index ab8e42f4ce60..f6951eddb0b8 100644 --- a/sc/source/filter/xml/xmlfonte.cxx +++ b/sc/source/filter/xml/xmlfonte.cxx @@ -59,7 +59,9 @@ void ScXMLFontAutoStylePool_Impl::AddFontItems(const sal_uInt16* pWhichIds, sal_ pFont->GetFamily(), pFont->GetPitch(), pFont->GetCharSet() ); } - for (const SfxPoolItem* pItem : pItemPool->GetItemSurrogates( nWhichId )) + ItemSurrogates aSurrogates; + pItemPool->GetItemSurrogates( aSurrogates, nWhichId ); + for (const SfxPoolItem* pItem : aSurrogates) { const SvxFontItem *pFont(static_cast<const SvxFontItem *>(pItem)); Add( pFont->GetFamilyName(), pFont->GetStyleName(), @@ -111,7 +113,9 @@ ScXMLFontAutoStylePool_Impl::ScXMLFontAutoStylePool_Impl(ScXMLExport& rExportP, for (sal_uInt16 nPageWhichId : aPageWhichIds) { - for (const SfxPoolItem* pItem : rPagePool.GetItemSurrogates( nPageWhichId )) + ItemSurrogates aSurrogates; + rPagePool.GetItemSurrogates( aSurrogates, nPageWhichId ); + for (const SfxPoolItem* pItem : aSurrogates) { const ScPageHFItem* pPageItem = static_cast<const ScPageHFItem*>(pItem); const EditTextObject* pLeftArea(pPageItem->GetLeftArea()); diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index 4907b6b50c05..03d93088a54d 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -2161,10 +2161,11 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) bool bManaged = false; // Get the pool item stored by Conditional Format Manager Dialog. - auto itemsRange = pTabViewShell->GetPool().GetItemSurrogates(SCITEM_CONDFORMATDLGDATA); - if (itemsRange.begin() != itemsRange.end()) + ItemSurrogates aSurrogates; + pTabViewShell->GetPool().GetItemSurrogates(aSurrogates, SCITEM_CONDFORMATDLGDATA); + if (aSurrogates.begin() != aSurrogates.end()) { - const ScCondFormatDlgItem* pDlgItem = static_cast<const ScCondFormatDlgItem*>(*itemsRange.begin()); + const ScCondFormatDlgItem* pDlgItem = static_cast<const ScCondFormatDlgItem*>(*aSurrogates.begin()); nIndex = pDlgItem->GetIndex(); bManaged = true; } @@ -2873,10 +2874,11 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) ScConditionalFormatList* pList = nullptr; const ScCondFormatDlgItem* pDlgItem = nullptr; - auto itemsRange = pTabViewShell->GetPool().GetItemSurrogates(SCITEM_CONDFORMATDLGDATA); - if (itemsRange.begin() != itemsRange.end()) + ItemSurrogates aSurrogates; + pTabViewShell->GetPool().GetItemSurrogates(aSurrogates, SCITEM_CONDFORMATDLGDATA); + if (aSurrogates.begin() != aSurrogates.end()) { - pDlgItem= static_cast<const ScCondFormatDlgItem*>(*itemsRange.begin()); + pDlgItem= static_cast<const ScCondFormatDlgItem*>(*aSurrogates.begin()); pList = const_cast<ScCondFormatDlgItem*>(pDlgItem)->GetConditionalFormatList(); } diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index edad3a96f0b6..58b6db5107d3 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -823,7 +823,7 @@ static bool lcl_EqualBack( const RowInfo& rFirst, const RowInfo& rOther, else { for ( nX=nX1; nX<=nX2; nX++ ) - if ( !SfxPoolItem::areSame(rFirst.cellInfo(nX).pBackground, rOther.cellInfo(nX).pBackground ) ) + if ( !SfxPoolItem::areSame(rFirst.cellInfo(nX).maBackground.getItem(), rOther.cellInfo(nX).maBackground.getItem() ) ) return false; } @@ -1204,7 +1204,7 @@ void ScOutputData::DrawBackground(vcl::RenderContext& rRenderContext) pBackground = nullptr; } else - pBackground = pInfo->pBackground; + pBackground = static_cast<const SvxBrushItem*>(pInfo->maBackground.getItem()); if ( bPagebreakMode && !pInfo->bPrinted ) pBackground = pProtectedBackground.get(); @@ -1723,7 +1723,7 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext) aPoints[2] = Point(nBotRight, nBottom); aPoints[3] = Point(nBotLeft, nBottom); - const SvxBrushItem* pBackground = pInfo->pBackground; + const SvxBrushItem* pBackground(static_cast<const SvxBrushItem*>(pInfo->maBackground.getItem())); if (!pBackground) pBackground = &pPattern->GetItem(ATTR_BACKGROUND, pCondSet); if (bCellContrast) @@ -2494,7 +2494,7 @@ void ScOutputData::DrawNoteMarks(vcl::RenderContext& rRenderContext) { const bool bIsDarkBackground = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor.IsDark(); - const Color aColor = pInfo->pBackground->GetColor(); + const Color aColor(static_cast<const SvxBrushItem*>(pInfo->maBackground.getItem())->GetColor()); if ( aColor == COL_AUTO ? bIsDarkBackground : aColor.IsDark() ) rRenderContext.SetLineColor(COL_WHITE); else @@ -2794,7 +2794,9 @@ void ScOutputData::DrawClipMarks() tools::Long nMarkPixel = static_cast<tools::Long>( SC_CLIPMARK_SIZE * mnPPTX ); Size aMarkSize( nMarkPixel, (nMarkPixel-1)*2 ); - const Color aColor = pInfo->pBackground ? pInfo->pBackground->GetColor() : COL_AUTO; + const Color aColor = pInfo->maBackground ? + static_cast<const SvxBrushItem*>(pInfo->maBackground.getItem())->GetColor() : + COL_AUTO; if ( aColor == COL_AUTO ? bIsDarkBackground : aColor.IsDark() ) mpDev->SetDrawMode( nOldDrawMode | DrawModeFlags::WhiteLine ); else diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index eeb554454eab..1012f1ceb249 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -427,10 +427,11 @@ std::shared_ptr<SfxModelessDialogController> ScTabViewShell::CreateRefDialogCont { const ScCondFormatDlgItem* pDlgItem = nullptr; // Get the pool item stored by Conditional Format Manager Dialog. - auto itemsRange = GetPool().GetItemSurrogates(SCITEM_CONDFORMATDLGDATA); - if (itemsRange.begin() != itemsRange.end()) + ItemSurrogates aSurrogates; + GetPool().GetItemSurrogates(aSurrogates, SCITEM_CONDFORMATDLGDATA); + if (aSurrogates.begin() != aSurrogates.end()) { - const SfxPoolItem* pItem = *itemsRange.begin(); + const SfxPoolItem* pItem = *aSurrogates.begin(); pDlgItem = static_cast<const ScCondFormatDlgItem*>(pItem); } diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 97d7338ece91..a6d28ecbc37b 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -1049,10 +1049,13 @@ void ScViewFunc::ApplyAttributes( const SfxItemSet& rDialogSet, const SvxBoxInfoItem& rOldInner = rOldSet.Get(ATTR_BORDER_INNER); const SvxBoxInfoItem& rNewInner = rDialogSet.Get(ATTR_BORDER_INNER); SfxItemSet& rNewSet = aNewAttrs.GetItemSet(); - SfxItemPool* pNewPool = rNewSet.GetPool(); - pNewPool->DirectPutItemInPool(rNewOuter); // don't delete yet - pNewPool->DirectPutItemInPool(rNewInner); + // protect referenced Items from disappearing (was: don't delete yet) + const SfxPoolItemHolder aHoldOuter(*rDialogSet.GetPool() , &rNewOuter); + const SfxPoolItemHolder aHoldInner(*rDialogSet.GetPool() , &rNewInner); + (void)aHoldOuter; + (void)aHoldInner; + rNewSet.ClearItem( ATTR_BORDER ); rNewSet.ClearItem( ATTR_BORDER_INNER ); @@ -1096,9 +1099,6 @@ void ScViewFunc::ApplyAttributes( const SfxItemSet& rDialogSet, bDefNewInner ? &rOldInner : &rNewInner ); } - pNewPool->DirectRemoveItemFromPool(rNewOuter); // release - pNewPool->DirectRemoveItemFromPool(rNewInner); - // adjust height only if needed if (bAdjustBlockHeight) AdjustBlockHeight(); diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx index de82a8b95306..328952c577c5 100644 --- a/sd/source/core/drawdoc2.cxx +++ b/sd/source/core/drawdoc2.cxx @@ -268,7 +268,9 @@ void SdDrawDocument::UpdatePageRelativeURLs(std::u16string_view aOldName, std::u return; SfxItemPool& rPool(GetPool()); - for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(EE_FEATURE_FIELD)) + ItemSurrogates aSurrogates; + rPool.GetItemSurrogates(aSurrogates, EE_FEATURE_FIELD); + for (const SfxPoolItem* pItem : aSurrogates) { const SvxFieldItem* pFldItem = dynamic_cast< const SvxFieldItem * > (pItem); @@ -310,7 +312,9 @@ void SdDrawDocument::UpdatePageRelativeURLs(SdPage const * pPage, sal_uInt16 nPo bool bNotes = (pPage->GetPageKind() == PageKind::Notes); SfxItemPool& rPool(GetPool()); - for (const SfxPoolItem* pItem : rPool.GetItemSurrogates(EE_FEATURE_FIELD)) + ItemSurrogates aSurrogates; + rPool.GetItemSurrogates(aSurrogates, EE_FEATURE_FIELD); + for (const SfxPoolItem* pItem : aSurrogates) { const SvxFieldItem* pFldItem; diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index 075ee6e383a7..89efc76df232 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -1391,13 +1391,14 @@ uno::Any SAL_CALL SdXImpressDocument::getPropertyValue( const OUString& Property for(sal_uInt16 nWhichId : aWhichIds) { - const registeredSfxPoolItems& rSurrogates(rPool.GetItemSurrogates(nWhichId)); - const sal_uInt32 nItems(rSurrogates.size()); + ItemSurrogates aSurrogates; + rPool.GetItemSurrogates(aSurrogates, nWhichId); + const sal_uInt32 nItems(aSurrogates.size()); aSeq.realloc( aSeq.getLength() + nItems*5 + 5 ); auto pSeq = aSeq.getArray(); - for (const SfxPoolItem* pItem : rSurrogates) + for (const SfxPoolItem* pItem : aSurrogates) { const SvxFontItem *pFont = static_cast<const SvxFontItem *>(pItem); diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index a9690468cb89..5581b9486be0 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -10965,7 +10965,6 @@ svgio/source/svgreader/svgtspannode.cxx svgio/source/svgreader/svgusenode.cxx svgio/source/svguno/xsvgparser.cxx svl/qa/unit/items/test_IndexedStyleSheets.cxx -svl/qa/unit/items/test_itempool.cxx svl/qa/unit/svl.cxx svl/qa/unit/test_INetContentType.cxx svl/qa/unit/test_URIHelper.cxx @@ -10985,7 +10984,6 @@ svl/source/fsstor/oinputstreamcontainer.hxx svl/source/fsstor/ostreamcontainer.cxx svl/source/fsstor/ostreamcontainer.hxx svl/source/inc/fsfactory.hxx -svl/source/inc/poolio.hxx svl/source/items/IndexedStyleSheets.cxx svl/source/items/aeitem.cxx svl/source/items/cenumitm.cxx diff --git a/svl/CppunitTest_svl_itempool.mk b/svl/CppunitTest_svl_itempool.mk deleted file mode 100644 index 892107e906ca..000000000000 --- a/svl/CppunitTest_svl_itempool.mk +++ /dev/null @@ -1,34 +0,0 @@ -# -*- 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,svl_itempool)) - -$(eval $(call gb_CppunitTest_use_external,svl_itempool,boost_headers)) - -$(eval $(call gb_CppunitTest_use_sdk_api,svl_itempool)) - -$(eval $(call gb_CppunitTest_add_exception_objects,svl_itempool, \ - svl/qa/unit/items/test_itempool \ -)) - -$(eval $(call gb_CppunitTest_use_libraries,svl_itempool, \ - svl \ - comphelper \ - sal \ - salhelper \ - cppu \ - cppuhelper \ -)) - -$(eval $(call gb_CppunitTest_set_include,svl_itempool,\ - -I$(SRCDIR)/svl/source/inc \ - $$(INCLUDE) \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/svl/Module_svl.mk b/svl/Module_svl.mk index 45bf74915c14..71fc8d08120f 100644 --- a/svl/Module_svl.mk +++ b/svl/Module_svl.mk @@ -32,7 +32,6 @@ $(eval $(call gb_Module_add_l10n_targets,svl,\ $(eval $(call gb_Module_add_check_targets,svl,\ CppunitTest_svl_adrparse \ CppunitTest_svl_inetcontenttype \ - CppunitTest_svl_itempool \ CppunitTest_svl_items \ CppunitTest_svl_lngmisc \ CppunitTest_svl_lockfiles \ diff --git a/svl/qa/unit/items/test_itempool.cxx b/svl/qa/unit/items/test_itempool.cxx deleted file mode 100644 index 2cb751d4fd77..000000000000 --- a/svl/qa/unit/items/test_itempool.cxx +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- 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/. - */ - -#include <svl/itempool.hxx> -#include <svl/voiditem.hxx> -#include <poolio.hxx> - -#include <cppunit/TestAssert.h> -#include <cppunit/TestFixture.h> -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/plugin/TestPlugIn.h> - -class PoolItemTest : public CppUnit::TestFixture -{ - public: - PoolItemTest() {} - - void testPool(); - - // Adds code needed to register the test suite - CPPUNIT_TEST_SUITE(PoolItemTest); - - CPPUNIT_TEST(testPool); - - // End of test suite definition - CPPUNIT_TEST_SUITE_END(); -}; - -void PoolItemTest::testPool() -{ - SfxItemInfo const aItems[] = - { - // _nSID, _bNeedsPoolRegistration, _bShareable - { 4, true, true }, - { 3, true, false /* test NeedsPoolRegistration */ }, - { 2, false, false }, - { 1, true, false /* test NeedsPoolRegistration */} - }; - - rtl::Reference<SfxItemPool> pPool = new SfxItemPool("testpool", 1, 4, aItems); - - // Poolable - SfxVoidItem aItemOne( 1 ); - SfxVoidItem aNotherOne( 1 ); - - { - CPPUNIT_ASSERT(nullptr == pPool->ppRegisteredSfxPoolItems); - const SfxPoolItem &rVal = pPool->DirectPutItemInPool(aItemOne); - CPPUNIT_ASSERT(bool(rVal == aItemOne)); - CPPUNIT_ASSERT(nullptr != pPool->ppRegisteredSfxPoolItems); - CPPUNIT_ASSERT(nullptr != pPool->ppRegisteredSfxPoolItems[0]); - CPPUNIT_ASSERT(!pPool->ppRegisteredSfxPoolItems[0]->empty()); - const SfxPoolItem &rVal2 = pPool->DirectPutItemInPool(aNotherOne); - CPPUNIT_ASSERT(bool(rVal2 == rVal)); - - // ITEM: With leaving the paradigm that internally an already - // existing Item with true = operator==() (which is very - // expensive) the ptr's are no longer required to be equal, - // but the content-compare *is* - CPPUNIT_ASSERT(SfxPoolItem::areSame(rVal, rVal2)); - - // Clones on Put ... - // ptr compare OK, we want to check just the ptrs here - CPPUNIT_ASSERT(!areSfxPoolItemPtrsEqual(&rVal2, &aItemOne)); - CPPUNIT_ASSERT(!areSfxPoolItemPtrsEqual(&rVal2, &aNotherOne)); - CPPUNIT_ASSERT(!areSfxPoolItemPtrsEqual(&rVal, &aItemOne)); - CPPUNIT_ASSERT(!areSfxPoolItemPtrsEqual(&rVal, &aNotherOne)); - } - - // non-poolable - SfxVoidItem aItemTwo( 2 ); - SfxVoidItem aNotherTwo( 2 ); - { - CPPUNIT_ASSERT(nullptr == pPool->ppRegisteredSfxPoolItems[1]); - const SfxPoolItem &rVal = pPool->DirectPutItemInPool(aItemTwo); - CPPUNIT_ASSERT(bool(rVal == aItemTwo)); - CPPUNIT_ASSERT(nullptr != pPool->ppRegisteredSfxPoolItems[1]); - CPPUNIT_ASSERT(!pPool->ppRegisteredSfxPoolItems[1]->empty()); - const SfxPoolItem &rVal2 = pPool->DirectPutItemInPool(aNotherTwo); - CPPUNIT_ASSERT(bool(rVal2 == rVal)); - // ptr compare OK, we want to check just the ptrs here - CPPUNIT_ASSERT(!areSfxPoolItemPtrsEqual(&rVal2, &rVal)); - } - - // Test removal. - SfxVoidItem aRemoveFour(4); - SfxVoidItem aNotherFour(4); - - const SfxPoolItem &rKeyFour = pPool->DirectPutItemInPool(aRemoveFour); - pPool->DirectPutItemInPool(aNotherFour); - CPPUNIT_ASSERT(pPool->ppRegisteredSfxPoolItems[3]->size() > 0); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pPool->ppRegisteredSfxPoolItems[3]->size()); - pPool->DirectRemoveItemFromPool(rKeyFour); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pPool->ppRegisteredSfxPoolItems[3]->size()); - pPool->DirectPutItemInPool(aNotherFour); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), pPool->ppRegisteredSfxPoolItems[3]->size()); -} - - -CPPUNIT_TEST_SUITE_REGISTRATION(PoolItemTest); - -CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/svl/source/inc/poolio.hxx b/svl/source/inc/poolio.hxx deleted file mode 100644 index 118deaf50e2e..000000000000 --- a/svl/source/inc/poolio.hxx +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- 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 . - */ - -#ifndef INCLUDED_SVL_SOURCE_INC_POOLIO_HXX -#define INCLUDED_SVL_SOURCE_INC_POOLIO_HXX - -#include <rtl/ref.hxx> -#include <svl/itempool.hxx> -#include <svl/SfxBroadcaster.hxx> -#include <tools/debug.hxx> -#include <memory> -#include <o3tl/sorted_vector.hxx> -#include <utility> - -class SfxPoolItem; -class SfxItemPoolUser; - -struct SfxItemPool_Impl -{ - SfxBroadcaster aBC; - OUString aName; - std::vector<SfxPoolItem*> maPoolDefaults; - std::vector<SfxPoolItem*>* mpStaticDefaults; - SfxItemPool* mpMaster; - rtl::Reference<SfxItemPool> mpSecondary; - WhichRangesContainer mpPoolRanges; - sal_uInt16 mnStart; - sal_uInt16 mnEnd; - MapUnit eDefMetric; - - SfxItemPool_Impl( SfxItemPool* pMaster, OUString _aName, sal_uInt16 nStart, sal_uInt16 nEnd ) - : aName(std::move(_aName)) - , maPoolDefaults(nEnd - nStart + 1) - , mpStaticDefaults(nullptr) - , mpMaster(pMaster) - , mnStart(nStart) - , mnEnd(nEnd) - , eDefMetric(MapUnit::MapCM) - { - DBG_ASSERT(mnStart, "Start-Which-Id must be greater 0" ); - } - - ~SfxItemPool_Impl() - { - DeleteItems(); - } - - void DeleteItems() - { - maPoolDefaults.clear(); - mpPoolRanges.reset(); - } -}; - -#endif // INCLUDED_SVL_SOURCE_INC_POOLIO_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/itempool.cxx b/svl/source/items/itempool.cxx index e697a5e9a1f2..0fd59788a711 100644 --- a/svl/source/items/itempool.cxx +++ b/svl/source/items/itempool.cxx @@ -28,8 +28,7 @@ #include <svl/SfxBroadcaster.hxx> #include <svl/hint.hxx> #include <svl/itemset.hxx> - -#include <poolio.hxx> +#include <tools/debug.hxx> #include <cassert> #include <vector> @@ -236,7 +235,7 @@ lcl_CheckSlots2(std::map<sal_uInt16, sal_uInt16> & rSlotMap, #define CHECK_SLOTS() \ do { \ std::map<sal_uInt16, sal_uInt16> slotmap; \ - for (SfxItemPool * p = pImpl->mpMaster; p; p = p->pImpl->mpSecondary.get()) \ + for (SfxItemPool * p = mpMaster; p; p = p->mpSecondary.get()) \ { \ lcl_CheckSlots2(slotmap, *p, p->pItemInfos); \ } \ @@ -246,43 +245,107 @@ do { \ #define CHECK_SLOTS() do {} while (false) #endif +void SfxItemPool::registerItemSet(SfxItemSet& rSet) +{ + registeredSfxItemSets& rTarget(GetMasterPool()->maRegisteredSfxItemSets); +#ifdef DBG_UTIL + const size_t nBefore(rTarget.size()); +#endif + rTarget.insert(&rSet); +#ifdef DBG_UTIL + const size_t nAfter(rTarget.size()); + if (nBefore + 1 != nAfter) + { + SAL_WARN("svl.items", "SfxItemPool::registerItemSet: ItemSet was already registered (!)"); + } +#endif +} + +void SfxItemPool::unregisterItemSet(SfxItemSet& rSet) +{ + registeredSfxItemSets& rTarget(GetMasterPool()->maRegisteredSfxItemSets); +#ifdef DBG_UTIL + const size_t nBefore(rTarget.size()); +#endif + rTarget.erase(&rSet); +#ifdef DBG_UTIL + const size_t nAfter(rTarget.size()); + if (nBefore != nAfter + 1) + { + SAL_WARN("svl.items", "SfxItemPool::unregisterItemSet: ItemSet was not registered (!)"); + } +#endif +} + +void SfxItemPool::registerPoolItemHolder(SfxPoolItemHolder& rHolder) +{ + registeredSfxPoolItemHolders& rTarget(GetMasterPool()->maRegisteredSfxPoolItemHolders); +#ifdef DBG_UTIL + const size_t nBefore(rTarget.size()); +#endif + rTarget.insert(&rHolder); +#ifdef DBG_UTIL + const size_t nAfter(rTarget.size()); + if (nBefore + 1 != nAfter) + { + SAL_WARN("svl.items", "SfxItemPool::registerPoolItemHolder: SfxPoolItemHolder was already registered (!)"); + } +#endif +} + +void SfxItemPool::unregisterPoolItemHolder(SfxPoolItemHolder& rHolder) +{ + registeredSfxPoolItemHolders& rTarget(GetMasterPool()->maRegisteredSfxPoolItemHolders); +#ifdef DBG_UTIL + const size_t nBefore(rTarget.size()); +#endif + rTarget.erase(&rHolder); +#ifdef DBG_UTIL + const size_t nAfter(rTarget.size()); + if (nBefore != nAfter + 1) + { + SAL_WARN("svl.items", "SfxItemPool::unregisterPoolItemHolder: SfxPoolItemHolder was not registered (!)"); + } +#endif +} + sal_uInt16 SfxItemPool::GetFirstWhich() const { - return pImpl->mnStart; + return mnStart; } sal_uInt16 SfxItemPool::GetLastWhich() const { - return pImpl->mnEnd; + return mnEnd; } bool SfxItemPool::IsInRange( sal_uInt16 nWhich ) const { - return nWhich >= pImpl->mnStart && nWhich <= pImpl->mnEnd; + return nWhich >= mnStart && nWhich <= mnEnd; } sal_uInt16 SfxItemPool::GetIndex_Impl(sal_uInt16 nWhich) const { - if (nWhich < pImpl->mnStart || nWhich > pImpl->mnEnd) + if (nWhich < mnStart || nWhich > mnEnd) { assert(false && "missing bounds check before use"); return 0; } - return nWhich - pImpl->mnStart; + return nWhich - mnStart; } sal_uInt16 SfxItemPool::GetSize_Impl() const { - return pImpl->mnEnd - pImpl->mnStart + 1; + return mnEnd - mnStart + 1; } const SfxPoolItem* SfxItemPool::GetPoolDefaultItem( sal_uInt16 nWhich ) const { const SfxPoolItem* pRet; if( IsInRange( nWhich ) ) - pRet = pImpl->maPoolDefaults[GetIndex_Impl(nWhich)]; - else if( pImpl->mpSecondary ) - pRet = pImpl->mpSecondary->GetPoolDefaultItem( nWhich ); + pRet = maPoolDefaults[GetIndex_Impl(nWhich)]; + else if( mpSecondary ) + pRet = mpSecondary->GetPoolDefaultItem( nWhich ); else { assert(false && "unknown WhichId - cannot get pool default"); @@ -297,12 +360,12 @@ bool SfxItemPool::NeedsPoolRegistration(sal_uInt16 nWhich) const if (!IsInRange(nWhich)) { // get to correct pool - if (pImpl->mpSecondary) - return pImpl->mpSecondary->NeedsPoolRegistration(nWhich); + if (mpSecondary) + return mpSecondary->NeedsPoolRegistration(nWhich); return false; } - return NeedsPoolRegistration_Impl(nWhich - pImpl->mnStart); + return NeedsPoolRegistration_Impl(nWhich - mnStart); } bool SfxItemPool::Shareable(sal_uInt16 nWhich) const @@ -310,18 +373,18 @@ bool SfxItemPool::Shareable(sal_uInt16 nWhich) const if (!IsInRange(nWhich)) { // get to correct pool - if (pImpl->mpSecondary) - return pImpl->mpSecondary->Shareable(nWhich); + if (mpSecondary) + return mpSecondary->Shareable(nWhich); return false; } - return Shareable_Impl(nWhich - pImpl->mnStart); + return Shareable_Impl(nWhich - mnStart); } SfxBroadcaster& SfxItemPool::BC() { - return pImpl->aBC; + return aBC; } @@ -357,12 +420,22 @@ SfxItemPool::SfxItemPool pDefaults /* Pointer to static Defaults; is directly referenced by the Pool, but no transfer of ownership */ -) : - pItemInfos(pInfo), - pImpl( new SfxItemPool_Impl( this, rName, nStartWhich, nEndWhich ) ), - ppRegisteredSfxPoolItems(nullptr) -{ - pImpl->eDefMetric = MapUnit::MapTwip; +) +: salhelper::SimpleReferenceObject() +,pItemInfos(pInfo) +, aName(rName) +, maPoolDefaults(nEndWhich - nStartWhich + 1) +, mpStaticDefaults(nullptr) +, mpMaster(this) +, mnStart(nStartWhich) +, mnEnd(nEndWhich) +, eDefMetric(MapUnit::MapCM) +, maRegisteredSfxItemSets() +, maRegisteredSfxPoolItemHolders() +, maDirectPutItems() +, mbPreDeleteDone(false) +{ + eDefMetric = MapUnit::MapTwip; if ( pDefaults ) SetDefaults(pDefaults); @@ -400,68 +473,75 @@ SfxItemPool::SfxItemPool false Take over static Defaults */ -) : - salhelper::SimpleReferenceObject(), - pItemInfos(rPool.pItemInfos), - pImpl( new SfxItemPool_Impl( this, rPool.pImpl->aName, rPool.pImpl->mnStart, rPool.pImpl->mnEnd ) ), - ppRegisteredSfxPoolItems(nullptr) -{ - pImpl->eDefMetric = rPool.pImpl->eDefMetric; +) +: salhelper::SimpleReferenceObject() +, pItemInfos(rPool.pItemInfos) +, aName(rPool.aName) +, maPoolDefaults(rPool.mnEnd - rPool.mnStart + 1) +, mpStaticDefaults(nullptr) +, mpMaster(this) +, mnStart(rPool.mnStart) +, mnEnd(rPool.mnEnd) +, eDefMetric(MapUnit::MapCM) +, maRegisteredSfxItemSets() +, maRegisteredSfxPoolItemHolders() +, maDirectPutItems() +, mbPreDeleteDone(false) +{ + eDefMetric = rPool.eDefMetric; // Take over static Defaults if ( bCloneStaticDefaults ) { - std::vector<SfxPoolItem *>* ppDefaults = new std::vector<SfxPoolItem*>(pImpl->mnEnd-pImpl->mnStart+1); - for ( sal_uInt16 n = 0; n <= pImpl->mnEnd - pImpl->mnStart; ++n ) + std::vector<SfxPoolItem *>* ppDefaults = new std::vector<SfxPoolItem*>(mnEnd-mnStart+1); + for ( sal_uInt16 n = 0; n <= mnEnd - mnStart; ++n ) { - (*ppDefaults)[n] = (*rPool.pImpl->mpStaticDefaults)[n]->Clone(this); + (*ppDefaults)[n] = (*rPool.mpStaticDefaults)[n]->Clone(this); (*ppDefaults)[n]->setStaticDefault(); } SetDefaults( ppDefaults ); } else - SetDefaults( rPool.pImpl->mpStaticDefaults ); + SetDefaults( rPool.mpStaticDefaults ); // Copy Pool Defaults - for (size_t n = 0; n < pImpl->maPoolDefaults.size(); ++n ) - if (rPool.pImpl->maPoolDefaults[n]) + for (size_t n = 0; n < maPoolDefaults.size(); ++n ) + if (rPool.maPoolDefaults[n]) { - pImpl->maPoolDefaults[n] = rPool.pImpl->maPoolDefaults[n]->Clone(this); //resets kind - pImpl->maPoolDefaults[n]->setPoolDefault(); + maPoolDefaults[n] = rPool.maPoolDefaults[n]->Clone(this); //resets kind + maPoolDefaults[n]->setPoolDefault(); } // Repair linkage - if ( rPool.pImpl->mpSecondary ) - SetSecondaryPool( rPool.pImpl->mpSecondary->Clone().get() ); + if ( rPool.mpSecondary ) + SetSecondaryPool( rPool.mpSecondary->Clone().get() ); } void SfxItemPool::SetDefaults( std::vector<SfxPoolItem*>* pDefaults ) { DBG_ASSERT( pDefaults, "first we ask for it, and then we don't give back..." ); - DBG_ASSERT( !pImpl->mpStaticDefaults, "already have Defaults" ); + DBG_ASSERT( !mpStaticDefaults, "already have Defaults" ); - pImpl->mpStaticDefaults = pDefaults; + mpStaticDefaults = pDefaults; //! if ((*mpStaticDefaults)->GetKind() != SfxItemKind::StaticDefault) //! FIXME: Probably doesn't work with SetItems at the end { - DBG_ASSERT( (*pImpl->mpStaticDefaults)[0]->GetRefCount() == 0 || - IsDefaultItem( (*pImpl->mpStaticDefaults)[0] ), + DBG_ASSERT( (*mpStaticDefaults)[0]->GetRefCount() == 0 || + IsDefaultItem( (*mpStaticDefaults)[0] ), "these are not static" ); - for ( sal_uInt16 n = 0; n <= pImpl->mnEnd - pImpl->mnStart; ++n ) + for ( sal_uInt16 n = 0; n <= mnEnd - mnStart; ++n ) { - assert( ((*pImpl->mpStaticDefaults)[n]->Which() == n + pImpl->mnStart) + assert( ((*mpStaticDefaults)[n]->Which() == n + mnStart) && "items ids in pool-ranges and in static-defaults do not match" ); - (*pImpl->mpStaticDefaults)[n]->setStaticDefault(); - DBG_ASSERT(nullptr == ppRegisteredSfxPoolItems || nullptr == ppRegisteredSfxPoolItems[n] - || ppRegisteredSfxPoolItems[n]->empty(), "defaults with setitems with items?!" ); + (*mpStaticDefaults)[n]->setStaticDefault(); } } } void SfxItemPool::ClearDefaults() { - pImpl->mpStaticDefaults = nullptr; + mpStaticDefaults = nullptr; } /** @@ -482,12 +562,12 @@ void SfxItemPool::ReleaseDefaults { - DBG_ASSERT( pImpl->mpStaticDefaults, "requirements not met" ); - ReleaseDefaults( pImpl->mpStaticDefaults, bDelete ); + DBG_ASSERT( mpStaticDefaults, "requirements not met" ); + ReleaseDefaults( mpStaticDefaults, bDelete ); // mpStaticDefaults points to deleted memory if bDelete == true. if ( bDelete ) - pImpl->mpStaticDefaults = nullptr; + mpStaticDefaults = nullptr; } @@ -536,73 +616,39 @@ void SfxItemPool::ReleaseDefaults SfxItemPool::~SfxItemPool() { // Need to be deleted? - // Caution: ppRegisteredSfxPoolItems is on-demand created and can be nullptr - if ( nullptr != ppRegisteredSfxPoolItems || !pImpl->maPoolDefaults.empty() ) + if (!mbPreDeleteDone)//maPoolDefaults.empty()) Delete(); - if (pImpl->mpMaster != nullptr && pImpl->mpMaster != this) + if (mpMaster != nullptr && mpMaster != this) { // This condition indicates an error. - // A pImpl->mpMaster->SetSecondaryPool(...) call should have been made + // A mpMaster->SetSecondaryPool(...) call should have been made // earlier to prevent this. At this point we can only try to // prevent a crash later on. - DBG_ASSERT( pImpl->mpMaster == this, "destroying active Secondary-Pool" ); - if (pImpl->mpMaster->pImpl->mpSecondary == this) - pImpl->mpMaster->pImpl->mpSecondary = nullptr; + DBG_ASSERT( mpMaster == this, "destroying active Secondary-Pool" ); + if (mpMaster->mpSecondary == this) + mpMaster->mpSecondary = nullptr; } } void SfxItemPool::SetSecondaryPool( SfxItemPool *pPool ) { // Reset Master in attached Pools - if ( pImpl->mpSecondary ) + if ( mpSecondary ) { -#ifdef DBG_UTIL - if (nullptr != pImpl->mpStaticDefaults - && nullptr != ppRegisteredSfxPoolItems - && nullptr != pImpl->mpSecondary->ppRegisteredSfxPoolItems) - // Delete() did not yet run? - { - // Does the Master have SetItems? - bool bHasSetItems(false); - - for (sal_uInt16 i(0); !bHasSetItems && i < pImpl->mnEnd - pImpl->mnStart; ++i) - { - const SfxPoolItem* pStaticDefaultItem((*pImpl->mpStaticDefaults)[i]); - bHasSetItems = pStaticDefaultItem->isSetItem(); - } - - if (bHasSetItems) - { - // Detached Pools must be empty - registeredSfxPoolItems** ppSet(pImpl->mpSecondary->ppRegisteredSfxPoolItems); - - for (sal_uInt16 a(0); a < pImpl->mpSecondary->GetSize_Impl(); a++, ppSet++) - { - if (nullptr != *ppSet && !(*ppSet)->empty()) - { - SAL_WARN("svl.items", "old secondary pool: " << pImpl->mpSecondary->pImpl->aName - << " of pool: " << pImpl->aName << " must be empty."); - break; - } - } - } - } -#endif - - pImpl->mpSecondary->pImpl->mpMaster = pImpl->mpSecondary.get(); - for ( SfxItemPool *p = pImpl->mpSecondary->pImpl->mpSecondary.get(); p; p = p->pImpl->mpSecondary.get() ) - p->pImpl->mpMaster = pImpl->mpSecondary.get(); + mpSecondary->mpMaster = mpSecondary.get(); + for ( SfxItemPool *p = mpSecondary->mpSecondary.get(); p; p = p->mpSecondary.get() ) + p->mpMaster = mpSecondary.get(); } // Set Master of new Secondary Pools - DBG_ASSERT( !pPool || pPool->pImpl->mpMaster == pPool, "Secondary is present in two Pools" ); - SfxItemPool *pNewMaster = GetMasterPool() ? pImpl->mpMaster : this; - for ( SfxItemPool *p = pPool; p; p = p->pImpl->mpSecondary.get() ) - p->pImpl->mpMaster = pNewMaster; + DBG_ASSERT( !pPool || pPool->mpMaster == pPool, "Secondary is present in two Pools" ); + SfxItemPool *pNewMaster = GetMasterPool() ? mpMaster : this; + for ( SfxItemPool *p = pPool; p; p = p->mpSecondary.get() ) + p->mpMaster = pNewMaster; // Remember new Secondary Pool - pImpl->mpSecondary = pPool; + mpSecondary = pPool; CHECK_SLOTS(); } @@ -616,24 +662,24 @@ void SfxItemPool::SetItemInfos(SfxItemInfo const*const pInfo) MapUnit SfxItemPool::GetMetric( sal_uInt16 ) const { - return pImpl->eDefMetric; + return eDefMetric; } void SfxItemPool::SetDefaultMetric( MapUnit eNewMetric ) { // assert((pImpl->eDefMetric == eNewMetric || !pImpl->mpPoolRanges) && "pool already frozen, cannot change metric"); - pImpl->eDefMetric = eNewMetric; + eDefMetric = eNewMetric; } MapUnit SfxItemPool::GetDefaultMetric() const { - return pImpl->eDefMetric; + return eDefMetric; } const OUString& SfxItemPool::GetName() const { - return pImpl->aName; + return aName; } @@ -659,74 +705,20 @@ rtl::Reference<SfxItemPool> SfxItemPool::Clone() const void SfxItemPool::Delete() { // Already deleted? - // Caution: ppRegisteredSfxPoolItems is on-demand created and can be nullptr - if (nullptr == ppRegisteredSfxPoolItems && pImpl->maPoolDefaults.empty()) + if (mbPreDeleteDone)//maPoolDefaults.empty()) return; + mbPreDeleteDone = true; // Inform e.g. running Requests - pImpl->aBC.Broadcast( SfxHint( SfxHintId::Dying ) ); + aBC.Broadcast( SfxHint( SfxHintId::Dying ) ); - // Iterate through twice: first for the SetItems. - if (nullptr != pImpl->mpStaticDefaults && nullptr != ppRegisteredSfxPoolItems) - { - for (size_t n = 0; n < GetSize_Impl(); ++n) - { - // *mpStaticDefaultItem could've already been deleted in a class derived - // from SfxItemPool - // This causes chaos in Itempool! - const SfxPoolItem* pStaticDefaultItem((*pImpl->mpStaticDefaults)[n]); - if (pStaticDefaultItem->isSetItem() && nullptr != ppRegisteredSfxPoolItems[n]) - { - // SfxSetItem found, remove PoolItems (and defaults) with same ID - auto& rArray(*(ppRegisteredSfxPoolItems[n])); - for (auto& rItemPtr : rArray) - { - ReleaseRef(*rItemPtr, rItemPtr->GetRefCount()); // for RefCount check in dtor - delete rItemPtr; - } - rArray.clear(); - // let pImpl->DeleteItems() delete item arrays in maPoolItems - auto& rItemPtr = pImpl->maPoolDefaults[n]; - if (rItemPtr) - { -#ifdef DBG_UTIL - ClearRefCount(*rItemPtr); -#endif - delete rItemPtr; - rItemPtr = nullptr; - } - } - } - } - - if (nullptr != ppRegisteredSfxPoolItems) - { - registeredSfxPoolItems** ppSet(ppRegisteredSfxPoolItems); - - for (sal_uInt16 a(0); a < GetSize_Impl(); a++, ppSet++) - { - if (nullptr != *ppSet) - { - for (auto& rCandidate : **ppSet) - { - if (nullptr != rCandidate && !IsDefaultItem(rCandidate)) - { - ReleaseRef(*rCandidate, rCandidate->GetRefCount()); // for RefCount check in dtor - delete rCandidate; - } - } - - delete *ppSet; - *ppSet = nullptr; - } - } - - delete[] ppRegisteredSfxPoolItems; - ppRegisteredSfxPoolItems = nullptr; - } + // delete direct put items, may assert here when not empty + for (const auto& rCand : maDirectPutItems) + delete rCand; + maDirectPutItems.clear(); // default items - for (auto rItemPtr : pImpl->maPoolDefaults) + for (auto rItemPtr : maPoolDefaults) { if (rItemPtr) { @@ -738,7 +730,8 @@ void SfxItemPool::Delete() } } - pImpl->DeleteItems(); + maPoolDefaults.clear(); + mpPoolRanges.reset(); } @@ -747,7 +740,7 @@ void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem) if ( IsInRange(rItem.Which()) ) { auto& rOldDefault = - pImpl->maPoolDefaults[GetIndex_Impl(rItem.Which())]; + maPoolDefaults[GetIndex_Impl(rItem.Which())]; SfxPoolItem *pNewDefault = rItem.Clone(this); pNewDefault->setPoolDefault(); if (rOldDefault) @@ -758,8 +751,8 @@ void SfxItemPool::SetPoolDefaultItem(const SfxPoolItem &rItem) } rOldDefault = pNewDefault; } - else if ( pImpl->mpSecondary ) - pImpl->mpSecondary->SetPoolDefaultItem(rItem); + else if ( mpSecondary ) + mpSecondary->SetPoolDefaultItem(rItem); else { assert(false && "unknown WhichId - cannot set pool default"); @@ -775,7 +768,7 @@ void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId ) if ( IsInRange(nWhichId) ) { auto& rOldDefault = - pImpl->maPoolDefaults[GetIndex_Impl(nWhichId)]; + maPoolDefaults[GetIndex_Impl(nWhichId)]; if (rOldDefault) { rOldDefault->SetRefCount(0); @@ -783,30 +776,24 @@ void SfxItemPool::ResetPoolDefaultItem( sal_uInt16 nWhichId ) rOldDefault = nullptr; } } - else if ( pImpl->mpSecondary ) - pImpl->mpSecondary->ResetPoolDefaultItem(nWhichId); + else if ( mpSecondary ) + mpSecondary->ResetPoolDefaultItem(nWhichId); else { assert(false && "unknown WhichId - cannot reset pool default"); } } -const SfxPoolItem& SfxItemPool::DirectPutItemInPoolImpl(const SfxPoolItem& rItem, sal_uInt16 nWhich, bool bPassingOwnership) +const SfxPoolItem& SfxItemPool::DirectPutItemInPool(const SfxPoolItem& rItem) { #ifdef DBG_UTIL nAllDirectlyPooledSfxPoolItemCount++; nRemainingDirectlyPooledSfxPoolItemCount++; #endif - - // make sure to use 'master'-pool, that's the one used by SfxItemSets - const SfxPoolItem* pRetval(implCreateItemEntry(*GetMasterPool(), &rItem, nWhich, bPassingOwnership)); - - // For the moment, as long as DirectPutItemInPoolImpl is used, make sure that - // the changes in implCreateItemEntry do not change anything, that would - // risc memory leaks by not (ab)using the garbage collector aspect of the pool. - registerSfxPoolItem(*pRetval); - - return *pRetval; + // use SfxPoolItemHolder now to secure lifetime + SfxPoolItemHolder* pHolder(new SfxPoolItemHolder(*GetMasterPool(), &rItem)); + GetMasterPool()->maDirectPutItems.insert(pHolder); + return *pHolder->getItem(); } void SfxItemPool::DirectRemoveItemFromPool(const SfxPoolItem& rItem) @@ -814,31 +801,36 @@ void SfxItemPool::DirectRemoveItemFromPool(const SfxPoolItem& rItem) #ifdef DBG_UTIL nRemainingDirectlyPooledSfxPoolItemCount--; #endif - - // make sure to use 'master'-pool, that's the one used by SfxItemSets - implCleanupItemEntry(*GetMasterPool(), &rItem); + directPutSfxPoolItemHolders& rDirects(GetMasterPool()->maDirectPutItems); + for (directPutSfxPoolItemHolders::iterator aIter(rDirects.begin()); aIter != rDirects.end(); aIter++) + if ((*aIter)->getItem() == &rItem) + { + delete *aIter; + rDirects.erase(aIter); + break; + } } const SfxPoolItem& SfxItemPool::GetDefaultItem( sal_uInt16 nWhich ) const { if ( !IsInRange(nWhich) ) { - if ( pImpl->mpSecondary ) - return pImpl->mpSecondary->GetDefaultItem( nWhich ); + if ( mpSecondary ) + return mpSecondary->GetDefaultItem( nWhich ); assert(!"unknown which - don't ask me for defaults"); } - DBG_ASSERT( pImpl->mpStaticDefaults, "no defaults known - don't ask me for defaults" ); + DBG_ASSERT( mpStaticDefaults, "no defaults known - don't ask me for defaults" ); sal_uInt16 nPos = GetIndex_Impl(nWhich); - SfxPoolItem* pDefault = pImpl->maPoolDefaults[nPos]; + SfxPoolItem* pDefault = maPoolDefaults[nPos]; if ( pDefault ) return *pDefault; - return *(*pImpl->mpStaticDefaults)[nPos]; + return *(*mpStaticDefaults)[nPos]; } SfxItemPool* SfxItemPool::GetSecondaryPool() const { - return pImpl->mpSecondary.get(); + return mpSecondary.get(); } /* get the last pool by following the GetSecondaryPool chain */ @@ -852,7 +844,7 @@ SfxItemPool* SfxItemPool::GetLastPoolInChain() SfxItemPool* SfxItemPool::GetMasterPool() const { - return pImpl->mpMaster; + return mpMaster; } /** @@ -864,125 +856,95 @@ SfxItemPool* SfxItemPool::GetMasterPool() const */ void SfxItemPool::FreezeIdRanges() { - assert(pImpl->mpPoolRanges.empty() && "pool already frozen, cannot freeze twice"); - FillItemIdRanges_Impl( pImpl->mpPoolRanges ); + assert(mpPoolRanges.empty() && "pool already frozen, cannot freeze twice"); + FillItemIdRanges_Impl( mpPoolRanges ); } void SfxItemPool::FillItemIdRanges_Impl( WhichRangesContainer& pWhichRanges ) const { - DBG_ASSERT( pImpl->mpPoolRanges.empty(), "GetFrozenRanges() would be faster!" ); + DBG_ASSERT( mpPoolRanges.empty(), "GetFrozenRanges() would be faster!" ); pWhichRanges.reset(); // Merge all ranges, keeping them sorted - for (const SfxItemPool* pPool = this; pPool; pPool = pPool->pImpl->mpSecondary.get()) - pWhichRanges = pWhichRanges.MergeRange(pPool->pImpl->mnStart, pPool->pImpl->mnEnd); + for (const SfxItemPool* pPool = this; pPool; pPool = pPool->mpSecondary.get()) + pWhichRanges = pWhichRanges.MergeRange(pPool->mnStart, pPool->mnEnd); } const WhichRangesContainer& SfxItemPool::GetFrozenIdRanges() const { - return pImpl->mpPoolRanges; + return mpPoolRanges; } const SfxPoolItem *SfxItemPool::GetItem2Default(sal_uInt16 nWhich) const { if ( !IsInRange(nWhich) ) { - if ( pImpl->mpSecondary ) - return pImpl->mpSecondary->GetItem2Default( nWhich ); + if ( mpSecondary ) + return mpSecondary->GetItem2Default( nWhich ); assert(false && "unknown WhichId - cannot resolve surrogate"); return nullptr; } - return (*pImpl->mpStaticDefaults)[ GetIndex_Impl(nWhich) ]; + return (*mpStaticDefaults)[ GetIndex_Impl(nWhich) ]; } -#ifdef DBG_UTIL -static void warnForMissingPoolRegistration(const SfxItemPool& rPool, sal_uInt16 nWhich) -{ - if (!rPool.NeedsPoolRegistration(nWhich)) - SAL_INFO("svl.items", "ITEM: ItemSurrogate requested for WhichID " << nWhich << - " class " << typeid(rPool.GetDefaultItem(nWhich)).name() << - ": needs _bNeedsPoolRegistration==true in SfxItemInfo for that slot"); -} -#endif - -const registeredSfxPoolItems& SfxItemPool::GetItemSurrogates(sal_uInt16 nWhich) const +void SfxItemPool::CollectSurrogates(std::unordered_set<const SfxPoolItem*>& rTarget, sal_uInt16 nWhich) const { - static const registeredSfxPoolItems EMPTY; + rTarget.clear(); - if (!IsInRange(nWhich)) - { - if (pImpl->mpSecondary) - return pImpl->mpSecondary->GetItemSurrogates(nWhich); - return EMPTY; - } + if (0 == nWhich) + return; - if (nullptr == ppRegisteredSfxPoolItems) - { + // 1st source for surrogates + const registeredSfxItemSets& rSets(GetMasterPool()->maRegisteredSfxItemSets); + const SfxPoolItem* pItem(nullptr); + for (const auto& rCand : rSets) + if (SfxItemState::SET == rCand->GetItemState(nWhich, false, &pItem)) + rTarget.insert(pItem); + + // 2nd source for surrogates + const registeredSfxPoolItemHolders& rHolders(GetMasterPool()->maRegisteredSfxPoolItemHolders); + for (const auto& rCand : rHolders) + if (rCand->Which() == nWhich && nullptr != rCand->getItem()) + rTarget.insert(rCand->getItem()); + + // the 3rd source for surrogates is the list of direct put items + // but since these use SfxPoolItemHolder now they are automatically + // registered at 2nd source - IF NeedsPoolRegistration is set. So + // as long as we have this DirectPutItem stuff, iterate here and + // warn if an Item was added + const directPutSfxPoolItemHolders& rDirects(GetMasterPool()->maDirectPutItems); #ifdef DBG_UTIL - warnForMissingPoolRegistration(*this, nWhich); + const size_t aBefore(rTarget.size()); #endif - return EMPTY; - } - - registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nWhich - pImpl->mnStart]); - - if (nullptr == pSet) - { + for (const auto& rCand : rDirects) + if (rCand->Which() == nWhich && nullptr != rCand->getItem()) + rTarget.insert(rCand->getItem()); #ifdef DBG_UTIL - warnForMissingPoolRegistration(*this, nWhich); -#endif - return EMPTY; - } - - return *pSet; -} - -std::vector<const SfxPoolItem*> SfxItemPool::FindItemSurrogate(sal_uInt16 nWhich, SfxPoolItem const & rSample) const -{ - static const std::vector<const SfxPoolItem*> EMPTY; - - if (nullptr == ppRegisteredSfxPoolItems) - return EMPTY; - - if ( !IsInRange(nWhich) ) + const size_t aAfter(rTarget.size()); + if (aBefore != aAfter) { - if ( pImpl->mpSecondary ) - return pImpl->mpSecondary->FindItemSurrogate( nWhich, rSample ); - assert(false && "unknown WhichId - cannot resolve surrogate"); - return EMPTY; + SAL_WARN("svl.items", "SfxItemPool: Found non-automatically registered Item for Surrogates in DirectPutItems (!)"); } - - // get index (must exist due to checks above) - const sal_uInt16 nIndex(rSample.Which() - pImpl->mnStart); - - if (nullptr == ppRegisteredSfxPoolItems) - { -#ifdef DBG_UTIL - warnForMissingPoolRegistration(*this, nWhich); #endif - return EMPTY; - } - - // get registeredSfxPoolItems container - registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]); - - if (nullptr == pSet) - { -#ifdef DBG_UTIL - warnForMissingPoolRegistration(*this, nWhich); -#endif - return EMPTY; - } - - std::vector<const SfxPoolItem*> rv; +} - for (const SfxPoolItem* p : *pSet) - if (rSample == *p) - rv.push_back(p); +void SfxItemPool::GetItemSurrogates(ItemSurrogates& rTarget, sal_uInt16 nWhich) const +{ + std::unordered_set<const SfxPoolItem*> aNewSurrogates; + CollectSurrogates(aNewSurrogates, nWhich); + rTarget = ItemSurrogates(aNewSurrogates.begin(), aNewSurrogates.end()); +} - return rv; +void SfxItemPool::FindItemSurrogate(ItemSurrogates& rTarget, sal_uInt16 nWhich, SfxPoolItem const & rSample) const +{ + std::unordered_set<const SfxPoolItem*> aNewSurrogates; + CollectSurrogates(aNewSurrogates, nWhich); + rTarget.clear(); + for (const auto& rCand : aNewSurrogates) + if (rSample == *rCand) + rTarget.push_back(rCand); } sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, bool bDeep ) const @@ -990,12 +952,12 @@ sal_uInt16 SfxItemPool::GetWhich( sal_uInt16 nSlotId, bool bDeep ) const if ( !IsSlot(nSlotId) ) return nSlotId; - sal_uInt16 nCount = pImpl->mnEnd - pImpl->mnStart + 1; + sal_uInt16 nCount = mnEnd - mnStart + 1; for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) if ( pItemInfos[nOfs]._nSID == nSlotId ) - return nOfs + pImpl->mnStart; - if ( pImpl->mpSecondary && bDeep ) - return pImpl->mpSecondary->GetWhich(nSlotId); + return nOfs + mnStart; + if ( mpSecondary && bDeep ) + return mpSecondary->GetWhich(nSlotId); return nSlotId; } @@ -1007,13 +969,13 @@ sal_uInt16 SfxItemPool::GetSlotId( sal_uInt16 nWhich ) const if ( !IsInRange( nWhich ) ) { - if ( pImpl->mpSecondary ) - return pImpl->mpSecondary->GetSlotId(nWhich); + if ( mpSecondary ) + return mpSecondary->GetSlotId(nWhich); assert(false && "unknown WhichId - cannot get slot-id"); return 0; } - sal_uInt16 nSID = pItemInfos[nWhich - pImpl->mnStart]._nSID; + sal_uInt16 nSID = pItemInfos[nWhich - mnStart]._nSID; return nSID ? nSID : nWhich; } @@ -1023,12 +985,12 @@ sal_uInt16 SfxItemPool::GetTrueWhich( sal_uInt16 nSlotId, bool bDeep ) const if ( !IsSlot(nSlotId) ) return 0; - sal_uInt16 nCount = pImpl->mnEnd - pImpl->mnStart + 1; + sal_uInt16 nCount = mnEnd - mnStart + 1; for ( sal_uInt16 nOfs = 0; nOfs < nCount; ++nOfs ) if ( pItemInfos[nOfs]._nSID == nSlotId ) - return nOfs + pImpl->mnStart; - if ( pImpl->mpSecondary && bDeep ) - return pImpl->mpSecondary->GetTrueWhich(nSlotId); + return nOfs + mnStart; + if ( mpSecondary && bDeep ) + return mpSecondary->GetTrueWhich(nSlotId); return 0; } @@ -1040,192 +1002,12 @@ sal_uInt16 SfxItemPool::GetTrueSlotId( sal_uInt16 nWhich ) const if ( !IsInRange( nWhich ) ) { - if ( pImpl->mpSecondary ) - return pImpl->mpSecondary->GetTrueSlotId(nWhich); + if ( mpSecondary ) + return mpSecondary->GetTrueSlotId(nWhich); assert(false && "unknown WhichId - cannot get slot-id"); return 0; } - return pItemInfos[nWhich - pImpl->mnStart]._nSID; -} - -void SfxItemPool::registerSfxPoolItem(const SfxPoolItem& rItem) -{ - assert(rItem.Which() != 0); - - if (IsSlot(rItem.Which())) - // do not register SlotItems - return; - - if (rItem.isRegisteredAtPool()) - // already registered, done - return; - - if (!IsInRange(rItem.Which())) - { - // get to the right pool - if (pImpl->mpSecondary) - { - pImpl->mpSecondary->registerSfxPoolItem(rItem); - return; - } - - return; - } - - if (nullptr == ppRegisteredSfxPoolItems) - // on-demand allocate array of registeredSfxPoolItems and init to nullptr - ppRegisteredSfxPoolItems = new registeredSfxPoolItems*[GetSize_Impl()]{}; - - // get correct registeredSfxPoolItems - const sal_uInt16 nIndex(rItem.Which() - pImpl->mnStart); - registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]); - - if (nullptr == pSet) - // on-demand allocate - ppRegisteredSfxPoolItems[nIndex] = pSet = new registeredSfxPoolItems; - - // insert to registeredSfxPoolItems and set flag at Item - pSet->insert(&rItem); - const_cast<SfxPoolItem&>(rItem).setRegisteredAtPool(true); -} - -void SfxItemPool::unregisterSfxPoolItem(const SfxPoolItem& rItem) -{ - if (!rItem.isRegisteredAtPool()) - // Item is not registered, done - return; - - if (!IsInRange(rItem.Which())) - { - // get to the right pool - if (pImpl->mpSecondary) - { - pImpl->mpSecondary->unregisterSfxPoolItem(rItem); - return; - } - - assert(false && "unknown WhichId - cannot execute unregisterSfxPoolItem"); - return; - } - - // we need a valid WhichID and the array of containers has to exist - assert(rItem.Which() != 0); - assert(nullptr != ppRegisteredSfxPoolItems); - - // get index (must exist due to checks above) - const sal_uInt16 nIndex(rItem.Which() - pImpl->mnStart); - - // a valid registeredSfxPoolItems container has to exist - registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]); - assert(nullptr != pSet); - - // remove registered Item and reset flag at Item - pSet->erase(&rItem); - const_cast<SfxPoolItem&>(rItem).setRegisteredAtPool(false); -} - -bool SfxItemPool::isSfxPoolItemRegisteredAtThisPool(const SfxPoolItem& rItem) const -{ - if (!rItem.isRegisteredAtPool()) - // Item is not registered at all, so also not at this Pool - return false; - - if (IsSlot(rItem.Which())) - // do not check being registered for SlotItems - return false; - - if (!IsInRange(rItem.Which())) - { - // get to the right pool - if (pImpl->mpSecondary) - return pImpl->mpSecondary->isSfxPoolItemRegisteredAtThisPool(rItem); - return false; - } - - // we need a valid WhichID - assert(rItem.Which() != 0); - - if (nullptr == ppRegisteredSfxPoolItems) - // when no array of containers exists the Item is not registered - return false; - - // get index (must exist due to checks above) - const sal_uInt16 nIndex(rItem.Which() - pImpl->mnStart); - - // get registeredSfxPoolItems container - registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]); - - if (nullptr == pSet) - // when no registeredSfxPoolItems container exists the Item is not registered - return false; - - // test if Item is registered - return pSet->find(&rItem) != pSet->end(); -} - -const SfxPoolItem* SfxItemPool::tryToGetEqualItem(const SfxPoolItem& rItem, sal_uInt16 nWhich) const -{ - if (IsSlot(nWhich)) - // SlotItems are not registered @pool and not in any range - return nullptr; - - if (!IsInRange(nWhich)) - { - // get to the right pool - if (pImpl->mpSecondary) - return pImpl->mpSecondary->tryToGetEqualItem(rItem, nWhich); - return nullptr; - } - - if (nullptr == ppRegisteredSfxPoolItems) - // no Items at all - return nullptr; - - // get index (must exist due to checks above) - const sal_uInt16 nIndex(nWhich - pImpl->mnStart); - - if (!Shareable_Impl(nIndex)) - // not shareable - return nullptr; - - // get registeredSfxPoolItems container - registeredSfxPoolItems* pSet(ppRegisteredSfxPoolItems[nIndex]); - - if (nullptr == pSet) - // no registeredSfxPoolItems for this WhichID - return nullptr; - - for (const auto& rCandidate : *pSet) - if (*rCandidate == rItem) - return rCandidate; - - return nullptr; -} - -void SfxItemPool::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxItemPool")); - - if (nullptr != ppRegisteredSfxPoolItems) - { - registeredSfxPoolItems** ppSet(ppRegisteredSfxPoolItems); - - for (sal_uInt16 a(0); a < GetSize_Impl(); a++, ppSet++) - { - if (nullptr != *ppSet) - { - for (auto& rCandidate : **ppSet) - { - if (nullptr != rCandidate) - { - rCandidate->dumpAsXml(pWriter); - } - } - } - } - } - - (void)xmlTextWriterEndElement(pWriter); + return pItemInfos[nWhich - mnStart]._nSID; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index 3b8a77f8186f..41051a981aa4 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -50,7 +50,6 @@ size_t getUsedSfxPoolItemHolderCount() { return nUsedSfxPoolItemHolderCount; } // ScPatternAttr). Still keep it so that when errors // come up to this change be able to quickly check using the // fallback flag 'ITEM_CLASSIC_MODE' -static bool g_bItemClassicMode(getenv("ITEM_CLASSIC_MODE")); // I thought about this constructor a while, but when there is no // Item we need no cleanup at destruction (what we would need the @@ -83,7 +82,9 @@ SfxPoolItemHolder::SfxPoolItemHolder(SfxItemPool& rPool, const SfxPoolItem* pIte nUsedSfxPoolItemHolderCount++; #endif if (nullptr != m_pItem) - m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), bPassingOwnership); + m_pItem = implCreateItemEntry(getPool(), m_pItem, m_pItem->Which(), bPassingOwnership); + if (nullptr != m_pItem && getPool().NeedsPoolRegistration(m_pItem->Which())) + getPool().registerPoolItemHolder(*this); } SfxPoolItemHolder::SfxPoolItemHolder(const SfxPoolItemHolder& rHolder) @@ -99,7 +100,9 @@ SfxPoolItemHolder::SfxPoolItemHolder(const SfxPoolItemHolder& rHolder) nUsedSfxPoolItemHolderCount++; #endif if (nullptr != m_pItem) - m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false); + m_pItem = implCreateItemEntry(getPool(), m_pItem, m_pItem->Which(), false); + if (nullptr != m_pItem && getPool().NeedsPoolRegistration(m_pItem->Which())) + getPool().registerPoolItemHolder(*this); } SfxPoolItemHolder::~SfxPoolItemHolder() @@ -108,8 +111,10 @@ SfxPoolItemHolder::~SfxPoolItemHolder() assert(!isDeleted() && "Destructed instance used (!)"); nAllocatedSfxPoolItemHolderCount--; #endif + if (nullptr != m_pItem && getPool().NeedsPoolRegistration(m_pItem->Which())) + getPool().unregisterPoolItemHolder(*this); if (nullptr != m_pItem) - implCleanupItemEntry(*m_pPool, m_pItem); + implCleanupItemEntry(m_pItem); #ifdef DBG_UTIL m_bDeleted = true; #endif @@ -122,14 +127,18 @@ const SfxPoolItemHolder& SfxPoolItemHolder::operator=(const SfxPoolItemHolder& r if (this == &rHolder || *this == rHolder) return *this; + if (nullptr != m_pItem && getPool().NeedsPoolRegistration(m_pItem->Which())) + getPool().unregisterPoolItemHolder(*this); if (nullptr != m_pItem) - implCleanupItemEntry(*m_pPool, m_pItem); + implCleanupItemEntry(m_pItem); m_pPool = rHolder.m_pPool; m_pItem = rHolder.m_pItem; if (nullptr != m_pItem) - m_pItem = implCreateItemEntry(*m_pPool, m_pItem, m_pItem->Which(), false); + m_pItem = implCreateItemEntry(getPool(), m_pItem, m_pItem->Which(), false); + if (nullptr != m_pItem && getPool().NeedsPoolRegistration(m_pItem->Which())) + getPool().registerPoolItemHolder(*this); return *this; } @@ -154,6 +163,7 @@ SfxItemSet::SfxItemSet(SfxItemPool& rPool) : m_pPool(&rPool) , m_pParent(nullptr) , m_nCount(0) + , m_nRegister(0) , m_nTotalCount(svl::detail::CountRanges(rPool.GetFrozenIdRanges())) , m_bItemsFixed(false) , m_ppItems(new SfxPoolItem const *[m_nTotalCount]{}) @@ -171,6 +181,7 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, SfxAllItemSetFlag ) : m_pPool(&rPool) , m_pParent(nullptr) , m_nCount(0) + , m_nRegister(0) , m_nTotalCount(0) , m_bItemsFixed(false) , m_ppItems(nullptr) @@ -188,6 +199,7 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, WhichRangesContainer&& ranges, SfxPo : m_pPool(&rPool) , m_pParent(nullptr) , m_nCount(0) + , m_nRegister(0) , m_nTotalCount(nTotalCount) , m_bItemsFixed(true) , m_ppItems(ppItems) @@ -209,6 +221,7 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rOther, : m_pPool(rOther.m_pPool) , m_pParent(rOther.m_pParent) , m_nCount(rOther.m_nCount) + , m_nRegister(rOther.m_nRegister) , m_nTotalCount(rOther.m_nTotalCount) , m_bItemsFixed(true) , m_ppItems(ppMyItems) @@ -234,12 +247,16 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rOther, *ppDst = implCreateItemEntry(*GetPool(), rSource, 0, false); ppDst++; } + + if (0 != m_nRegister) + GetPool()->registerItemSet(*this); } SfxItemSet::SfxItemSet(SfxItemPool& pool, WhichRangesContainer wids) : m_pPool(&pool) , m_pParent(nullptr) , m_nCount(0) + , m_nRegister(0) , m_nTotalCount(svl::detail::CountRanges(wids)) , m_bItemsFixed(false) , m_ppItems(new SfxPoolItem const *[m_nTotalCount]{}) @@ -278,9 +295,13 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS // return pSource; if (0 == pSource->Which()) + { // These *should* be SfxVoidItem(0) the only Items with 0 == WhichID, // these need to be cloned (currently...) + if (bPassingOwnership) + return pSource; return pSource->Clone(); + } // get correct target WhichID if (0 == nWhich) @@ -321,6 +342,46 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS return pSource; } + // // currently need to check if pSource is a default Item and + // // avoid it to leave the Pool. This is necessary since Pools + // // currently delete their default items hard, resetting RefCnt + // // and killing them. This might change after a Pool refinement. + // // For now, replace them with the local Pool default. It *might* + // // be even necessary to replace with a cloned non-default instance + // // if the defaults differ. + // // NOTE: Currently even some Pools have no 'real' StaticDefaults, + // // but these also get deleted (sigh) + // if (IsStaticDefaultItem(pSource)) + // { + // assert(!bPassingOwnership && "ITEM: PassingOwnership not possible combined with StaticDefault (!)"); + // const SfxPoolItem* pStatic(pTargetPool->GetItem2Default(nWhich)); + // if (nullptr != pStatic) + // { + // if (SfxPoolItem::areSame(pSource, pStatic)) + // pSource = pStatic; + // else + // { + // pSource = pSource->Clone(pMasterPool); + // bPassingOwnership = true; + // } + // } + // } + // else if (IsDefaultItem(pSource)) + // { + // assert(!bPassingOwnership && "ITEM: PassingOwnership not possible combined with DynaimcDefault (!)"); + // const SfxPoolItem* pDynamic(pTargetPool->GetPoolDefaultItem(nWhich)); + // if (nullptr != pDynamic) + // { + // if (SfxPoolItem::areSame(pSource, pDynamic)) + // pSource = pDynamic; + // else + // { + // pSource = pSource->Clone(pMasterPool); + // bPassingOwnership = true; + // } + // } + // } + // CAUTION: Shareable_Impl and NeedsPoolRegistration_Impl // use index, not WhichID (one more reason to change the Pools) const sal_uInt16 nIndex(pTargetPool->GetIndex_Impl(nWhich)); @@ -351,49 +412,11 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS if (pSource->isSetItem() && static_cast<const SfxSetItem*>(pSource)->GetItemSet().GetPool() != pMasterPool) break; - // If the Item is registered it is pool-dependent, so do not share when - // it is registered but not at this pool - if (pSource->isRegisteredAtPool() && !pTargetPool->isSfxPoolItemRegisteredAtThisPool(*pSource)) - break; - // If we get here we can share the Item pSource->AddRef(); return pSource; } - // g_bItemClassicMode: try finding already existing item - // NOTE: the UnitTest testIteratorsDefPattern claims that that Item "can be - // edited by the user" which explains why it breaks so many rules for Items, - // it behaves like an alien. That Item in the SC Pool claims to be a - // 'StaticDefault' and gets changed (..?) - - // only do this if classic mode or required (calls from Pool::Direct*) - while(g_bItemClassicMode) - { - if (!pTargetPool->Shareable_Impl(nIndex)) - // not shareable, so no need to search for identical item - break; - - // try to get equal Item. This is the expensive part... - const SfxPoolItem* pExisting(pTargetPool->tryToGetEqualItem(*pSource, nWhich)); - - if (nullptr == pExisting) - // none found, done - break; - - if (0 == pExisting->GetRefCount()) - // do not share not-yet shared Items (should not happen) - break; - - if (bPassingOwnership) - // need to cleanup if we are offered to own pSource - delete pSource; - - // If we get here we can share the found Item - pExisting->AddRef(); - return pExisting; - } - // check if the handed over and to be directly used item is a // SfxSetItem, that would make it pool-dependent. It then must have // the same target-pool, ensure that by the cost of cloning it @@ -419,30 +442,10 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS // increase RefCnt 0->1 pSource->AddRef(); - // try to register @Pool (only needed if not yet registered) - if (!pSource->isRegisteredAtPool()) - { - bool bRegisterAtPool(false); - - if (g_bItemClassicMode) - { - // in classic mode register only/all shareable items - bRegisterAtPool = pTargetPool->Shareable_Impl(nIndex); - } - else - { - // in new mode register only/all items marked as need to be registered - bRegisterAtPool = pTargetPool->NeedsPoolRegistration_Impl(nIndex); - } - - if (bRegisterAtPool) - pTargetPool->registerSfxPoolItem(*pSource); - } - return pSource; } -void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource) +void implCleanupItemEntry(SfxPoolItem const* pSource) { if (nullptr == pSource) // no entry, done @@ -454,10 +457,6 @@ void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource) if (0 == pSource->Which()) { - // de-register when registered @pool - if (pSource->isRegisteredAtPool()) - rPool.unregisterSfxPoolItem(*pSource); - // These *should* be SfxVoidItem(0) the only Items with 0 == WhichID // and need to be deleted delete pSource; @@ -479,10 +478,6 @@ void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource) // good to find other errors) pSource->ReleaseRef(); - // de-register before deletion when registered @pool - if (pSource->isRegisteredAtPool()) - rPool.unregisterSfxPoolItem(*pSource); - // delete Item delete pSource; } @@ -491,6 +486,7 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) : m_pPool( rASet.m_pPool ) , m_pParent( rASet.m_pParent ) , m_nCount( rASet.m_nCount ) + , m_nRegister( rASet.m_nRegister ) , m_nTotalCount( rASet.m_nTotalCount ) , m_bItemsFixed(false) , m_ppItems(nullptr) @@ -502,9 +498,7 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) nUsedSfxItemSetCount++; #endif if (rASet.GetRanges().empty()) - { return; - } if (0 == rASet.Count()) { @@ -527,12 +521,15 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) } assert(svl::detail::validRanges2(m_pWhichRanges)); + if (0 != m_nRegister) + GetPool()->registerItemSet(*this); } SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept : m_pPool( rASet.m_pPool ) , m_pParent( rASet.m_pParent ) , m_nCount( rASet.m_nCount ) + , m_nRegister( rASet.m_nRegister ) , m_nTotalCount( rASet.m_nTotalCount ) , m_bItemsFixed(false) , m_ppItems( rASet.m_ppItems ) @@ -550,18 +547,27 @@ SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept // can just copy the pointers, the ones in the original m_ppItems // array will no longer be used/referenced (unused mem, but not lost, - // it's part of the ItemSet-derived object) + // it's part of the ItemSet-derived object). std::copy(rASet.m_ppItems, rASet.m_ppItems + TotalCount(), m_ppItems); } - else - { - // taking over ownership - rASet.m_nTotalCount = 0; - rASet.m_ppItems = nullptr; - } + + // deregister if rASet is registered before ptrs vanish + if (0 != rASet.m_nRegister) + rASet.GetPool()->unregisterItemSet(rASet); + + // register if new set needs that + if (0 != m_nRegister) + GetPool()->registerItemSet(*this); + + // taking over ownership rASet.m_pPool = nullptr; rASet.m_pParent = nullptr; rASet.m_nCount = 0; + rASet.m_nRegister = 0; + rASet.m_nTotalCount = 0; + rASet.m_ppItems = nullptr; + rASet.m_pWhichRanges.reset(); + rASet.m_aCallback = nullptr; assert(svl::detail::validRanges2(m_pWhichRanges)); } @@ -614,6 +620,65 @@ sal_uInt16 SfxItemSet::ClearSingleItem_ForWhichID( sal_uInt16 nWhich ) return 0; } +void SfxItemSet::checkRemovePoolRegistration(const SfxPoolItem* pItem) +{ + if (nullptr == pItem) + // no Item, done + return; + + if (IsInvalidItem(pItem) || pItem->isVoidItem() || 0 == pItem->Which()) + // checks IsInvalidItem/SfxVoidItem(0) + return; + + if (SfxItemPool::IsSlot(pItem->Which())) + // no slots, these do not support NeedsPoolRegistration + return; + + if(!GetPool()->NeedsPoolRegistration(pItem->Which())) + // not needed for this item, done + return; + + // there must be a registered one + assert(0 != m_nRegister); + + // decrement counter + m_nRegister--; + -e ... etc. - the rest is truncated