summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolan.mcnamara@collabora.com>2024-02-29 20:09:09 +0000
committerCaolán McNamara <caolan.mcnamara@collabora.com>2024-03-02 21:54:34 +0100
commit2c3605405225de4b850064cf25b15cd64be1409b (patch)
tree7a24b1cc1fdd42ae83012779777bc3389436eadd
parent4f2704920c697e8a6f053de52439dbcd49a16ce3 (diff)
avoid SvNumberFormatter lock in formula-group-threading
keep a per-interpret-thread cache of the SvNumberFormatter mapping while formula-group-threading, this is similar to: commit c2d8341ee392949274b901abfd44d9645d2e4e36 Date: Tue Oct 15 08:32:22 2019 +0530 Cache last used number-format-type in interpreter-context Change-Id: Ie99807eaf2f3260cec357f9d66307df0a69826e9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164227 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
-rw-r--r--sc/inc/column.hxx2
-rw-r--r--sc/inc/interpretercontext.hxx40
-rw-r--r--sc/inc/patattr.hxx2
-rw-r--r--sc/source/core/data/patattr.cxx11
-rw-r--r--sc/source/core/tool/interpretercontext.cxx39
5 files changed, 68 insertions, 26 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 306d7d28de3f..0aa812f038a2 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -986,7 +986,7 @@ inline const SfxPoolItem& ScColumnData::GetAttr( SCROW nRow, sal_uInt16 nWhich,
inline sal_uInt32 ScColumnData::GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const
{
- return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext.GetFormatTable() );
+ return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext );
}
inline void ScColumn::AddCondFormat( SCROW nStartRow, SCROW nEndRow, sal_uInt32 nIndex )
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 39d528cb6ca9..c46f00395cc0 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -11,6 +11,8 @@
#include <vector>
#include <memory>
+#include <i18nlangtag/lang.h>
+#include <o3tl/sorted_vector.hxx>
#include "types.hxx"
namespace formula
@@ -34,20 +36,6 @@ struct DelayedSetNumberFormat
sal_uInt32 mnNumberFormat;
};
-struct NFIndexAndFmtType
-{
- sal_uInt32 nIndex;
- SvNumFormatType eType : 16;
- bool bIsValid : 1;
-
- NFIndexAndFmtType()
- : nIndex(0)
- , eType(static_cast<SvNumFormatType>(0))
- , bIsValid(false)
- {
- }
-};
-
class ScInterpreterContextPool;
struct ScInterpreterContext
@@ -77,6 +65,8 @@ struct ScInterpreterContext
SvNumFormatType GetNumberFormatType(sal_uInt32 nFIndex) const;
+ sal_uInt32 GetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat, LanguageType eLnge) const;
+
private:
friend class ScInterpreterContextPool;
void ResetTokens();
@@ -85,7 +75,27 @@ private:
void ClearLookupCache(const ScDocument* pDoc);
void initFormatTable();
SvNumberFormatter* mpFormatter;
- mutable NFIndexAndFmtType maNFTypeCache;
+
+ template <typename T> struct CompareKey
+ {
+ bool operator()(const T& lhs, const T& rhs) const { return lhs.nKey < rhs.nKey; }
+ };
+
+ struct NFType
+ {
+ sal_uInt32 nKey;
+ mutable SvNumFormatType eType;
+ };
+ // map from format index to type
+ mutable o3tl::sorted_vector<NFType, CompareKey<NFType>> maNFTypeCache;
+
+ struct NFBuiltIn
+ {
+ sal_uInt64 nKey;
+ mutable sal_uInt32 nFormat;
+ };
+ // map from format+lang to builtin format
+ mutable o3tl::sorted_vector<NFBuiltIn, CompareKey<NFBuiltIn>> maNFBuiltInCache;
};
class ScThreadedInterpreterContextGetterGuard;
diff --git a/sc/inc/patattr.hxx b/sc/inc/patattr.hxx
index 3c790c7637e3..bbb55b5a309f 100644
--- a/sc/inc/patattr.hxx
+++ b/sc/inc/patattr.hxx
@@ -32,6 +32,7 @@
namespace vcl { class Font; }
namespace model { class ComplexColor; }
+struct ScInterpreterContext;
class OutputDevice;
class Fraction;
class ScStyleSheet;
@@ -237,6 +238,7 @@ public:
bool IsSymbolFont() const;
sal_uInt32 GetNumberFormat( SvNumberFormatter* ) const;
+ sal_uInt32 GetNumberFormat( const ScInterpreterContext& rContext ) const;
sal_uInt32 GetNumberFormat( SvNumberFormatter* pFormatter,
const SfxItemSet* pCondSet ) const;
diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx
index 59f9fa1866b4..95823cee9473 100644
--- a/sc/source/core/data/patattr.cxx
+++ b/sc/source/core/data/patattr.cxx
@@ -1652,6 +1652,17 @@ sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter ) const
return nFormat;
}
+sal_uInt32 ScPatternAttr::GetNumberFormat( const ScInterpreterContext& rContext ) const
+{
+ sal_uInt32 nFormat = getNumberFormatKey(GetItemSet());
+ LanguageType eLang = getLanguageType(GetItemSet());
+ if ( nFormat < SV_COUNTRY_LANGUAGE_OFFSET && eLang == LANGUAGE_SYSTEM )
+ ; // it remains as it is
+ else
+ nFormat = rContext.GetFormatForLanguageIfBuiltIn( nFormat, eLang );
+ return nFormat;
+}
+
// the same if conditional formatting is in play:
sal_uInt32 ScPatternAttr::GetNumberFormat( SvNumberFormatter* pFormatter,
diff --git a/sc/source/core/tool/interpretercontext.cxx b/sc/source/core/tool/interpretercontext.cxx
index deb6f6d0ed5b..03d5036b6e63 100644
--- a/sc/source/core/tool/interpretercontext.cxx
+++ b/sc/source/core/tool/interpretercontext.cxx
@@ -83,19 +83,38 @@ void ScInterpreterContext::ClearLookupCache(const ScDocument* pDoc)
SvNumFormatType ScInterpreterContext::GetNumberFormatType(sal_uInt32 nFIndex) const
{
if (!mpDoc->IsThreadedGroupCalcInProgress())
- {
return mpFormatter->GetType(nFIndex);
- }
- if (maNFTypeCache.bIsValid && maNFTypeCache.nIndex == nFIndex)
- {
- return maNFTypeCache.eType;
- }
+ // Search/update cache by attempting to find nFIndex by inserting a new entry
+ auto result = maNFTypeCache.insert(NFType{ nFIndex, SvNumFormatType::ALL });
+ if (!result.second) // already exists, so return that SvNumFormatType
+ return result.first->eType;
- maNFTypeCache.nIndex = nFIndex;
- maNFTypeCache.eType = mpFormatter->GetType(nFIndex);
- maNFTypeCache.bIsValid = true;
- return maNFTypeCache.eType;
+ // Didn't exist, overwrite the placeholder SvNumFormatType::ALL with the real type
+ SvNumFormatType eType = mpFormatter->GetType(nFIndex);
+ result.first->eType = eType;
+ return eType;
+}
+
+sal_uInt32 ScInterpreterContext::GetFormatForLanguageIfBuiltIn(sal_uInt32 nFormat,
+ LanguageType eLnge) const
+{
+ if (!mpFormatter)
+ return nFormat;
+
+ if (!mpDoc->IsThreadedGroupCalcInProgress())
+ return mpFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLnge);
+
+ sal_uInt64 nKey = (static_cast<sal_uInt64>(nFormat) << 32) | eLnge.get();
+ // Search/update cache by attempting to find nFormat+eLnge by inserting a new entry
+ auto result = maNFBuiltInCache.insert(NFBuiltIn{ nKey, 0 });
+ if (!result.second) // already exists, so return that dest Format
+ return result.first->nFormat;
+
+ // Didn't exist, overwrite the placeholder zero with the real format
+ nFormat = mpFormatter->GetFormatForLanguageIfBuiltIn(nFormat, eLnge);
+ result.first->nFormat = nFormat;
+ return nFormat;
}
/* ScInterpreterContextPool */