summaryrefslogtreecommitdiff
path: root/sc/source/filter/oox
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2023-12-23 15:52:06 +0100
committerArmin Le Grand <Armin.Le.Grand@me.com>2023-12-28 19:38:15 +0100
commit2e1f9da8a6359c8909e087a92239aefd4851b116 (patch)
treeae639bbc69342e51571fe688da79f54c8d4a23a6 /sc/source/filter/oox
parent6af35d077e9b5f5723f90f1589c5d801e79ccd4d (diff)
Decouple ScPatternAttr from SfxItemPool
ScPatternAttr is traditionally derived from SfxPoolItem (or better: SfxSetItem) and held in the ScDocumentPool as Item. This is only because of 'using' the 'poolable' functionality of the Item/ItemSet/ItemPool mechanism. Lots of hacks were added to sc and Item/ItemSet/ ItemPool to make that 'work' which shows already that this relationship is not optimal. It uses DirectPutItemInPool/DirectRemoveItemFromPool to do so, also with massive overhead to do that (and with not much success). The RefCnt in the SfxPoolItem that is used for this never worked reliably, so the SfxItemPool was (ab)used as garbage collector (all Items added and never removed get deleted at last for good when the Pool goes down). For this reasons and to be able to further get ItemSets modernized I changed this. I did two big changes here: (1) No longer derive ScPatternAttr from SfxItemSet/ SfxSetItem, no longer hold as SfxPoolItem (2) Add tooling to reliably control the lifetime of ScPatternAttr instances and ther uniqueness/ reusage for memory reasons It is now a regular non-derived class. The SfxItemSet formally derived from SfxSetItem is now a member. The RefCnt is now also a member (so independent from size/data type of SfxPoolItem). All in all it's pretty much the same size as before. To support handling it I created a CellAttributeHelper that is at/owned by ScDocument and takes over tooling to handle the ScPatternAttr. It supports to guarantee the uniqueness of incarnated ScPatternAttr instances for a ScDocument by providing helpers like registerAndCheck and doUnregister. It hosts the default CellAttribute/ ScPatternAttr. That default handling was anyways not using the standard default-handling of Items/Pools. I adapted whole SC to use that mainly by replacing calls to DirectPutItemInPool with registerAndCheck and DirectRemoveItemFromPool with doUnregister, BUT: This was not sufficient, the RefCnt kept to be broken. For that reason I decided to also do (2) in this change: I added a CellAttributeHolder that owns/regulates the lifetime of a single ScPatternAttr. Originally it also contained the CellAttributeHolder, but after some thoughts I decided that this is not needed - if there is no ScPatternAttr set, no CellAttributeHolder is needed for safe cleanup at destruction of the helper. So I moved/added the CellAttributeHolder to ScPatternAttr where it belongs more naturally anyways. The big plus is that CellAttributeHolder is just one ptr, so not bigger than having a simple ScPatternAttr*. That way, e.g. ScAttrEntry in ScAttrArray did not 'grow' at all. In principle all places where a ScPatternAttr* is used can now be replaced by using a CellAttributeHolder, except for construction. It is capable to be initialized with either ScPatternAttr instances from the heap (it creates a copy that then gets RefCounted) or allocated (it supports ownership change at construction time). Note that ScAttrEntry started to get more a C++ class in that change, it has a constructor. I did not change the SCROW member, but that should also be done. Also made registerAndCheck/doUnregister private in CellAttributeHelper and exclusively used by CellAttributeHolder. That way the RefCnt works, and a lot of code gets much simpler (check ScItemPoolCache, it's now straightforward) and safer and ~ScPatternAttr() uses now a hard assert(!isRegistered()); which shows that RefCnt works now (the 1st time?). There can be done more (see ToDo section below) but I myself will concentrate on getting ItemSets forward. This decoupling makes both involved mechanisms more safe, less complex and more stable. It also opens up possibilities to further optimize ScPatternAttr in SC without further hacking Item/ItemSet/ItemPool stuff. NOTE: ScPatternAttr *should* be renamed to 'CellAttribute' which describes what it is. The experiencd devs may know what it does, but it is a hindrance for understanding for attacting new devs. I already used now names like CellAttributeHelper/CellAttributeHolder etc., but abstained from renaming ScPatternAttr, see ToDo list below. SfxItemSet discussion: ScPatternAttr still contains a SfxItemSet, or better, a SfxSetItem. For that reason it still depends on access to an SfxItemPool (so there is acces in CellAttributeHelper). This is in principle not needed - no Item (in the range [ATTR_PATTERN_START .. ATTR_PATTERN_END]) needs that. In principle ScPatternAttr could now do it's own handling of those needed Items, however this might be done (linear array, hash-by-WhichID, ...). The Items get translated to and from this to the rest of the office anyways. Note that *merging* of SfxItemSets is *still* needed what means to have WhichID slots in SfxItemState::DONTCARE, see note in ScPatternAttr::ScPatternAttr about that. And there is also the Surrogates stuff which would have to be checked. The other extreme is to use SfxItemSet *more*, e.g. directly derive from SfxItemSet what would make stuff easier, maybe even get back to using the 'regular' Items like all office, I doubt that that would be much slower, so why...? Also possible is to remove that range of Items exclusively used by ScPatternAttr from ScDocumentPool *completely* and create an own Pool for them, owned by CellAttributeHelper. That Pool might even be static global, so all SC Docs could share all those Items - maybe even the ScPatternAttr themselves (except the default per document). That would remove the dependency of ScPatternAttr from a Pool completely. ToDo-List: - rename ScPatternAttr to CellAttribute or similar - use SfxItemSetFixed with range [ATTR_PATTERN_START .. ATTR_PATTERN_END] instead of regular SfxItemSet (if the copy-construtor works now...?) - maybe create own/separate Pool for exclusive Items - make ScAttrEntry more a C++ class by moving SCROW to the private section, add get/set methods and adapt SC Had to add some more usages of CellAttributeHolder to the SC Sort mechanism, there were situations where the sorted ScPatternAttr were replaced in the Table, but the 'sorted' ones were just ScPatternAttr*, thus deleting the valid ones in the Table already. Using CellAttributeHolder makes this safe, too. Added a small, one-entry cache to CellAttributeHelper to buffer the last found buffered ScPattrnAttr. It has a HitRate of ca. 5-6% and brings the UnitTest testSheetCellRangeProperties from 0m48,710s to 0m37,556s. Not too massive, but erery bit counts :-) Also shows that after that change optimizations in the now split functionality is possible and easy. Change-Id: I268a7b2a943ce5ddfe3c75b5e648c0f6b0cedb85 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161244 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
Diffstat (limited to 'sc/source/filter/oox')
-rw-r--r--sc/source/filter/oox/sheetdatabuffer.cxx7
-rw-r--r--sc/source/filter/oox/stylesbuffer.cxx14
2 files changed, 10 insertions, 11 deletions
diff --git a/sc/source/filter/oox/sheetdatabuffer.cxx b/sc/source/filter/oox/sheetdatabuffer.cxx
index 98d50c2a05c3..f42694f5623a 100644
--- a/sc/source/filter/oox/sheetdatabuffer.cxx
+++ b/sc/source/filter/oox/sheetdatabuffer.cxx
@@ -508,7 +508,7 @@ void SheetDataBuffer::finalizeImport()
nScRow++;
}
if ( !pDefPattern || nScRow == rDoc.MaxRow() )
- pDefPattern = rDoc.GetDefPattern();
+ pDefPattern = &rDoc.getCellAttributeHelper().getDefaultCellAttribute();
Xf::AttrList aAttrs(pDefPattern);
for ( const auto& rRowStyle : rRowStyles )
@@ -523,11 +523,10 @@ void SheetDataBuffer::finalizeImport()
{
ScAttrEntry aEntry;
aEntry.nEndRow = rDoc.MaxRow();
- aEntry.pPattern = pDefPattern;
- rDoc.GetPool()->DirectPutItemInPool(*aEntry.pPattern);
+ aEntry.setScPatternAttr(pDefPattern, false);
aAttrs.maAttrs.push_back(aEntry);
- if (!sc::NumFmtUtil::isLatinScript(*aEntry.pPattern, rDoc))
+ if (!sc::NumFmtUtil::isLatinScript(*aEntry.getScPatternAttr(), rDoc))
aAttrs.mbLatinNumFmtOnly = false;
}
diff --git a/sc/source/filter/oox/stylesbuffer.cxx b/sc/source/filter/oox/stylesbuffer.cxx
index f31cde38bcff..22ebb2025833 100644
--- a/sc/source/filter/oox/stylesbuffer.cxx
+++ b/sc/source/filter/oox/stylesbuffer.cxx
@@ -2140,7 +2140,7 @@ void Xf::applyPatternToAttrList( AttrList& rAttrs, SCROW nRow1, SCROW nRow2, sal
}
if ( !pCachedPattern && nNumFmtId >= 0 )
{
- ScPatternAttr aNumPat(rDoc.GetPool());
+ ScPatternAttr aNumPat(rDoc.getCellAttributeHelper());
mnScNumFmt = getStyles().writeNumFmtToItemSet( aNumPat.GetItemSet(), nNumFmtId, false );
rPat.GetItemSet().Put(aNumPat.GetItemSet());
}
@@ -2166,24 +2166,24 @@ void Xf::applyPatternToAttrList( AttrList& rAttrs, SCROW nRow1, SCROW nRow2, sal
// Fill this gap with the default pattern.
ScAttrEntry aEntry;
aEntry.nEndRow = nRow1 - 1;
- aEntry.pPattern = &rDoc.GetPool()->DirectPutItemInPool(*rAttrs.mpDefPattern);
+ aEntry.setScPatternAttr(rAttrs.mpDefPattern, false);
rAttrs.maAttrs.push_back(aEntry);
// Check if the default pattern is 'General'.
- if (!rDocImport.isLatinScript(*aEntry.pPattern))
+ if (!rDocImport.isLatinScript(*aEntry.getScPatternAttr()))
rAttrs.mbLatinNumFmtOnly = false;
}
ScAttrEntry aEntry;
aEntry.nEndRow = nRow2;
- aEntry.pPattern = &rDoc.GetPool()->DirectPutItemInPool(rPat);
+ aEntry.setScPatternAttr(&rPat, false);
// Put the allocated pattern to cache
if (!pCachedPattern)
- rCache.add(nXfId, nNumFmtId, const_cast<ScPatternAttr*>(aEntry.pPattern));
+ rCache.add(nXfId, nNumFmtId, const_cast<ScPatternAttr*>(aEntry.getScPatternAttr()));
rAttrs.maAttrs.push_back(aEntry);
- if (!rDocImport.isLatinScript(*aEntry.pPattern))
+ if (!rDocImport.isLatinScript(*aEntry.getScPatternAttr()))
rAttrs.mbLatinNumFmtOnly = false;
}
@@ -2218,7 +2218,7 @@ Xf::createPattern( bool bSkipPoolDefs )
{
if( mpPattern )
return *mpPattern;
- mpPattern.reset( new ::ScPatternAttr( getScDocument().GetPool() ) );
+ mpPattern.reset( new ::ScPatternAttr(getScDocument().getCellAttributeHelper()) );
SfxItemSet& rItemSet = mpPattern->GetItemSet();
/* Enables the used flags, if the formatting attributes differ from the
style XF. In cell XFs Excel uses the cell attributes, if they differ