summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2024-01-22 15:43:05 +0100
committerArmin Le Grand <Armin.Le.Grand@me.com>2024-01-23 18:56:12 +0100
commit063781f4a94e3960a2cb40d1981c0e0ef9a73153 (patch)
treea3742b559c96202eacf220901f6db7592b538805
parentmake the macro assign dialog async (diff)
downloadcore-063781f4a94e3960a2cb40d1981c0e0ef9a73153.tar.gz
core-063781f4a94e3960a2cb40d1981c0e0ef9a73153.zip
tdf#158605 Add global SfxPoolItem re-use
The task shows that the commit including the Item paradigm change has follow-ups: It now does no longer try to share Items as much as possible (detailed reasons in that commit). Mainly for speed reasons since that sharing was done before by (mostly) linearly searching in existing instances registered at one Pool, using the operator== of the SfxPoolItems. That costs runtime. There is somewhere a sweet-spot between memory and runtime: the number of Items allocated and the time spent to share them more effectively. This task shows - despite being a non-real-world document - that for extremes like this putting work in sharing is still needed. But there are possibilities to combine both: If we can implement solutions that do not need much time to ideintify an aleady existing instance we will get the best of both worlds. As explained already in that change, if we would need that again, then on a better base. Thus I drove forward ITEM changes to a state where we are now able to share Items globally in the office - not per pool but for all ItemSets/ItemHolders and thus all Apps/ Models/opened documents. NOTE: This currently needs to include the WhichID that is included in the Item, so cannot share pure Item-data (as the old usage did too). This does not need to stay that way: If you think about it, the association between WhichID and Pool/Holder is defined in Pool/Holder, so theoretically the Item does not need to contain the WhichID. This will be hard to do due too many places in the code that use the WhichID stored at the Item. To support that I added an ItemInstanceManager with a simple interface (find/add/remove) and it's usage in the two central Item-existance managing methods implCreateItemEntry/implCleanupItemEntry. The interface is pure virtual and all methods private, only the mentioned managing methods are allowed to access these. Also added a virtual method to SfxPoolItem called getItemInstanceManager() that can be implemented by Items that want to support that. Also added a default implementation of ItemInstanceManager called DefaultItemInstanceManager that uses linear search using operator== from the Item that can be used/added to every Item easily. It works for all Items and does in principle what the former implementation does. It is intended as simple/fast fallback. I also added a statistic element to measure the most used non-RefCounted Items on an Office-run, this will be printed at office shutdown using SAL_LOG and the 'svl.items' flag. I then checked all Items that were used in this error/bug scenario that used an extensive number of incarnations and added an ItemInstanceManager for these. For SvxFontItem I added one that creates a hash and thus needs not to search for instances at all, with the caveat that the WhichID needs to be included. Thus the hash is not at the Item, but only in the ItemInstanceManager implementation. For SfxBoolItem I implemented one that hashes using the WhichID and holding both possible states in an associated std::pair, true and false, thus the SfxBoolItem is identified fast and only two instances per WhichID exist (when used in Pool/Holder). For 11 other Items I just added using the standard implementation, DefaultItemInstanceManager. Of course the more we optimize the better it will get. For all Items where I added that mechanism I also added ASSERT_CHANGE_REFCOUNTED_ITEM to all write calls/methods for that Item. It asserts when the RefCounted Item is to be changed. This should be done in all write accesses to Items, but we have ca. 500 derivations. NOTE: There was *one* place I found where that was already done -> was alredy seen as problem, but not really adressed. Despite this example file is not representative, it is still a start to init this new instance re-use of Items. I am already thinking about doing that globally, depending on the usage number (maybe combined with sizeof(item)). There is no argument to not even change strategy at runtime when a specific number of incarnations of one Item derivation is reached, but this is not part of this fix. Change-Id: Ie56cf40e0341f98dcbf29cf5c06368316829415e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162402 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
-rw-r--r--editeng/source/items/frmitems.cxx33
-rw-r--r--editeng/source/items/paraitem.cxx7
-rw-r--r--editeng/source/items/textitem.cxx224
-rw-r--r--include/editeng/adjustitem.hxx7
-rw-r--r--include/editeng/brushitem.hxx16
-rw-r--r--include/editeng/charreliefitem.hxx3
-rw-r--r--include/editeng/crossedoutitem.hxx3
-rw-r--r--include/editeng/emphasismarkitem.hxx3
-rw-r--r--include/editeng/fhgtitem.hxx6
-rw-r--r--include/editeng/fontitem.hxx28
-rw-r--r--include/editeng/frmdiritem.hxx3
-rw-r--r--include/editeng/langitem.hxx3
-rw-r--r--include/editeng/postitem.hxx3
-rw-r--r--include/editeng/udlnitem.hxx9
-rw-r--r--include/editeng/wghtitem.hxx3
-rw-r--r--include/svl/eitem.hxx6
-rw-r--r--include/svl/itemset.hxx1
-rw-r--r--include/svl/poolitem.hxx50
-rw-r--r--svl/source/items/cenumitm.cxx85
-rw-r--r--svl/source/items/itemset.cxx98
-rw-r--r--svl/source/items/poolitem.cxx17
-rw-r--r--vcl/source/app/svapp.cxx3
22 files changed, 550 insertions, 61 deletions
diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx
index 94b7704303ba..c3a5836b082a 100644
--- a/editeng/source/items/frmitems.cxx
+++ b/editeng/source/items/frmitems.cxx
@@ -3978,6 +3978,12 @@ void SvxLineItem::SetLine( const SvxBorderLine* pNew )
pLine.reset( pNew ? new SvxBorderLine( *pNew ) : nullptr );
}
+ItemInstanceManager* SvxBrushItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxBrushItem::SvxBrushItem(sal_uInt16 _nWhich)
: SfxPoolItem(_nWhich)
, aColor(COL_TRANSPARENT)
@@ -4201,6 +4207,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
aNewCol.SetAlpha(aColor.GetAlpha());
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
aColor = aNewCol;
}
break;
@@ -4209,6 +4216,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
sal_Int32 nTrans = 0;
if ( !( rVal >>= nTrans ) || nTrans < 0 || nTrans > 100 )
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
aColor.SetAlpha(255 - lcl_PercentToTransparency(nTrans));
}
break;
@@ -4220,7 +4228,10 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
return false;
if (xComplexColor.is())
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
maComplexColor = model::color::getFromXComplexColor(xComplexColor);
+ }
}
break;
@@ -4234,11 +4245,13 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
return false;
eLocation = static_cast<style::GraphicLocation>(nValue);
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetGraphicPos( static_cast<SvxGraphicPosition>(static_cast<sal_uInt16>(eLocation)) );
}
break;
case MID_GRAPHIC_TRANSPARENT:
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
aColor.SetAlpha( Any2Bool( rVal ) ? 0 : 255 );
break;
@@ -4262,6 +4275,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
maStrLink.clear();
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
std::unique_ptr<GraphicObject> xOldGrfObj(std::move(xGraphicObject));
xGraphicObject.reset(new GraphicObject(aGraphic));
ApplyGraphicTransparency_Impl();
@@ -4285,6 +4299,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
OUString sLink;
rVal >>= sLink;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetGraphicFilter( sLink );
}
}
@@ -4295,6 +4310,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
rVal >>= nTmp;
if(nTmp >= 0 && nTmp <= 100)
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nGraphicTransparency = sal_Int8(nTmp);
if (xGraphicObject)
ApplyGraphicTransparency_Impl();
@@ -4308,6 +4324,7 @@ bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
if (!(rVal >>= nVal))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nShadingValue = nVal;
}
break;
@@ -4457,6 +4474,7 @@ void SvxBrushItem::setGraphicTransparency(sal_Int8 nNew)
{
if (nNew != nGraphicTransparency)
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nGraphicTransparency = nNew;
ApplyGraphicTransparency_Impl();
}
@@ -4470,6 +4488,10 @@ const Graphic* SvxBrushItem::GetGraphic(OUString const & referer) const
void SvxBrushItem::SetGraphicPos( SvxGraphicPosition eNew )
{
+ if (eGraphicPos == eNew)
+ return;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
eGraphicPos = eNew;
if ( GPOS_NONE == eGraphicPos )
@@ -4491,6 +4513,7 @@ void SvxBrushItem::SetGraphic( const Graphic& rNew )
{
if ( maStrLink.isEmpty() )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
if (xGraphicObject)
xGraphicObject->SetGraphic(rNew);
else
@@ -4511,6 +4534,7 @@ void SvxBrushItem::SetGraphicObject( const GraphicObject& rNewObj )
{
if ( maStrLink.isEmpty() )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
if (xGraphicObject)
*xGraphicObject = rNewObj;
else
@@ -4529,6 +4553,7 @@ void SvxBrushItem::SetGraphicObject( const GraphicObject& rNewObj )
void SvxBrushItem::SetGraphicLink( const OUString& rNew )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
if ( rNew.isEmpty() )
maStrLink.clear();
else
@@ -4540,6 +4565,7 @@ void SvxBrushItem::SetGraphicLink( const OUString& rNew )
void SvxBrushItem::SetGraphicFilter( const OUString& rNew )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
maStrFilter = rNew;
}
@@ -4570,6 +4596,12 @@ void SvxBrushItem::dumpAsXml(xmlTextWriterPtr pWriter) const
}
+ItemInstanceManager* SvxFrameDirectionItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxFrameDirectionItem::SvxFrameDirectionItem( SvxFrameDirection nValue ,
sal_uInt16 _nWhich )
: SfxEnumItem<SvxFrameDirection>( _nWhich, nValue )
@@ -4618,6 +4650,7 @@ bool SvxFrameDirectionItem::PutValue( const css::uno::Any& rVal,
bool bRet = ( rVal >>= nVal );
if( bRet )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
// translate WritingDirection2 constants into SvxFrameDirection
switch( nVal )
{
diff --git a/editeng/source/items/paraitem.cxx b/editeng/source/items/paraitem.cxx
index e10c323bcdf6..2a9a514a6461 100644
--- a/editeng/source/items/paraitem.cxx
+++ b/editeng/source/items/paraitem.cxx
@@ -338,6 +338,12 @@ void SvxLineSpacingItem::SetEnumValue( sal_uInt16 nVal )
// class SvxAdjustItem ---------------------------------------------------
+ItemInstanceManager* SvxAdjustItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxAdjustItem::SvxAdjustItem(const SvxAdjust eAdjst, const sal_uInt16 nId )
: SfxEnumItemInterface( nId ),
bOneBlock( false ), bLastCenter( false ), bLastBlock( false )
@@ -397,6 +403,7 @@ bool SvxAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
}
break;
case MID_EXPAND_SINGLE :
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
bOneBlock = Any2Bool(rVal);
break;
}
diff --git a/editeng/source/items/textitem.cxx b/editeng/source/items/textitem.cxx
index cf4017e7911e..3be26195b52d 100644
--- a/editeng/source/items/textitem.cxx
+++ b/editeng/source/items/textitem.cxx
@@ -82,6 +82,7 @@
#include <docmodel/uno/UnoComplexColor.hxx>
#include <docmodel/color/ComplexColor.hxx>
#include <libxml/xmlwriter.h>
+#include <unordered_map>
using namespace ::com::sun::star;
using namespace ::com::sun::star::text;
@@ -159,29 +160,85 @@ bool SvxFontListItem::GetPresentation
// class SvxFontItem -----------------------------------------------------
-SvxFontItem::SvxFontItem( const sal_uInt16 nId ) :
- SfxPoolItem( nId )
+typedef std::unordered_map<size_t, const SfxPoolItem*> SvxFontItemMap;
+
+namespace
{
- eFamily = FAMILY_SWISS;
- ePitch = PITCH_VARIABLE;
- eTextEncoding = RTL_TEXTENCODING_DONTKNOW;
-}
+ class SvxFontItemInstanceManager : public ItemInstanceManager
+ {
+ SvxFontItemMap maRegistered;
+
+ static size_t hashCode(const SfxPoolItem&);
+ virtual const SfxPoolItem* find(const SfxPoolItem&) const override;
+ virtual void add(const SfxPoolItem&) override;
+ virtual void remove(const SfxPoolItem&) override;
+ };
-SvxFontItem::SvxFontItem( const FontFamily eFam, OUString aName,
- OUString aStName, const FontPitch eFontPitch,
- const rtl_TextEncoding eFontTextEncoding, const sal_uInt16 nId ) :
+ size_t SvxFontItemInstanceManager::hashCode(const SfxPoolItem& rItem)
+ {
+ const SvxFontItem& rFontItem(static_cast<const SvxFontItem&>(rItem));
+ std::size_t seed(0);
+ o3tl::hash_combine(seed, rItem.Which());
+ o3tl::hash_combine(seed, rFontItem.GetFamilyName().hashCode());
+ o3tl::hash_combine(seed, rFontItem.GetStyleName().hashCode());
+ o3tl::hash_combine(seed, rFontItem.GetFamily());
+ o3tl::hash_combine(seed, rFontItem.GetPitch());
+ o3tl::hash_combine(seed, rFontItem.GetCharSet());
+ return seed;
+ }
- SfxPoolItem( nId ),
+ const SfxPoolItem* SvxFontItemInstanceManager::find(const SfxPoolItem& rItem) const
+ {
+ SvxFontItemMap::const_iterator aHit(maRegistered.find(hashCode(rItem)));
+ if (aHit != maRegistered.end())
+ return aHit->second;
+ return nullptr;
+ }
+
+ void SvxFontItemInstanceManager::add(const SfxPoolItem& rItem)
+ {
+ maRegistered.insert({hashCode(rItem), &rItem});
+ }
+
+ void SvxFontItemInstanceManager::remove(const SfxPoolItem& rItem)
+ {
+ maRegistered.erase(hashCode(rItem));
+ }
+}
+
+ItemInstanceManager* SvxFontItem::getItemInstanceManager() const
+{
+ static SvxFontItemInstanceManager aManager;
+ return &aManager;
+}
- aFamilyName(std::move(aName)),
- aStyleName(std::move(aStName))
+SvxFontItem::SvxFontItem(
+ const sal_uInt16 nId)
+: SfxPoolItem( nId )
+, aFamilyName()
+, aStyleName()
+, eFamily(FAMILY_SWISS)
+, ePitch(PITCH_VARIABLE)
+, eTextEncoding(RTL_TEXTENCODING_DONTKNOW)
{
- eFamily = eFam;
- ePitch = eFontPitch;
- eTextEncoding = eFontTextEncoding;
}
+SvxFontItem::SvxFontItem(
+ const FontFamily eFam,
+ OUString aName,
+ OUString aStName,
+ const FontPitch eFontPitch,
+ const rtl_TextEncoding eFontTextEncoding,
+ const sal_uInt16 nId)
+: SfxPoolItem( nId )
+, aFamilyName(std::move(aName))
+, aStyleName(std::move(aStName))
+, eFamily(eFam)
+, ePitch(eFontPitch)
+, eTextEncoding(eFontTextEncoding)
+{
+}
bool SvxFontItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
{
@@ -223,6 +280,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
if ( !( rVal >>= aFontDescriptor ))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
aFamilyName = aFontDescriptor.Name;
aStyleName = aFontDescriptor.StyleName;
eFamily = static_cast<FontFamily>(aFontDescriptor.Family);
@@ -235,6 +293,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
OUString aStr;
if(!(rVal >>= aStr))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
aFamilyName = aStr;
}
break;
@@ -243,6 +302,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
OUString aStr;
if(!(rVal >>= aStr))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
aStyleName = aStr;
}
break;
@@ -251,6 +311,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
sal_Int16 nFamily = sal_Int16();
if(!(rVal >>= nFamily))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
eFamily = static_cast<FontFamily>(nFamily);
}
break;
@@ -259,6 +320,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
sal_Int16 nSet = sal_Int16();
if(!(rVal >>= nSet))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
eTextEncoding = static_cast<rtl_TextEncoding>(nSet);
}
break;
@@ -267,6 +329,7 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
sal_Int16 nPitch = sal_Int16();
if(!(rVal >>= nPitch))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
ePitch = static_cast<FontPitch>(nPitch);
}
break;
@@ -274,13 +337,58 @@ bool SvxFontItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId)
return true;
}
+void SvxFontItem::SetFamilyName(const OUString& rFamilyName)
+{
+ if (aFamilyName == rFamilyName)
+ return;
-bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ aFamilyName = rFamilyName;
+}
+
+void SvxFontItem::SetStyleName(const OUString &rStyleName)
{
- assert(SfxPoolItem::operator==(rAttr));
+ if (aStyleName == rStyleName)
+ return;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ aStyleName = rStyleName;
+}
+
+void SvxFontItem::SetFamily(FontFamily _eFamily)
+{
+ if (eFamily == _eFamily)
+ return;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ eFamily = _eFamily;
+}
+
+void SvxFontItem::SetPitch(FontPitch _ePitch)
+{
+ if (ePitch == _ePitch)
+ return;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ ePitch = _ePitch;
+}
+
+void SvxFontItem::SetCharSet(rtl_TextEncoding _eEncoding)
+{
+ if (eTextEncoding == _eEncoding)
+ return;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ eTextEncoding = _eEncoding;
+}
- const SvxFontItem& rItem = static_cast<const SvxFontItem&>(rAttr);
+bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const
+{
+ if (this == &rAttr)
+ return true;
+ assert(SfxPoolItem::operator==(rAttr));
+ const SvxFontItem& rItem(static_cast<const SvxFontItem&>(rAttr));
bool bRet = ( eFamily == rItem.eFamily &&
aFamilyName == rItem.aFamilyName &&
aStyleName == rItem.aStyleName );
@@ -293,6 +401,7 @@ bool SvxFontItem::operator==( const SfxPoolItem& rAttr ) const
SAL_INFO( "editeng.items", "FontItem::operator==(): only pitch or rtl_TextEncoding different ");
}
}
+
return bRet;
}
@@ -328,6 +437,12 @@ void SvxFontItem::dumpAsXml(xmlTextWriterPtr pWriter) const
// class SvxPostureItem --------------------------------------------------
+ItemInstanceManager* SvxPostureItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxPostureItem::SvxPostureItem( const FontItalic ePosture, const sal_uInt16 nId ) :
SfxEnumItem( nId, ePosture )
{
@@ -396,6 +511,7 @@ bool SvxPostureItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
switch( nMemberId )
{
case MID_ITALIC:
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetBoolValue(Any2Bool(rVal));
break;
case MID_POSTURE:
@@ -409,6 +525,7 @@ bool SvxPostureItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
eSlant = static_cast<awt::FontSlant>(nValue);
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(vcl::unohelper::ConvertFontSlant(eSlant));
}
}
@@ -427,6 +544,7 @@ bool SvxPostureItem::GetBoolValue() const
void SvxPostureItem::SetBoolValue( bool bVal )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? ITALIC_NORMAL : ITALIC_NONE );
}
@@ -441,6 +559,12 @@ void SvxPostureItem::dumpAsXml(xmlTextWriterPtr pWriter) const
// class SvxWeightItem ---------------------------------------------------
+ItemInstanceManager* SvxWeightItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxWeightItem::SvxWeightItem( const FontWeight eWght, const sal_uInt16 nId ) :
SfxEnumItem( nId, eWght )
{
@@ -461,6 +585,7 @@ bool SvxWeightItem::GetBoolValue() const
void SvxWeightItem::SetBoolValue( bool bVal )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? WEIGHT_BOLD : WEIGHT_NORMAL );
}
@@ -532,6 +657,7 @@ bool SvxWeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
switch( nMemberId )
{
case MID_BOLD :
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetBoolValue(Any2Bool(rVal));
break;
case MID_WEIGHT:
@@ -544,6 +670,7 @@ bool SvxWeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
return false;
fValue = static_cast<float>(nValue);
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( vcl::unohelper::ConvertFontWeight(static_cast<float>(fValue)) );
}
break;
@@ -562,6 +689,12 @@ void SvxWeightItem::dumpAsXml(xmlTextWriterPtr pWriter) const
// class SvxFontHeightItem -----------------------------------------------
+ItemInstanceManager* SvxFontHeightItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxFontHeightItem::SvxFontHeightItem( const sal_uInt32 nSz,
const sal_uInt16 nPrp,
const sal_uInt16 nId ) :
@@ -739,6 +872,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
if( fPoint < 0. || fPoint > 10000. )
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = static_cast<tools::Long>( fPoint * 20.0 + 0.5 ); // Twips
if (!bConvert)
nHeight = convertTwipToMm100(nHeight); // Convert, if the item contains 1/100mm
@@ -771,6 +905,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
return false;
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = static_cast<tools::Long>( fPoint * 20.0 + 0.5 ); // Twips
if (!bConvert)
nHeight = convertTwipToMm100(nHeight); // Convert, if the item contains 1/100mm
@@ -782,6 +917,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
if(!(rVal >>= nNew))
return true;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = lcl_GetRealHeight_Impl(nHeight, nProp, ePropUnit, bConvert);
nHeight *= nNew;
@@ -801,6 +937,7 @@ bool SvxFontHeightItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
return false;
fValue = static_cast<float>(nValue);
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
sal_Int16 nCoreDiffValue = static_cast<sal_Int16>(fValue * 20.);
nHeight += bConvert ? nCoreDiffValue : convertTwipToMm100(nCoreDiffValue);
nProp = static_cast<sal_uInt16>(static_cast<sal_Int16>(fValue));
@@ -841,6 +978,7 @@ bool SvxFontHeightItem::GetPresentation
void SvxFontHeightItem::ScaleMetrics( tools::Long nMult, tools::Long nDiv )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nHeight = static_cast<sal_uInt32>(BigInt::Scale( nHeight, nMult, nDiv ));
}
@@ -855,6 +993,7 @@ void SvxFontHeightItem::SetHeight( sal_uInt32 nNewHeight, const sal_uInt16 nNewP
{
DBG_ASSERT( GetRefCount() == 0, "SetValue() with pooled item" );
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
if( MapUnit::MapRelative != eUnit )
nHeight = nNewHeight + ::ItemToControl( short(nNewProp), eUnit,
FieldUnit::TWIP );
@@ -872,6 +1011,7 @@ void SvxFontHeightItem::SetHeight( sal_uInt32 nNewHeight, sal_uInt16 nNewProp,
{
DBG_ASSERT( GetRefCount() == 0, "SetValue() with pooled item" );
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
if( MapUnit::MapRelative != eMetric )
nHeight = nNewHeight +
::ControlToItem( ::ItemToControl(static_cast<short>(nNewProp), eMetric,
@@ -898,6 +1038,12 @@ void SvxFontHeightItem::dumpAsXml(xmlTextWriterPtr pWriter) const
// class SvxTextLineItem ------------------------------------------------
+ItemInstanceManager* SvxTextLineItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxTextLineItem::SvxTextLineItem( const FontLineStyle eSt, const sal_uInt16 nId )
: SfxEnumItem(nId, eSt)
, maColor(COL_TRANSPARENT)
@@ -919,6 +1065,7 @@ bool SvxTextLineItem::GetBoolValue() const
void SvxTextLineItem::SetBoolValue( bool bVal )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? LINESTYLE_SINGLE : LINESTYLE_NONE );
}
@@ -988,6 +1135,7 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
switch(nMemberId)
{
case MID_TEXTLINED:
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetBoolValue(Any2Bool(rVal));
break;
case MID_TL_STYLE:
@@ -996,7 +1144,10 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
if(!(rVal >>= nValue))
bRet = false;
else
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(static_cast<FontLineStyle>(nValue));
+ }
}
break;
case MID_TL_COLOR:
@@ -1008,6 +1159,7 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
{
// Keep transparence, because it contains the information
// whether the font color or the stored color should be used
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
sal_uInt8 nAlpha = maColor.GetAlpha();
maColor = nCol;
maColor.SetAlpha( nAlpha );
@@ -1021,10 +1173,14 @@ bool SvxTextLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
return false;
if (xComplexColor.is())
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
maComplexColor = model::color::getFromXComplexColor(xComplexColor);
+ }
}
break;
case MID_TL_HASCOLOR:
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
maColor.SetAlpha( Any2Bool( rVal ) ? 255 : 0 );
break;
}
@@ -1123,6 +1279,12 @@ OUString SvxOverlineItem::GetValueTextByPos( sal_uInt16 nPos ) const
// class SvxCrossedOutItem -----------------------------------------------
+ItemInstanceManager* SvxCrossedOutItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxCrossedOutItem::SvxCrossedOutItem( const FontStrikeout eSt, const sal_uInt16 nId )
: SfxEnumItem( nId, eSt )
{
@@ -1143,6 +1305,7 @@ bool SvxCrossedOutItem::GetBoolValue() const
void SvxCrossedOutItem::SetBoolValue( bool bVal )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( bVal ? STRIKEOUT_SINGLE : STRIKEOUT_NONE );
}
@@ -1214,6 +1377,7 @@ bool SvxCrossedOutItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
sal_Int32 nValue = 0;
if(!(rVal >>= nValue))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(static_cast<FontStrikeout>(nValue));
}
break;
@@ -1917,6 +2081,12 @@ bool SvxEscapementItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
// class SvxLanguageItem -------------------------------------------------
+ItemInstanceManager* SvxLanguageItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxLanguageItem::SvxLanguageItem( const LanguageType eLang, const sal_uInt16 nId )
: SvxLanguageItem_Base( nId , eLang )
{
@@ -1976,6 +2146,7 @@ bool SvxLanguageItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
if(!(rVal >>= nValue))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue(LanguageType(nValue));
}
break;
@@ -1985,6 +2156,7 @@ bool SvxLanguageItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
if(!(rVal >>= aLocale))
return false;
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( LanguageTag::convertToLanguageType( aLocale, false));
}
break;
@@ -2053,6 +2225,12 @@ bool SvxBlinkItem::GetPresentation
// class SvxEmphaisMarkItem ---------------------------------------------------
+ItemInstanceManager* SvxEmphasisMarkItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxEmphasisMarkItem::SvxEmphasisMarkItem( const FontEmphasisMark nValue,
TypedWhichId<SvxEmphasisMarkItem> nId )
: SfxUInt16Item( nId, static_cast<sal_uInt16>(nValue) )
@@ -2145,6 +2323,7 @@ bool SvxEmphasisMarkItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
case FontEmphasis::ACCENT_BELOW: nMark = FontEmphasisMark::Accent|FontEmphasisMark::PosBelow; break;
default: return false;
}
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( static_cast<sal_Int16>(nMark) );
}
break;
@@ -2486,6 +2665,12 @@ bool SvxCharScaleWidthItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/
|* class SvxCharReliefItem
*************************************************************************/
+ItemInstanceManager* SvxCharReliefItem::getItemInstanceManager() const
+{
+ static DefaultItemInstanceManager aManager;
+ return &aManager;
+}
+
SvxCharReliefItem::SvxCharReliefItem( FontRelief eValue,
const sal_uInt16 nId )
: SfxEnumItem( nId, eValue )
@@ -2539,7 +2724,10 @@ bool SvxCharReliefItem::PutValue( const css::uno::Any& rVal,
sal_Int16 nVal = -1;
rVal >>= nVal;
if(nVal >= 0 && nVal <= sal_Int16(FontRelief::Engraved))
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
SetValue( static_cast<FontRelief>(nVal) );
+ }
else
bRet = false;
}
diff --git a/include/editeng/adjustitem.hxx b/include/editeng/adjustitem.hxx
index e2793907736c..c660598abfc7 100644
--- a/include/editeng/adjustitem.hxx
+++ b/include/editeng/adjustitem.hxx
@@ -44,6 +44,9 @@ class EDITENG_DLLPUBLIC SvxAdjustItem final : public SfxEnumItemInterface
bool bLastCenter : 1;
bool bLastBlock : 1;
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
@@ -68,17 +71,20 @@ public:
void SetOneWord( const SvxAdjust eType )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
bOneBlock = eType == SvxAdjust::Block;
}
void SetLastBlock( const SvxAdjust eType )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
bLastBlock = eType == SvxAdjust::Block;
bLastCenter = eType == SvxAdjust::Center;
}
void SetAdjust( const SvxAdjust eType )
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
bLeft = eType == SvxAdjust::Left;
bRight = eType == SvxAdjust::Right;
bCenter = eType == SvxAdjust::Center;
@@ -132,6 +138,7 @@ public:
void SetAsFlags(sal_Int8 nFlags)
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
bOneBlock = 0 != (nFlags & 0x0001);
bLastCenter = 0 != (nFlags & 0x0002);
bLastBlock = 0 != (nFlags & 0x0004);
diff --git a/include/editeng/brushitem.hxx b/include/editeng/brushitem.hxx
index de433f2f272d..6897e319a3b6 100644
--- a/include/editeng/brushitem.hxx
+++ b/include/editeng/brushitem.hxx
@@ -54,6 +54,9 @@ class EDITENG_DLLPUBLIC SvxBrushItem final : public SfxPoolItem
void ApplyGraphicTransparency_Impl();
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
@@ -89,7 +92,11 @@ public:
const Color& GetColor() const { return aColor; }
Color& GetColor() { return aColor; }
- void SetColor( const Color& rCol) { aColor = rCol; }
+ void SetColor( const Color& rCol)
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ aColor = rCol;
+ }
const model::ComplexColor& getComplexColor() const
{
@@ -100,11 +107,16 @@ public:
void setComplexColor(model::ComplexColor const& rComplexColor)
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
maComplexColor = rComplexColor;
}
const Color& GetFiltColor() const { return aFilterColor; }
- void SetFiltColor( const Color& rCol) { aFilterColor = rCol; }
+ void SetFiltColor( const Color& rCol)
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ aFilterColor = rCol;
+ }
SvxGraphicPosition GetGraphicPos() const { return eGraphicPos; }
diff --git a/include/editeng/charreliefitem.hxx b/include/editeng/charreliefitem.hxx
index 78b57fa7df00..910adcf11e24 100644
--- a/include/editeng/charreliefitem.hxx
+++ b/include/editeng/charreliefitem.hxx
@@ -33,6 +33,9 @@
class EDITENG_DLLPUBLIC SvxCharReliefItem final : public SfxEnumItem<FontRelief>
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
diff --git a/include/editeng/crossedoutitem.hxx b/include/editeng/crossedoutitem.hxx
index 5d8b18fe2650..259eb412e1e1 100644
--- a/include/editeng/crossedoutitem.hxx
+++ b/include/editeng/crossedoutitem.hxx
@@ -31,6 +31,9 @@
class EDITENG_DLLPUBLIC SvxCrossedOutItem final : public SfxEnumItem<FontStrikeout>
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
diff --git a/include/editeng/emphasismarkitem.hxx b/include/editeng/emphasismarkitem.hxx
index e0fd74cf4400..94d48e4b8d9c 100644
--- a/include/editeng/emphasismarkitem.hxx
+++ b/include/editeng/emphasismarkitem.hxx
@@ -32,6 +32,9 @@
class EDITENG_DLLPUBLIC SvxEmphasisMarkItem final : public SfxUInt16Item
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
diff --git a/include/editeng/fhgtitem.hxx b/include/editeng/fhgtitem.hxx
index efaad86bdfa8..bdde8c6f0afd 100644
--- a/include/editeng/fhgtitem.hxx
+++ b/include/editeng/fhgtitem.hxx
@@ -41,10 +41,12 @@ class EDITENG_DLLPUBLIC SvxFontHeightItem final : public SfxPoolItem
sal_uInt16 nProp; // default 100%
MapUnit ePropUnit; // Percent, Twip, ...
-private:
friend void Create_legacy_direct_set(SvxFontHeightItem& rItem, sal_uInt32 nH, sal_uInt16 nP, MapUnit eP);
void legacy_direct_set(sal_uInt32 nH, sal_uInt16 nP, MapUnit eP) { nHeight = nH; nProp = nP; ePropUnit = eP; }
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
@@ -75,7 +77,7 @@ public:
void SetProp( sal_uInt16 nNewProp, MapUnit eUnit )
{
- DBG_ASSERT( GetRefCount() == 0, "SetValue() with pooled item" );
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
nProp = nNewProp;
ePropUnit = eUnit;
}
diff --git a/include/editeng/fontitem.hxx b/include/editeng/fontitem.hxx
index 7cab5f462e4e..f892178c521e 100644
--- a/include/editeng/fontitem.hxx
+++ b/include/editeng/fontitem.hxx
@@ -34,6 +34,9 @@ class EDITENG_DLLPUBLIC SvxFontItem final : public SfxPoolItem
FontPitch ePitch;
rtl_TextEncoding eTextEncoding;
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
@@ -55,46 +58,31 @@ public:
OUString &rText, const IntlWrapper&) const override;
// Access methods:
- void SetFamilyName(const OUString& rFamilyName)
- {
- aFamilyName = rFamilyName;
- }
+ void SetFamilyName(const OUString& rFamilyName);
const OUString &GetFamilyName() const
{
return aFamilyName;
}
- void SetStyleName(const OUString &rStyleName)
- {
- aStyleName = rStyleName;
- }
+ void SetStyleName(const OUString &rStyleName);
const OUString &GetStyleName() const
{
return aStyleName;
}
- void SetFamily(FontFamily _eFamily)
- {
- eFamily = _eFamily;
- }
+ void SetFamily(FontFamily _eFamily);
FontFamily GetFamily() const
{
return eFamily;
}
- void SetPitch(FontPitch _ePitch)
- {
- ePitch = _ePitch;
- }
+ void SetPitch(FontPitch _ePitch);
FontPitch GetPitch() const
{
return ePitch;
}
- void SetCharSet(rtl_TextEncoding _eEncoding)
- {
- eTextEncoding = _eEncoding;
- }
+ void SetCharSet(rtl_TextEncoding _eEncoding);
rtl_TextEncoding GetCharSet() const
{
return eTextEncoding;
diff --git a/include/editeng/frmdiritem.hxx b/include/editeng/frmdiritem.hxx
index 7bb6dc09950d..e2bba96b8974 100644
--- a/include/editeng/frmdiritem.hxx
+++ b/include/editeng/frmdiritem.hxx
@@ -30,6 +30,9 @@
class EDITENG_DLLPUBLIC SvxFrameDirectionItem final : public SfxEnumItem<SvxFrameDirection>
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
SvxFrameDirectionItem( SvxFrameDirection nValue, sal_uInt16 nWhich );
virtual ~SvxFrameDirectionItem() override;
diff --git a/include/editeng/langitem.hxx b/include/editeng/langitem.hxx
index 4d3852141666..7c8f68e96fd6 100644
--- a/include/editeng/langitem.hxx
+++ b/include/editeng/langitem.hxx
@@ -40,6 +40,9 @@ protected:
class EDITENG_DLLPUBLIC SvxLanguageItem final : public SvxLanguageItem_Base
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
diff --git a/include/editeng/postitem.hxx b/include/editeng/postitem.hxx
index 93ed44b6b794..392a9627feb6 100644
--- a/include/editeng/postitem.hxx
+++ b/include/editeng/postitem.hxx
@@ -32,6 +32,9 @@
class EDITENG_DLLPUBLIC SvxPostureItem final : public SfxEnumItem<FontItalic>
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
diff --git a/include/editeng/udlnitem.hxx b/include/editeng/udlnitem.hxx
index ecbec7a17b8d..560833d4d088 100644
--- a/include/editeng/udlnitem.hxx
+++ b/include/editeng/udlnitem.hxx
@@ -33,6 +33,9 @@ class EDITENG_DLLPUBLIC SvxTextLineItem : public SfxEnumItem<FontLineStyle>
Color maColor;
model::ComplexColor maComplexColor;
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
SvxTextLineItem( const FontLineStyle eSt,
const sal_uInt16 nId );
@@ -61,7 +64,10 @@ public:
FontLineStyle GetLineStyle() const
{ return GetValue(); }
void SetLineStyle( FontLineStyle eNew )
- { SetValue(eNew); }
+ {
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ SetValue(eNew);
+ }
const Color& GetColor() const { return maColor; }
void SetColor(const Color& rColor) { maColor = rColor; }
@@ -73,6 +79,7 @@ public:
void setComplexColor(model::ComplexColor const& rComplexColor)
{
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
maComplexColor = rComplexColor;
}
};
diff --git a/include/editeng/wghtitem.hxx b/include/editeng/wghtitem.hxx
index 121cfcf318a6..f8beb7c7a62f 100644
--- a/include/editeng/wghtitem.hxx
+++ b/include/editeng/wghtitem.hxx
@@ -32,6 +32,9 @@
class EDITENG_DLLPUBLIC SvxWeightItem final : public SfxEnumItem<FontWeight>
{
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
diff --git a/include/svl/eitem.hxx b/include/svl/eitem.hxx
index 114e451c061d..18bb334a7e96 100644
--- a/include/svl/eitem.hxx
+++ b/include/svl/eitem.hxx
@@ -69,6 +69,9 @@ class SVL_DLLPUBLIC SfxBoolItem
{
bool m_bValue;
+protected:
+ virtual ItemInstanceManager* getItemInstanceManager() const override;
+
public:
static SfxPoolItem* CreateDefault();
@@ -78,8 +81,7 @@ public:
{ }
bool GetValue() const { return m_bValue; }
-
- void SetValue(bool const bTheValue) { m_bValue = bTheValue; }
+ void SetValue(bool const bTheValue);
// SfxPoolItem
virtual bool operator ==(const SfxPoolItem & rItem) const override;
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx
index 8762c77e142f..f04b274ec83b 100644
--- a/include/svl/itemset.hxx
+++ b/include/svl/itemset.hxx
@@ -36,6 +36,7 @@ SVL_DLLPUBLIC size_t getAllocatedSfxItemSetCount();
SVL_DLLPUBLIC size_t getUsedSfxItemSetCount();
SVL_DLLPUBLIC size_t getAllocatedSfxPoolItemHolderCount();
SVL_DLLPUBLIC size_t getUsedSfxPoolItemHolderCount();
+SVL_DLLPUBLIC void listSfxPoolItemsWithHighestUsage(sal_uInt16);
#endif
// ItemSet/ItemPool helpers
diff --git a/include/svl/poolitem.hxx b/include/svl/poolitem.hxx
index ab909c4edfec..79a113b6da89 100644
--- a/include/svl/poolitem.hxx
+++ b/include/svl/poolitem.hxx
@@ -32,12 +32,11 @@
#include <tools/mapunit.hxx>
#include <tools/long.hxx>
#include <boost/property_tree/ptree_fwd.hpp>
+#include <unordered_set>
class IntlWrapper;
-#define SFX_ITEMS_OLD_MAXREF 0xffef
-#define SFX_ITEMS_MAXREF 0xfffffffe
-
+#define SFX_ITEMS_MAXREF 0xffffffff
#define CONVERT_TWIPS 0x80 // Uno conversion for measurement (for MemberId)
// warning, if there is no boolean inside the any this will always return the value false
@@ -54,6 +53,12 @@ inline bool Any2Bool( const css::uno::Any&rValue )
return bValue;
}
+// Offer simple assert if Item is RefCounted (RefCnt > 1) and thus CANNOT be changed.
+// This should be used at *all* SfxPoolItem set* mehods. Remember that SfxPoolItems
+// are by design intended to be create-one, read-only, shared data packages
+#define ASSERT_CHANGE_REFCOUNTED_ITEM \
+ assert(!GetRefCount() && "ERROR: RefCounted SfxPoolItem CANNOT be changed (!)")
+
/*
* The values of this enum describe the degree of textual
* representation of an item after calling the virtual
@@ -106,6 +111,7 @@ SVL_DLLPUBLIC void listAllocatedSfxPoolItems();
class SfxItemPool;
class SfxItemSet;
typedef struct _xmlTextWriter* xmlTextWriterPtr;
+class ItemInstanceManager;
class SVL_DLLPUBLIC SfxPoolItem
{
@@ -168,10 +174,13 @@ protected:
void setIsSetItem() { m_bIsSetItem = true; }
void setNonShareable() { m_bShareable = false; }
+ // access ItemInstanceManager for this Item, default
+ // is nullptr
+ virtual ItemInstanceManager* getItemInstanceManager() const;
+
public:
inline void AddRef(sal_uInt32 n = 1) const
{
- assert(m_nRefCount <= SFX_ITEMS_MAXREF && "AddRef with non-Pool-Item");
assert(n <= SFX_ITEMS_MAXREF - m_nRefCount && "AddRef: refcount overflow");
m_nRefCount += n;
}
@@ -194,7 +203,6 @@ public:
private:
inline sal_uInt32 ReleaseRef(sal_uInt32 n = 1) const
{
- assert(m_nRefCount <= SFX_ITEMS_MAXREF && "ReleaseRef with non-Pool-Item");
assert(n <= m_nRefCount);
m_nRefCount -= n;
return m_nRefCount;
@@ -281,7 +289,37 @@ private:
SfxPoolItem& operator=( const SfxPoolItem& ) = delete;
};
+// basic Interface definition
+class SVL_DLLPUBLIC ItemInstanceManager
+{
+ // allow *only* ItemSetTooling to access
+ friend SfxPoolItem const* implCreateItemEntry(SfxItemPool&, SfxPoolItem const*, bool);
+ friend void implCleanupItemEntry(SfxPoolItem const*);
+
+ // standard interface, accessed exclusively
+ // by implCreateItemEntry/implCleanupItemEntry
+ virtual const SfxPoolItem* find(const SfxPoolItem&) const = 0;
+ virtual void add(const SfxPoolItem&) = 0;
+ virtual void remove(const SfxPoolItem&) = 0;
+};
+
+// offering a default implementation that can be use for
+// each SfxPoolItem (except when !isShareable()). It just
+// uses an unordered_set holding ptrs to SfxPoolItems added
+// and SfxPoolItem::opeator== to linearly search for one.
+// Thus thisi is not the fastest, but as fast as old 'poooled'
+// stuff - btter use an intelligent, pro-Item implementation
+// that does e.g. hashing or whatever might be feasible for
+// that specific Item (see other derivations)
+class SVL_DLLPUBLIC DefaultItemInstanceManager : public ItemInstanceManager
+{
+ std::unordered_set<const SfxPoolItem*> maRegistered;
+public:
+ virtual const SfxPoolItem* find(const SfxPoolItem&) const override;
+ virtual void add(const SfxPoolItem&) override;
+ virtual void remove(const SfxPoolItem&) override;
+};
inline bool IsPoolDefaultItem(const SfxPoolItem *pItem )
{
@@ -300,7 +338,7 @@ inline bool IsDefaultItem( const SfxPoolItem *pItem )
inline bool IsPooledItem( const SfxPoolItem *pItem )
{
- return pItem && pItem->GetRefCount() > 0 && pItem->GetRefCount() <= SFX_ITEMS_MAXREF;
+ return pItem && pItem->GetRefCount() > 0;
}
SVL_DLLPUBLIC extern SfxPoolItem const * const INVALID_POOL_ITEM;
diff --git a/svl/source/items/cenumitm.cxx b/svl/source/items/cenumitm.cxx
index 713e1608efd8..86e30b7e6bdc 100644
--- a/svl/source/items/cenumitm.cxx
+++ b/svl/source/items/cenumitm.cxx
@@ -20,7 +20,7 @@
#include <com/sun/star/uno/Any.hxx>
#include <svl/cenumitm.hxx>
#include <svl/eitem.hxx>
-
+#include <unordered_map>
#include <comphelper/extract.hxx>
#include <libxml/xmlwriter.h>
#include <sal/log.hxx>
@@ -83,6 +83,85 @@ bool SfxEnumItemInterface::GetBoolValue() const
void SfxEnumItemInterface::SetBoolValue(bool)
{}
+typedef std::unordered_map<sal_uInt16, std::pair<const SfxPoolItem*, const SfxPoolItem*>> SfxBoolItemMap;
+
+namespace
+{
+ class SfxBoolItemInstanceManager : public ItemInstanceManager
+ {
+ SfxBoolItemMap maRegistered;
+
+ virtual const SfxPoolItem* find(const SfxPoolItem&) const override;
+ virtual void add(const SfxPoolItem&) override;
+ virtual void remove(const SfxPoolItem&) override;
+ };
+
+ const SfxPoolItem* SfxBoolItemInstanceManager::find(const SfxPoolItem& rItem) const
+ {
+ SfxBoolItemMap::const_iterator aHit(maRegistered.find(rItem.Which()));
+ if (aHit == maRegistered.end())
+ return nullptr;
+
+ const SfxBoolItem& rSfxBoolItem(static_cast<const SfxBoolItem&>(rItem));
+ if (rSfxBoolItem.GetValue())
+ return aHit->second.first;
+ return aHit->second.second;
+ }
+
+ void SfxBoolItemInstanceManager::add(const SfxPoolItem& rItem)
+ {
+ SfxBoolItemMap::iterator aHit(maRegistered.find(rItem.Which()));
+ const SfxBoolItem& rSfxBoolItem(static_cast<const SfxBoolItem&>(rItem));
+
+ if (aHit == maRegistered.end())
+ {
+ if (rSfxBoolItem.GetValue())
+ maRegistered.insert({rItem.Which(), std::make_pair(&rItem, nullptr)});
+ else
+ maRegistered.insert({rItem.Which(), std::make_pair(nullptr, &rItem)});
+ }
+ else
+ {
+ if (rSfxBoolItem.GetValue())
+ aHit->second.first = &rItem;
+ else
+ aHit->second.second = &rItem;
+ }
+ }
+
+ void SfxBoolItemInstanceManager::remove(const SfxPoolItem& rItem)
+ {
+ SfxBoolItemMap::iterator aHit(maRegistered.find(rItem.Which()));
+ const SfxBoolItem& rSfxBoolItem(static_cast<const SfxBoolItem&>(rItem));
+
+ if (aHit != maRegistered.end())
+ {
+ if (rSfxBoolItem.GetValue())
+ aHit->second.first = nullptr;
+ else
+ aHit->second.second = nullptr;
+
+ if (aHit->second.first == nullptr && aHit->second.second == nullptr)
+ maRegistered.erase(aHit);
+ }
+ }
+}
+
+ItemInstanceManager* SfxBoolItem::getItemInstanceManager() const
+{
+ static SfxBoolItemInstanceManager aManager;
+ return &aManager;
+}
+
+void SfxBoolItem::SetValue(bool const bTheValue)
+{
+ if (m_bValue == bTheValue)
+ return;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
+ m_bValue = bTheValue;
+}
+
SfxPoolItem* SfxBoolItem::CreateDefault()
{
return new SfxBoolItem();
@@ -126,6 +205,10 @@ bool SfxBoolItem::PutValue(const css::uno::Any& rVal, sal_uInt8)
bool bTheValue = bool();
if (rVal >>= bTheValue)
{
+ if (m_bValue == bTheValue)
+ return true;
+
+ ASSERT_CHANGE_REFCOUNTED_ITEM;
m_bValue = bTheValue;
return true;
}
diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx
index a7db03c68932..5eec0a7a9391 100644
--- a/svl/source/items/itemset.cxx
+++ b/svl/source/items/itemset.cxx
@@ -36,6 +36,8 @@
#include <items_helper.hxx>
+static bool g_bDisableItemInstanceManager(getenv("SVL_DISABLE_ITEM_INSTANCE_MANAGER"));
+
#ifdef DBG_UTIL
static size_t nAllocatedSfxItemSetCount(0);
static size_t nUsedSfxItemSetCount(0);
@@ -45,6 +47,45 @@ size_t getAllocatedSfxItemSetCount() { return nAllocatedSfxItemSetCount; }
size_t getUsedSfxItemSetCount() { return nUsedSfxItemSetCount; }
size_t getAllocatedSfxPoolItemHolderCount() { return nAllocatedSfxPoolItemHolderCount; }
size_t getUsedSfxPoolItemHolderCount() { return nUsedSfxPoolItemHolderCount; }
+
+typedef std::unordered_map<sal_uInt16, std::pair<sal_uInt32, const char*>> HightestUsage;
+static HightestUsage aHightestUsage;
+
+static void addUsage(const SfxPoolItem& rCandidate)
+{
+ HightestUsage::iterator aHit(aHightestUsage.find(rCandidate.Which()));
+ if (aHit == aHightestUsage.end())
+ {
+ aHightestUsage.insert({rCandidate.Which(), {1, typeid(rCandidate).name()}});
+ return;
+ }
+ aHit->second.first++;
+}
+
+void listSfxPoolItemsWithHighestUsage(sal_uInt16 nNum)
+{
+ struct sorted {
+ sal_uInt16 nWhich;
+ sal_uInt32 nUsage;
+ const char* pType;
+ sorted(sal_uInt16 _nWhich, sal_uInt32 _nUsage, const char* _pType)
+ : nWhich(_nWhich), nUsage(_nUsage), pType(_pType) {}
+ bool operator<(const sorted& rDesc) const { return nUsage > rDesc.nUsage; }
+ };
+ std::vector<sorted> aSorted;
+ aSorted.reserve(aHightestUsage.size());
+ for (const auto& rEntry : aHightestUsage)
+ aSorted.emplace_back(rEntry.first, rEntry.second.first, rEntry.second.second);
+ std::sort(aSorted.begin(), aSorted.end());
+ sal_uInt16 a(0);
+ SAL_INFO("svl.items", "ITEM: List of the " << nNum << " SfxPoolItems with highest non-RefCounted usages:");
+ for (const auto& rEntry : aSorted)
+ {
+ SAL_INFO("svl.items", " ITEM(" << a << "): Which: " << rEntry.nWhich << " Uses: " << rEntry.nUsage << " Type: " << rEntry.pType);
+ if (++a >= nNum)
+ break;
+ }
+}
#endif
// NOTE: Only needed for one Item in SC (see notes below for
// ScPatternAttr). Still keep it so that when errors
@@ -390,14 +431,9 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS
// }
// }
- // the Item itself is shareable when it already is used somewhere
- // which is equivalent to be referenced already. IsPooledItem also
- // checked for SFX_ITEMS_MAXREF, that is not needed here. Use a
- // fake 'while' loop and 'break' to make this better readable
-
- // only try to share items that are already shared somehow, else
- // these items are probably not (heap) item-ptr's (but on the
- // stack or else)
+ // The Item itself is shareable when it is used/added at an instance
+ // that RefCounts the Item, SfxItemPool or SfxPoolItemHolder. Try
+ // to share items that are already shared
while(pSource->GetRefCount() > 0)
{
if (!pSource->isShareable())
@@ -413,6 +449,29 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS
return pSource;
}
+ // check if we can globally share the Item using the
+ // ItemInstanceManager (only for shareable Items)
+ while (!g_bDisableItemInstanceManager && pSource->isShareable())
+ {
+ ItemInstanceManager* pManager(pSource->getItemInstanceManager());
+ if (nullptr == pManager)
+ // not supported by this Item, done
+ break;
+
+ const SfxPoolItem* pAlternative(pManager->find(*pSource));
+ if(nullptr == pAlternative)
+ // none found, done
+ break;
+
+ // need to delete evtl. handed over ownership change Item
+ if (bPassingOwnership)
+ delete pSource;
+
+ // If we get here we can share the Item
+ pAlternative->AddRef();
+ return pAlternative;
+ }
+
// 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
@@ -426,6 +485,11 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS
delete pOld;
}
+#ifdef DBG_UTIL
+ // create statistics for listSfxPoolItemsWithHighestUsage
+ addUsage(*pSource);
+#endif
+
// when we reach this line we know that we have to add/create a new item. If
// bPassingOwnership is given just use the item, else clone it
if (!bPassingOwnership)
@@ -434,6 +498,15 @@ SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pS
// increase RefCnt 0->1
pSource->AddRef();
+ // check if we should register this Item for the global
+ // ItemInstanceManager mechanism (only for shareable Items)
+ if (!g_bDisableItemInstanceManager && pSource->isShareable())
+ {
+ ItemInstanceManager* pManager(pSource->getItemInstanceManager());
+ if (nullptr != pManager)
+ pManager->add(*pSource);
+ }
+
return pSource;
}
@@ -472,6 +545,15 @@ void implCleanupItemEntry(SfxPoolItem const* pSource)
// default items (static and dynamic) are owned by the pool, do not delete
return;
+ // check if we should remove this Item from the global
+ // ItemInstanceManager mechanism (only for shareable Items)
+ if (!g_bDisableItemInstanceManager && pSource->isShareable())
+ {
+ ItemInstanceManager* pManager(pSource->getItemInstanceManager());
+ if (nullptr != pManager)
+ pManager->remove(*pSource);
+ }
+
// decrease RefCnt before deleting (destructor asserts for it and that's
// good to find other errors)
pSource->ReleaseRef();
diff --git a/svl/source/items/poolitem.cxx b/svl/source/items/poolitem.cxx
index 60de354cdeba..10fda040f5cb 100644
--- a/svl/source/items/poolitem.cxx
+++ b/svl/source/items/poolitem.cxx
@@ -488,6 +488,21 @@ void listAllocatedSfxPoolItems()
}
#endif
+const SfxPoolItem* DefaultItemInstanceManager::find(const SfxPoolItem& rItem) const
+{
+ for (const auto& rCandidate : maRegistered)
+ if (rCandidate->Which() == rItem.Which() && *rCandidate == rItem)
+ return rCandidate;
+
+ return nullptr;
+}
+
+void DefaultItemInstanceManager::add(const SfxPoolItem& rItem) { maRegistered.insert(&rItem); }
+
+void DefaultItemInstanceManager::remove(const SfxPoolItem& rItem) { maRegistered.erase(&rItem); }
+
+ItemInstanceManager* SfxPoolItem::getItemInstanceManager() const { return nullptr; }
+
SfxPoolItem::SfxPoolItem(sal_uInt16 const nWhich)
: m_nRefCount(0)
, m_nWhich(nWhich)
@@ -517,7 +532,7 @@ SfxPoolItem::~SfxPoolItem()
incarnatedSfxPoolItems().erase(this);
m_bDeleted = true;
#endif
- assert((m_nRefCount == 0 || m_nRefCount > SFX_ITEMS_MAXREF) && "destroying item in use");
+ assert((m_nRefCount == 0) && "destroying item in use");
}
bool SfxPoolItem::operator==(const SfxPoolItem& rCmp) const
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index e17e4533122f..bda94ef8e898 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -207,6 +207,9 @@ Application::~Application()
// Additional call to list still incarnated SfxPoolItems (under 'svl.items')
listAllocatedSfxPoolItems();
+ // List SfxPoolItems with highest RefCounts, these are the best
+ // candidates to add a ItemInstanceManager mechanism
+ listSfxPoolItemsWithHighestUsage(20);
#endif
}