[Libreoffice-commits] core.git: Branch 'feature/calc-parallel' - 49 commits - cui/source dbaccess/source filter/source formula/source include/connectivity include/formula include/sal include/svtools include/svx include/tools odk/examples officecfg/registry sal/qa sal/rtl sc/inc sc/source sd/source svl/source svx/source sw/inc sw/qa sw/source toolkit/source tools/source UnoControls/source vcl/source xmloff/source
Dennis Francis
dennis.francis at collabora.co.uk
Tue Nov 21 08:20:50 UTC 2017
Rebased ref, commits from common ancestor:
commit 53a39ffb351fd844afa8185c4f7e50ffa9569c88
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Fri Nov 17 15:30:35 2017 +0530
Move token-cache for doubles to ScInterpreterContext...
...from ScInterpreter and in the s/w interpreter, create
a ScInterpreterContext for each thread for passing into
per thread ScInterpreter constructor.
Change-Id: I4e0abce043c7e1e70859efb2e5001fc284f416a9
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 44bee716bf18..acd899e7658a 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -583,7 +583,7 @@ public:
void SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen );
void SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen );
- void CalculateInThread( const ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal );
+ void CalculateInThread( ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal );
void HandleStuffAfterParallelCalculation( SCROW nRow, size_t nLen );
void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 8b138378dda3..c4db749eab6a 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -458,6 +458,8 @@ private:
// plain thread_local static member.
thread_local static ScDocumentThreadSpecific maThreadSpecific;
+ mutable ScInterpreterContext maInterpreterContext;
+
sal_uInt16 nSrcVer; // file version (load/save)
sal_uInt16 nFormulaTrackCount;
HardRecalcState eHardRecalcState; // off, temporary, eternal
@@ -560,10 +562,11 @@ public:
SC_DLLPUBLIC void InitDrawLayer( SfxObjectShell* pDocShell = nullptr );
- ScInterpreterContext GetNonThreadedContext() const
+ ScInterpreterContext& GetNonThreadedContext() const
{
// GetFormatTable() asserts that we are not in a threaded calculation
- return ScInterpreterContext(*this, GetFormatTable());
+ maInterpreterContext.mpFormatter = GetFormatTable();
+ return maInterpreterContext;
}
SC_DLLPUBLIC sfx2::LinkManager* GetLinkManager();
@@ -2056,7 +2059,7 @@ public:
void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen );
void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const formula::FormulaConstTokenRef* pResults, size_t nLen );
- ScDocumentThreadSpecific CalculateInColumnInThread( const ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
+ ScDocumentThreadSpecific CalculateInColumnInThread( ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
void HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen );
/**
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 0185e2629010..e75416de8e56 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -150,7 +150,7 @@ public:
SCITP_FROM_ITERATION,
SCITP_CLOSE_ITERATION_CIRCLE
};
- void InterpretTail( const ScInterpreterContext&, ScInterpretTailParameter );
+ void InterpretTail( ScInterpreterContext&, ScInterpretTailParameter );
void HandleStuffAfterParallelCalculation();
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index cbf05349ca5f..ff52267dfb26 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -10,6 +10,11 @@
#ifndef INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX
#define INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX
+#include <vector>
+#include <formula/token.hxx>
+
+#define TOKEN_CACHE_SIZE 8
+
class ScDocument;
class SvNumberFormatter;
@@ -17,15 +22,22 @@ struct ScInterpreterContext
{
const ScDocument& mrDoc;
SvNumberFormatter* mpFormatter;
+ size_t mnTokenCachePos;
+ std::vector<formula::FormulaToken*> maTokens;
ScInterpreterContext(const ScDocument& rDoc, SvNumberFormatter* pFormatter) :
mrDoc(rDoc),
- mpFormatter(pFormatter)
+ mpFormatter(pFormatter),
+ mnTokenCachePos(0),
+ maTokens(TOKEN_CACHE_SIZE, nullptr)
{
}
~ScInterpreterContext()
{
+ for ( auto p : maTokens )
+ if ( p )
+ p->DecRef();
}
SvNumberFormatter* GetFormatTable() const
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 1f77ae4d2e39..3721e2226a5a 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -998,7 +998,7 @@ public:
void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen );
void SetFormulaResults( SCCOL nCol, SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen );
- void CalculateInColumnInThread( const ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
+ void CalculateInColumnInThread( ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
void HandleStuffAfterParallelCalculation( SCCOL nCol, SCROW nRow, size_t nLen);
/**
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index daeda62bd881..fea8d080dd13 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2877,7 +2877,7 @@ void ScColumn::SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRe
}
}
-void ScColumn::CalculateInThread( const ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
+void ScColumn::CalculateInThread( ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
{
assert(pDocument->mbThreadedGroupCalcInProgress);
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index b15ee591a7e2..9bf0fcf73194 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -177,6 +177,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) :
nInterpretLevel(0),
nMacroInterpretLevel(0),
nInterpreterTableOpLevel(0),
+ maInterpreterContext( *this, nullptr ),
nSrcVer( SC_CURRENT_VERSION ),
nFormulaTrackCount(0),
eHardRecalcState(HardRecalcState::OFF),
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 8bf1de3fb191..c7be637fb073 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -427,7 +427,7 @@ void ScDocument::SetFormulaResults(
pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
}
-ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( const ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
+ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
{
ScTable* pTab = FetchTable(rTopPos.Tab());
if (!pTab)
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index e68325c59e0e..329f1afa5034 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1746,7 +1746,7 @@ class StackCleaner
};
}
-void ScFormulaCell::InterpretTail( const ScInterpreterContext& rContext, ScInterpretTailParameter eTailParam )
+void ScFormulaCell::InterpretTail( ScInterpreterContext& rContext, ScInterpretTailParameter eTailParam )
{
RecursionCounter aRecursionCounter( pDocument->GetRecursionHelper(), this);
nSeenInIteration = pDocument->GetRecursionHelper().GetIteration();
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index e43ab0efc7ac..0b23c7474e91 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2338,7 +2338,7 @@ void ScTable::SetFormulaResults(
aCol[nCol].SetFormulaResults(nRow, pResults, nLen);
}
-void ScTable::CalculateInColumnInThread( const ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
+void ScTable::CalculateInColumnInThread( ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
{
if (!ValidCol(nCol))
return;
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index a6eaf5cd78ae..d6a77f2b9c1a 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -97,7 +97,6 @@ class SharedStringPool;
}
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
-#define TOKEN_CACHE_SIZE 8
class ScTokenStack
{
@@ -200,7 +199,7 @@ private:
formula::FormulaTokenIterator aCode;
ScAddress aPos;
ScTokenArray& rArr;
- const ScInterpreterContext& mrContext;
+ ScInterpreterContext& mrContext;
ScDocument* pDok;
sfx2::LinkManager* mpLinkManager;
svl::SharedStringPool& mrStrPool;
@@ -230,8 +229,6 @@ private:
bool bMatrixFormula; // formula cell is a matrix formula
VolatileType meVolatileType;
- size_t mnTokenCachePos;
- std::vector<formula::FormulaToken*> maTokenCache;
/// Merge global and document specific settings.
void MergeCalcConfig();
@@ -994,7 +991,7 @@ private:
double GetTInv( double fAlpha, double fSize, int nType );
public:
- ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, const ScInterpreterContext& rContext,
+ ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext,
const ScAddress&, ScTokenArray& );
~ScInterpreter();
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index a29030557032..f6565e732086 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -155,6 +155,7 @@ public:
ScAddress aBatchTopPos,
const ScAddress& rTopPos,
ScDocument& rDoc,
+ SvNumberFormatter* pFormatter,
std::vector<formula::FormulaConstTokenRef>& rRes,
SCROW nIndex,
SCROW nLastIndex) :
@@ -162,6 +163,7 @@ public:
maBatchTopPos(aBatchTopPos),
mrTopPos(rTopPos),
mrDoc(rDoc),
+ mpFormatter(pFormatter),
mrResults(rRes),
mnIdx(nIndex),
mnLastIdx(nLastIndex)
@@ -296,7 +298,8 @@ public:
ScCompiler aComp(&mrDoc, maBatchTopPos, aCode2);
aComp.CompileTokenArray();
- ScInterpreter aInterpreter(pDest, &mrDoc, mrDoc.GetNonThreadedContext(), maBatchTopPos, aCode2);
+ ScInterpreterContext aContext(mrDoc, mpFormatter);
+ ScInterpreter aInterpreter(pDest, &mrDoc, aContext, maBatchTopPos, aCode2);
aInterpreter.Interpret();
mrResults[i] = aInterpreter.GetResultToken();
} // Row iteration for loop end
@@ -307,6 +310,7 @@ private:
ScAddress maBatchTopPos;
const ScAddress& mrTopPos;
ScDocument& mrDoc;
+ SvNumberFormatter* mpFormatter;
std::vector<formula::FormulaConstTokenRef>& mrResults;
SCROW mnIdx;
SCROW mnLastIdx;
@@ -333,11 +337,12 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
ScAddress aBatchTopPos,
const ScAddress& rTopPos2,
ScDocument& rDoc2,
+ SvNumberFormatter* pFormatter2,
std::vector<formula::FormulaConstTokenRef>& rRes,
SCROW nIndex,
SCROW nLastIndex) :
comphelper::ThreadTask(rTag),
- maSWIFunc(rCode2, aBatchTopPos, rTopPos2, rDoc2, rRes, nIndex, nLastIndex)
+ maSWIFunc(rCode2, aBatchTopPos, rTopPos2, rDoc2, pFormatter2, rRes, nIndex, nLastIndex)
{
}
virtual void doWork() override
@@ -353,6 +358,8 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
bool bUseThreading = !bThreadingProhibited && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get();
+ SvNumberFormatter* pFormatter = rDoc.GetNonThreadedContext().GetFormatTable();
+
if (bUseThreading)
{
comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool());
@@ -381,7 +388,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
if ( nRemaining )
--nRemaining;
SCROW nLast = nStart + nCount - 1;
- rThreadPool.pushTask(new Executor(aTag, rCode, aTmpPos, rTopPos, rDoc, aResults, nStart, nLast));
+ rThreadPool.pushTask(new Executor(aTag, rCode, aTmpPos, rTopPos, rDoc, pFormatter, aResults, nStart, nLast));
aTmpPos.IncRow(nCount);
nLeft -= nCount;
nStart = nLast + 1;
@@ -392,7 +399,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
}
else
{
- SoftwareInterpreterFunc aSWIFunc(rCode, aTmpPos, rTopPos, rDoc, aResults, 0, xGroup->mnLength - 1);
+ SoftwareInterpreterFunc aSWIFunc(rCode, aTmpPos, rTopPos, rDoc, pFormatter, aResults, 0, xGroup->mnLength - 1);
aSWIFunc();
}
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 9ce2d00dde17..28f14137f077 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -1730,15 +1730,13 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, short nFmt )
{
- if ( maTokenCache.size() != TOKEN_CACHE_SIZE )
- maTokenCache.resize( TOKEN_CACHE_SIZE );
+ assert( mrContext.maTokens.size() == TOKEN_CACHE_SIZE );
// Find a spare token
- for ( auto p : maTokenCache )
+ for ( auto p : mrContext.maTokens )
{
if (p && p->GetRef() == 1)
{
- p->IncRef();
p->GetDoubleAsReference() = fVal;
p->SetDoubleType( nFmt );
return p;
@@ -1747,12 +1745,11 @@ formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, sho
// Allocate a new token
auto p = new FormulaTypedDoubleToken( fVal, nFmt );
- size_t pos = (mnTokenCachePos++) % TOKEN_CACHE_SIZE;
- if ( maTokenCache[pos] )
- maTokenCache[pos]->DecRef();
- maTokenCache[pos] = p;
+ if ( mrContext.maTokens[mrContext.mnTokenCachePos] )
+ mrContext.maTokens[mrContext.mnTokenCachePos]->DecRef();
+ mrContext.maTokens[mrContext.mnTokenCachePos] = p;
p->IncRef();
-
+ mrContext.mnTokenCachePos = (mrContext.mnTokenCachePos + 1) % TOKEN_CACHE_SIZE;
return p;
}
@@ -3811,7 +3808,7 @@ void ScInterpreter::ScTTT()
PushError(FormulaError::NoValue);
}
-ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, const ScInterpreterContext& rContext,
+ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext,
const ScAddress& rPos, ScTokenArray& r )
: aCode(r)
, aPos(rPos)
@@ -3871,11 +3868,6 @@ ScInterpreter::~ScInterpreter()
else
delete pStackObj;
delete pTokenMatrixMap;
-
- for ( auto p : maTokenCache )
- if ( p && p->GetRef() == 1 )
- p->DecRef();
-
}
ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
commit a9b86336d1bfec11328933532cca4f895d1569ad
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Fri Nov 17 14:05:56 2017 +0530
Type check the tokens before reuse
If the exisiting token is of wrong type, create and use a fresh new
token instead.
Change-Id: I348b0972306497dfe7eae0655c9b93d5830cb740
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index f5b90416e95f..a29030557032 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -206,13 +206,26 @@ public:
if ( !pTargetTok )
aCode2.AddString(rPool.intern(OUString(pStr)));
else
- pTargetTok->SetString(rPool.intern(OUString(pStr)));
+ {
+ if ( pTargetTok->GetType() == formula::svString )
+ pTargetTok->SetString(rPool.intern(OUString(pStr)));
+ else
+ {
+ formula::FormulaStringToken* pStrTok = new formula::FormulaStringToken(rPool.intern(OUString(pStr)));
+ aCode2.ReplaceToken(nTokIdx, pStrTok, formula::FormulaTokenArray::CODE_ONLY);
+ }
+ }
}
else if (rtl::math::isNan(fVal))
{
// Value of NaN represents an empty cell.
if ( !pTargetTok )
aCode2.AddToken(ScEmptyCellToken(false, false));
+ else if ( pTargetTok->GetType() != formula::svEmptyCell )
+ {
+ ScEmptyCellToken* pEmptyTok = new ScEmptyCellToken(false, false);
+ aCode2.ReplaceToken(nTokIdx, pEmptyTok, formula::FormulaTokenArray::CODE_ONLY);
+ }
}
else
{
@@ -220,7 +233,15 @@ public:
if ( !pTargetTok )
aCode2.AddDouble(fVal);
else
- pTargetTok->GetDoubleAsReference() = fVal;
+ {
+ if ( pTargetTok->GetType() == formula::svDouble )
+ pTargetTok->GetDoubleAsReference() = fVal;
+ else
+ {
+ formula::FormulaDoubleToken* pDoubleTok = new formula::FormulaDoubleToken( fVal );
+ aCode2.ReplaceToken(nTokIdx, pDoubleTok, formula::FormulaTokenArray::CODE_ONLY);
+ }
+ }
}
}
break;
commit 9001d50e7c77ef2242ed5bbc79981dd85e1de228
Author: Eike Rathke <erack at redhat.com>
Date: Wed Nov 15 18:08:30 2017 +0100
Assert also new FormulaToken::SetDoubleType() virtual dummy
Change-Id: I4532d0329dc7cd2609bc96abba140aba3f3d36f3
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 2ed68521e720..07ff7cc59b6e 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -218,7 +218,7 @@ short FormulaToken::GetDoubleType() const
void FormulaToken::SetDoubleType( short )
{
- SAL_WARN( "formula.core", "FormulaToken::SetDoubleType: virtual dummy called" );
+ assert( !"virtual dummy called" );
}
svl::SharedString FormulaToken::GetString() const
commit b95cb869b21147f1452a82e17ecd47caf243ea8c
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Wed Nov 15 21:08:44 2017 +0530
cache FormulaToken for doubles
Change-Id: Ic0b4dff6f03ef3f88bd150e798fa2d83dfb0f486
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 04c4a203284d..2ed68521e720 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -216,6 +216,11 @@ short FormulaToken::GetDoubleType() const
return 0;
}
+void FormulaToken::SetDoubleType( short )
+{
+ SAL_WARN( "formula.core", "FormulaToken::SetDoubleType: virtual dummy called" );
+}
+
svl::SharedString FormulaToken::GetString() const
{
SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
@@ -1797,6 +1802,11 @@ short FormulaTypedDoubleToken::GetDoubleType() const
return mnType;
}
+void FormulaTypedDoubleToken::SetDoubleType( short nType )
+{
+ mnType = nType;
+}
+
bool FormulaTypedDoubleToken::operator==( const FormulaToken& r ) const
{
return FormulaDoubleToken::operator==( r ) && mnType == r.GetDoubleType();
diff --git a/include/formula/token.hxx b/include/formula/token.hxx
index 9b06ae48182c..3de7c761d658 100644
--- a/include/formula/token.hxx
+++ b/include/formula/token.hxx
@@ -181,6 +181,7 @@ public:
virtual double GetDouble() const;
virtual double& GetDoubleAsReference();
virtual short GetDoubleType() const;
+ virtual void SetDoubleType( short nType );
virtual svl::SharedString GetString() const;
virtual void SetString( const svl::SharedString& rStr );
virtual sal_uInt16 GetIndex() const;
@@ -321,6 +322,7 @@ public:
virtual FormulaToken* Clone() const override { return new FormulaTypedDoubleToken(*this); }
virtual short GetDoubleType() const override;
+ virtual void SetDoubleType( short nType ) override;
virtual bool operator==( const FormulaToken& rToken ) const override;
DECL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaTypedDoubleToken )
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 8a240e617261..a6eaf5cd78ae 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -97,6 +97,7 @@ class SharedStringPool;
}
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
+#define TOKEN_CACHE_SIZE 8
class ScTokenStack
{
@@ -229,6 +230,8 @@ private:
bool bMatrixFormula; // formula cell is a matrix formula
VolatileType meVolatileType;
+ size_t mnTokenCachePos;
+ std::vector<formula::FormulaToken*> maTokenCache;
/// Merge global and document specific settings.
void MergeCalcConfig();
@@ -395,6 +398,7 @@ private:
sc::RangeMatrix PopRangeMatrix();
void QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr);
+ formula::FormulaToken* CreateFormulaDoubleToken( double fVal, short nFmt = css::util::NumberFormat::NUMBER );
formula::FormulaToken* CreateDoubleOrTypedToken( double fVal );
void PushDouble(double nVal);
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 73e91cfb6271..9ce2d00dde17 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -731,7 +731,7 @@ void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
{
TreatDoubleError( fVal);
if (!IfErrorPushError())
- PushTempTokenWithoutError( new FormulaDoubleToken( fVal));
+ PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal));
}
else
{
@@ -1687,7 +1687,7 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
{
if ( xMat->IsEmptyPath( 0, 0))
{ // result of empty FALSE jump path
- FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
+ FormulaTokenRef xRes = CreateFormulaDoubleToken( 0.0);
PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
rRetTypeExpr = css::util::NumberFormat::LOGICAL;
}
@@ -1716,7 +1716,7 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
if (nErr != FormulaError::NONE)
xRes = new FormulaErrorToken( nErr);
else
- xRes = new FormulaDoubleToken( nMatVal.fVal);
+ xRes = CreateFormulaDoubleToken( nMatVal.fVal);
PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
if ( rRetTypeExpr != css::util::NumberFormat::LOGICAL )
rRetTypeExpr = css::util::NumberFormat::NUMBER;
@@ -1728,14 +1728,42 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
SetError( FormulaError::UnknownStackVariable);
}
+formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, short nFmt )
+{
+ if ( maTokenCache.size() != TOKEN_CACHE_SIZE )
+ maTokenCache.resize( TOKEN_CACHE_SIZE );
+
+ // Find a spare token
+ for ( auto p : maTokenCache )
+ {
+ if (p && p->GetRef() == 1)
+ {
+ p->IncRef();
+ p->GetDoubleAsReference() = fVal;
+ p->SetDoubleType( nFmt );
+ return p;
+ }
+ }
+
+ // Allocate a new token
+ auto p = new FormulaTypedDoubleToken( fVal, nFmt );
+ size_t pos = (mnTokenCachePos++) % TOKEN_CACHE_SIZE;
+ if ( maTokenCache[pos] )
+ maTokenCache[pos]->DecRef();
+ maTokenCache[pos] = p;
+ p->IncRef();
+
+ return p;
+}
+
formula::FormulaToken* ScInterpreter::CreateDoubleOrTypedToken( double fVal )
{
// NumberFormat::NUMBER is the default untyped double.
if (nFuncFmtType && nFuncFmtType != css::util::NumberFormat::NUMBER &&
nFuncFmtType != css::util::NumberFormat::UNDEFINED)
- return new FormulaTypedDoubleToken( fVal, nFuncFmtType);
+ return CreateFormulaDoubleToken( fVal, nFuncFmtType);
else
- return new FormulaDoubleToken( fVal);
+ return CreateFormulaDoubleToken( fVal);
}
void ScInterpreter::PushDouble(double nVal)
@@ -3843,6 +3871,11 @@ ScInterpreter::~ScInterpreter()
else
delete pStackObj;
delete pTokenMatrixMap;
+
+ for ( auto p : maTokenCache )
+ if ( p && p->GetRef() == 1 )
+ p->DecRef();
+
}
ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
@@ -4584,7 +4617,7 @@ StackVar ScInterpreter::Interpret()
nRetIndexExpr = 0; // carry format index only for matching type
nRetTypeExpr = nFuncFmtType = nCurFmtType;
}
- PushTempToken( new FormulaDoubleToken( fVal));
+ PushTempToken( CreateFormulaDoubleToken( fVal));
}
if ( nFuncFmtType == css::util::NumberFormat::UNDEFINED )
{
commit c44c82d692b2df6b0c8767ce10092b0dda952b22
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Wed Nov 15 17:09:08 2017 +0530
halve thread count if HT active for group interpreter too
Change-Id: Iacc93122191152183127500a4172358a14e96c8b
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 12cbd1493bee..e68325c59e0e 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -49,6 +49,7 @@
#include <tokenarray.hxx>
#include <comphelper/threadpool.hxx>
+#include <tools/cpuid.hxx>
#include <formula/errorcodes.hxx>
#include <formula/vectortoken.hxx>
#include <svl/intitem.hxx>
@@ -4360,6 +4361,8 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
+ static bool bHyperThreadingActive = tools::cpuid::hasHyperThreading();
+
// Then do the threaded calculation
class Executor : public comphelper::ThreadTask
@@ -4404,6 +4407,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool());
sal_Int32 nThreadCount = rThreadPool.getWorkerCount();
+ if ( bHyperThreadingActive && nThreadCount >= 2 )
+ nThreadCount /= 2;
+
SAL_INFO("sc.threaded", "Running " << nThreadCount << " threads");
{
commit b473824819a6726d0a2438699984a2a6010e55b7
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Wed Nov 15 16:52:44 2017 +0530
Disable custom allocator
This has big positive effect on software interpreter threading
performance scaling.
Change-Id: I8fbb6bf8f7ed410fd53278acee63bf65f13bac38
diff --git a/sal/rtl/alloc_global.cxx b/sal/rtl/alloc_global.cxx
index 3d74287bc7e5..47643f3ea74a 100644
--- a/sal/rtl/alloc_global.cxx
+++ b/sal/rtl/alloc_global.cxx
@@ -35,7 +35,7 @@ AllocMode alloc_mode = AllocMode::UNSET;
static void determine_alloc_mode()
{
assert(alloc_mode == AllocMode::UNSET);
- alloc_mode = (getenv("G_SLICE") == nullptr ? AllocMode::CUSTOM : AllocMode::SYSTEM);
+ alloc_mode = AllocMode::SYSTEM;
}
static const sal_Size g_alloc_sizes[] =
commit 6d4c635bb68798aad8de70fae33b979d78315366
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Wed Nov 15 16:37:45 2017 +0530
halve the number of threads if HT is active
added hasHyperThreading() function to tools::cpuid
to detect hyperthreading.
Change-Id: I13fab4b6c649e681c329b7e3f4c9f36bda879d84
diff --git a/include/tools/cpuid.hxx b/include/tools/cpuid.hxx
index d7aa07d54258..419d05714ae4 100644
--- a/include/tools/cpuid.hxx
+++ b/include/tools/cpuid.hxx
@@ -25,6 +25,7 @@ namespace tools
namespace cpuid
{
TOOLS_DLLPUBLIC bool hasSSE2();
+ TOOLS_DLLPUBLIC bool hasHyperThreading();
}
}
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index b7968acb19d8..f5b90416e95f 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -19,6 +19,7 @@
#include <scmatrix.hxx>
#include <globalnames.hxx>
#include <comphelper/threadpool.hxx>
+#include <tools/cpuid.hxx>
#include <formula/vectortoken.hxx>
#include <officecfg/Office/Common.hxx>
@@ -299,6 +300,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
// The caller must ensure that the top position is the start position of
// the group.
+ static bool bHyperThreadingActive = tools::cpuid::hasHyperThreading();
ScAddress aTmpPos = rTopPos;
std::vector<formula::FormulaConstTokenRef> aResults(xGroup->mnLength);
@@ -335,6 +337,9 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool());
sal_Int32 nThreadCount = rThreadPool.getWorkerCount();
+ if ( bHyperThreadingActive && nThreadCount >= 2 )
+ nThreadCount /= 2;
+
SCROW nLen = xGroup->mnLength;
SCROW nBatchSize = nLen / nThreadCount;
if (nLen < nThreadCount)
diff --git a/tools/source/misc/cpuid.cxx b/tools/source/misc/cpuid.cxx
index 1518dfc175c4..e3ba82dffda5 100644
--- a/tools/source/misc/cpuid.cxx
+++ b/tools/source/misc/cpuid.cxx
@@ -16,8 +16,6 @@ namespace tools
namespace cpuid
{
-#if defined(LO_SSE2_AVAILABLE)
-
namespace
{
#if defined(_MSC_VER)
@@ -35,6 +33,8 @@ void getCpuId(uint32_t array[4])
#endif
}
+#if defined(LO_SSE2_AVAILABLE)
+
bool hasSSE2()
{
uint32_t cpuInfoArray[] = {0, 0, 0, 0};
@@ -48,6 +48,13 @@ bool hasSSE2() { return false; }
#endif
+bool hasHyperThreading()
+{
+ uint32_t cpuInfoArray[] = {0, 0, 0, 0};
+ getCpuId(cpuInfoArray);
+ return (cpuInfoArray[3] & (1 << 28)) != 0;
+}
+
}
}
commit c682cd1fea5b15010aed8c118635b0a4e7e99ded
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Wed Nov 15 16:14:32 2017 +0530
Avoid ScTokenArray thrash
Allocate ScTokenArray object only once per worker thread, fill it
for the first row/cell and reuse them for subsequent rows/cells
if possible.
Change-Id: If8f20da618938d0e189224f189b4763815702e10
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index f0183c69a5d1..b7968acb19d8 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -171,12 +171,14 @@ public:
{
double fNan;
rtl::math::setNan(&fNan);
+ ScTokenArray aCode2;
for (SCROW i = mnIdx; i <= mnLastIdx; ++i, maBatchTopPos.IncRow())
{
- ScTokenArray aCode2;
formula::FormulaTokenArrayPlainIterator aIter(mrCode);
- for (const formula::FormulaToken* p = aIter.First(); p; p = aIter.Next())
+ size_t nTokIdx = 0;
+ for (const formula::FormulaToken* p = aIter.First(); p; p = aIter.Next(), ++nTokIdx)
{
+ formula::FormulaToken* pTargetTok = aCode2.TokenAt(nTokIdx);
switch (p->GetType())
{
case formula::svSingleVectorRef:
@@ -200,14 +202,25 @@ public:
{
// This is a string cell.
svl::SharedStringPool& rPool = mrDoc.GetSharedStringPool();
- aCode2.AddString(rPool.intern(OUString(pStr)));
+ if ( !pTargetTok )
+ aCode2.AddString(rPool.intern(OUString(pStr)));
+ else
+ pTargetTok->SetString(rPool.intern(OUString(pStr)));
}
else if (rtl::math::isNan(fVal))
+ {
// Value of NaN represents an empty cell.
- aCode2.AddToken(ScEmptyCellToken(false, false));
+ if ( !pTargetTok )
+ aCode2.AddToken(ScEmptyCellToken(false, false));
+ }
else
+ {
// Numeric cell.
- aCode2.AddDouble(fVal);
+ if ( !pTargetTok )
+ aCode2.AddDouble(fVal);
+ else
+ pTargetTok->GetDoubleAsReference() = fVal;
+ }
}
break;
case formula::svDoubleVectorRef:
@@ -229,17 +242,29 @@ public:
aRefRange.aEnd.SetRow(mrTopPos.Row() + nRowEnd);
aRef.InitRange(aRefRange);
formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
- aCode2.AddToken(*xTok);
+ if ( !pTargetTok )
+ aCode2.AddToken(*xTok);
+ else
+ aCode2.ReplaceToken(nTokIdx, xTok.get(), formula::FormulaTokenArray::CODE_ONLY);
}
else
{
- ScMatrixToken aTok(pMat);
- aCode2.AddToken(aTok);
+ if ( !pTargetTok )
+ {
+ ScMatrixToken aTok(pMat);
+ aCode2.AddToken(aTok);
+ }
+ else
+ {
+ ScMatrixToken* pMatTok = new ScMatrixToken(pMat);
+ aCode2.ReplaceToken(nTokIdx, pMatTok, formula::FormulaTokenArray::CODE_ONLY);
+ }
}
}
break;
default:
- aCode2.AddToken(*p);
+ if ( !pTargetTok )
+ aCode2.AddToken(*p);
} // end of switch statement
} // end of formula token for loop
commit 08bd6511bd9da85f04e9eec1513807582419dee7
Author: Dennis Francis <dennis.francis at collabora.co.uk>
Date: Wed Nov 1 13:45:09 2017 +0530
Thread the software interpreter
Also introduce new state
ScFormulaVectorState::FormulaVectorEnabledForThreading
to indicate that using the “traditional” vectoring is disabled,
but threading should be tried.
Change-Id: I552d9e29e1ab9e5721534e07f4a45fdd5a23f399
diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx
index 294794f959e0..8b352b447f09 100644
--- a/sc/inc/tokenarray.hxx
+++ b/sc/inc/tokenarray.hxx
@@ -92,6 +92,7 @@ public:
svl::SharedStringPool& rSPool,
formula::ExternalReferenceHelper* _pRef) override;
virtual void CheckToken( const formula::FormulaToken& r ) override;
+ void CheckForThreading( OpCode eOp );
virtual formula::FormulaToken* AddOpCode( OpCode eCode ) override;
/** ScSingleRefToken with ocPush. */
formula::FormulaToken* AddSingleReference( const ScSingleRefData& rRef );
diff --git a/sc/inc/types.hxx b/sc/inc/types.hxx
index 51898c291fde..cc82e363765d 100644
--- a/sc/inc/types.hxx
+++ b/sc/inc/types.hxx
@@ -59,6 +59,7 @@ enum ScFormulaVectorState
FormulaVectorEnabled,
FormulaVectorCheckReference,
+ FormulaVectorEnabledForThreading,
FormulaVectorUnknown
};
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index cf036ad13734..12cbd1493bee 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -4341,7 +4341,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
- if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() && pCode->GetVectorState() != FormulaVectorDisabledNotInSubSet && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
+ if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() &&
+ pCode->GetVectorState() == FormulaVectorEnabledForThreading &&
+ officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
{
// iterate over code in the formula ...
// ensure all input is pre-calculated -
@@ -4430,26 +4432,30 @@ bool ScFormulaCell::InterpretFormulaGroup()
return true;
}
+ bool bCanVectorize = false;
switch (pCode->GetVectorState())
{
case FormulaVectorEnabled:
case FormulaVectorCheckReference:
- // Good.
+ bCanVectorize = true; // Good.
break;
// Not good.
case FormulaVectorDisabledByOpCode:
aScope.addMessage("group calc disabled due to vector state (non-vector-supporting opcode)");
- return false;
+ break;
case FormulaVectorDisabledNotInSoftwareSubset:
aScope.addMessage("group calc disabled due to vector state (opcode not in software subset)");
- return false;
+ break;
case FormulaVectorDisabledByStackVariable:
aScope.addMessage("group calc disabled due to vector state (non-vector-supporting stack variable)");
- return false;
+ break;
case FormulaVectorDisabledNotInSubSet:
aScope.addMessage("group calc disabled due to vector state (opcode not in subset)");
- return false;
+ break;
+ case FormulaVectorEnabledForThreading:
+ aScope.addMessage("group calc disabled due to vector state (wanted to try threading but couldn't)");
+ break;
case FormulaVectorDisabled:
case FormulaVectorUnknown:
default:
@@ -4457,6 +4463,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
+ if (!bCanVectorize)
+ return false;
+
if (!ScCalcConfig::isOpenCLEnabled() && !ScCalcConfig::isSwInterpreterEnabled())
{
aScope.addMessage("opencl not enabled and sw interpreter not enabled");
diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx
index f637ab5753bc..f0183c69a5d1 100644
--- a/sc/source/core/tool/formulagroup.cxx
+++ b/sc/source/core/tool/formulagroup.cxx
@@ -18,9 +18,11 @@
#include <interpre.hxx>
#include <scmatrix.hxx>
#include <globalnames.hxx>
+#include <comphelper/threadpool.hxx>
#include <formula/vectortoken.hxx>
#include <officecfg/Office/Common.hxx>
+#include <officecfg/Office/Calc.hxx>
#if HAVE_FEATURE_OPENCL
#include <opencl/platforminfo.hxx>
#endif
@@ -145,117 +147,208 @@ ScMatrixRef FormulaGroupInterpreterSoftware::inverseMatrix(const ScMatrix& /*rMa
return ScMatrixRef();
}
+class SoftwareInterpreterFunc
+{
+public:
+ SoftwareInterpreterFunc(ScTokenArray& rCode,
+ ScAddress aBatchTopPos,
+ const ScAddress& rTopPos,
+ ScDocument& rDoc,
+ std::vector<formula::FormulaConstTokenRef>& rRes,
+ SCROW nIndex,
+ SCROW nLastIndex) :
+ mrCode(rCode),
+ maBatchTopPos(aBatchTopPos),
+ mrTopPos(rTopPos),
+ mrDoc(rDoc),
+ mrResults(rRes),
+ mnIdx(nIndex),
+ mnLastIdx(nLastIndex)
+ {
+ }
+
+ void operator() ()
+ {
+ double fNan;
+ rtl::math::setNan(&fNan);
+ for (SCROW i = mnIdx; i <= mnLastIdx; ++i, maBatchTopPos.IncRow())
+ {
+ ScTokenArray aCode2;
+ formula::FormulaTokenArrayPlainIterator aIter(mrCode);
+ for (const formula::FormulaToken* p = aIter.First(); p; p = aIter.Next())
+ {
+ switch (p->GetType())
+ {
+ case formula::svSingleVectorRef:
+ {
+ const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p);
+ const formula::VectorRefArray& rArray = p2->GetArray();
+
+ rtl_uString* pStr = nullptr;
+ double fVal = fNan;
+ if (static_cast<size_t>(i) < p2->GetArrayLength())
+ {
+ if (rArray.mpStringArray)
+ // See if the cell is of string type.
+ pStr = rArray.mpStringArray[i];
+
+ if (!pStr && rArray.mpNumericArray)
+ fVal = rArray.mpNumericArray[i];
+ }
+
+ if (pStr)
+ {
+ // This is a string cell.
+ svl::SharedStringPool& rPool = mrDoc.GetSharedStringPool();
+ aCode2.AddString(rPool.intern(OUString(pStr)));
+ }
+ else if (rtl::math::isNan(fVal))
+ // Value of NaN represents an empty cell.
+ aCode2.AddToken(ScEmptyCellToken(false, false));
+ else
+ // Numeric cell.
+ aCode2.AddDouble(fVal);
+ }
+ break;
+ case formula::svDoubleVectorRef:
+ {
+ const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p);
+ size_t nRowStart = p2->IsStartFixed() ? 0 : i;
+ size_t nRowEnd = p2->GetRefRowSize() - 1;
+ if (!p2->IsEndFixed())
+ nRowEnd += i;
+
+ assert(nRowStart <= nRowEnd);
+ ScMatrixRef pMat(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1));
+
+ if (p2->IsStartFixed() && p2->IsEndFixed())
+ {
+ // Cached the converted token for absolute range reference.
+ ScComplexRefData aRef;
+ ScRange aRefRange = mrTopPos;
+ aRefRange.aEnd.SetRow(mrTopPos.Row() + nRowEnd);
+ aRef.InitRange(aRefRange);
+ formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
+ aCode2.AddToken(*xTok);
+ }
+ else
+ {
+ ScMatrixToken aTok(pMat);
+ aCode2.AddToken(aTok);
+ }
+ }
+ break;
+ default:
+ aCode2.AddToken(*p);
+ } // end of switch statement
+ } // end of formula token for loop
+
+ ScFormulaCell* pDest = mrDoc.GetFormulaCell(maBatchTopPos);
+ if (!pDest)
+ return;
+
+ ScCompiler aComp(&mrDoc, maBatchTopPos, aCode2);
+ aComp.CompileTokenArray();
+ ScInterpreter aInterpreter(pDest, &mrDoc, mrDoc.GetNonThreadedContext(), maBatchTopPos, aCode2);
+ aInterpreter.Interpret();
+ mrResults[i] = aInterpreter.GetResultToken();
+ } // Row iteration for loop end
+ } // operator () end
+
+private:
+ ScTokenArray& mrCode;
+ ScAddress maBatchTopPos;
+ const ScAddress& mrTopPos;
+ ScDocument& mrDoc;
+ std::vector<formula::FormulaConstTokenRef>& mrResults;
+ SCROW mnIdx;
+ SCROW mnLastIdx;
+};
+
bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddress& rTopPos,
ScFormulaCellGroupRef& xGroup,
ScTokenArray& rCode)
{
- typedef std::unordered_map<const formula::FormulaToken*, formula::FormulaTokenRef> CachedTokensType;
-
// Decompose the group into individual cells and calculate them individually.
// The caller must ensure that the top position is the start position of
// the group.
ScAddress aTmpPos = rTopPos;
- std::vector<formula::FormulaConstTokenRef> aResults;
- aResults.reserve(xGroup->mnLength);
- CachedTokensType aCachedTokens;
-
- double fNan;
- rtl::math::setNan(&fNan);
+ std::vector<formula::FormulaConstTokenRef> aResults(xGroup->mnLength);
- for (SCROW i = 0; i < xGroup->mnLength; ++i, aTmpPos.IncRow())
+ class Executor : public comphelper::ThreadTask
{
- ScTokenArray aCode2;
- formula::FormulaTokenArrayPlainIterator aIter(rCode);
- for (const formula::FormulaToken* p = aIter.First(); p; p = aIter.Next())
+ public:
+ Executor(std::shared_ptr<comphelper::ThreadTaskTag>& rTag,
+ ScTokenArray& rCode2,
+ ScAddress aBatchTopPos,
+ const ScAddress& rTopPos2,
+ ScDocument& rDoc2,
+ std::vector<formula::FormulaConstTokenRef>& rRes,
+ SCROW nIndex,
+ SCROW nLastIndex) :
+ comphelper::ThreadTask(rTag),
+ maSWIFunc(rCode2, aBatchTopPos, rTopPos2, rDoc2, rRes, nIndex, nLastIndex)
{
- CachedTokensType::iterator it = aCachedTokens.find(p);
- if (it != aCachedTokens.end())
- {
- // This token is cached. Use the cached one.
- aCode2.AddToken(*it->second);
- continue;
- }
+ }
+ virtual void doWork() override
+ {
+ maSWIFunc();
+ }
- switch (p->GetType())
- {
- case formula::svSingleVectorRef:
- {
- const formula::SingleVectorRefToken* p2 = static_cast<const formula::SingleVectorRefToken*>(p);
- const formula::VectorRefArray& rArray = p2->GetArray();
+ private:
+ SoftwareInterpreterFunc maSWIFunc;
+ };
- rtl_uString* pStr = nullptr;
- double fVal = fNan;
- if (static_cast<size_t>(i) < p2->GetArrayLength())
- {
- if (rArray.mpStringArray)
- // See if the cell is of string type.
- pStr = rArray.mpStringArray[i];
+ static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
- if (!pStr && rArray.mpNumericArray)
- fVal = rArray.mpNumericArray[i];
- }
+ bool bUseThreading = !bThreadingProhibited && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get();
- if (pStr)
- {
- // This is a string cell.
- svl::SharedStringPool& rPool = rDoc.GetSharedStringPool();
- aCode2.AddString(rPool.intern(OUString(pStr)));
- }
- else if (rtl::math::isNan(fVal))
- // Value of NaN represents an empty cell.
- aCode2.AddToken(ScEmptyCellToken(false, false));
- else
- // Numeric cell.
- aCode2.AddDouble(fVal);
- }
- break;
- case formula::svDoubleVectorRef:
- {
- const formula::DoubleVectorRefToken* p2 = static_cast<const formula::DoubleVectorRefToken*>(p);
- size_t nRowStart = p2->IsStartFixed() ? 0 : i;
- size_t nRowEnd = p2->GetRefRowSize() - 1;
- if (!p2->IsEndFixed())
- nRowEnd += i;
+ if (bUseThreading)
+ {
+ comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool());
+ sal_Int32 nThreadCount = rThreadPool.getWorkerCount();
+
+ SCROW nLen = xGroup->mnLength;
+ SCROW nBatchSize = nLen / nThreadCount;
+ if (nLen < nThreadCount)
+ {
+ nBatchSize = 1;
+ nThreadCount = nLen;
+ }
+ SCROW nRemaining = nLen - nBatchSize * nThreadCount;
- assert(nRowStart <= nRowEnd);
- ScMatrixRef pMat(new ScVectorRefMatrix(p2, nRowStart, nRowEnd - nRowStart + 1));
+ SAL_INFO("sc.threaded", "Running " << nThreadCount << " threads");
- if (p2->IsStartFixed() && p2->IsEndFixed())
- {
- // Cached the converted token for absolute range reference.
- ScComplexRefData aRef;
- ScRange aRefRange = rTopPos;
- aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
- aRef.InitRange(aRefRange);
- formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
- aCachedTokens.emplace(p, xTok);
- aCode2.AddToken(*xTok);
- }
- else
- {
- ScMatrixToken aTok(pMat);
- aCode2.AddToken(aTok);
- }
- }
- break;
- default:
- aCode2.AddToken(*p);
- }
+ SCROW nLeft = nLen;
+ SCROW nStart = 0;
+ std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag();
+ while (nLeft > 0)
+ {
+ SCROW nCount = std::min(nLeft, nBatchSize) + (nRemaining ? 1 : 0);
+ if ( nRemaining )
+ --nRemaining;
+ SCROW nLast = nStart + nCount - 1;
+ rThreadPool.pushTask(new Executor(aTag, rCode, aTmpPos, rTopPos, rDoc, aResults, nStart, nLast));
+ aTmpPos.IncRow(nCount);
+ nLeft -= nCount;
+ nStart = nLast + 1;
}
+ SAL_INFO("sc.threaded", "Joining threads");
+ rThreadPool.waitUntilDone(aTag);
+ SAL_INFO("sc.threaded", "Done");
+ }
+ else
+ {
+ SoftwareInterpreterFunc aSWIFunc(rCode, aTmpPos, rTopPos, rDoc, aResults, 0, xGroup->mnLength - 1);
+ aSWIFunc();
+ }
- ScFormulaCell* pDest = rDoc.GetFormulaCell(aTmpPos);
- if (!pDest)
+ for (SCROW i = 0; i < xGroup->mnLength; ++i)
+ if (!aResults[i].get())
return false;
- ScCompiler aComp(&rDoc, aTmpPos, aCode2);
- aComp.CompileTokenArray();
- ScInterpreter aInterpreter(pDest, &rDoc, rDoc.GetNonThreadedContext(), aTmpPos, aCode2);
- aInterpreter.Interpret();
- aResults.push_back(aInterpreter.GetResultToken());
- } // for loop end (xGroup->mnLength)
-
if (!aResults.empty())
rDoc.SetFormulaResults(rTopPos, &aResults[0], aResults.size());
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 5349e2d6dff3..2ded45291544 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1336,7 +1336,7 @@ bool ScTokenArray::AddFormulaToken(
return bError;
}
-void ScTokenArray::CheckToken( const FormulaToken& r )
+void ScTokenArray::CheckForThreading( OpCode eOp )
{
static const std::set<OpCode> aThreadedCalcBlackList({
ocIndirect,
@@ -1345,23 +1345,32 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
ocTableOp
});
- if (IsFormulaVectorDisabled())
- // It's already disabled. No more checking needed.
- return;
+ // We only call this if it was already disabled
+ assert(IsFormulaVectorDisabled());
static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
- OpCode eOp = r.GetOpCode();
-
if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
{
if (aThreadedCalcBlackList.count(eOp))
{
- meVectorState = FormulaVectorDisabledNotInSubSet;
SAL_INFO("sc.core.formulagroup", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp) << " disables threaded calculation of formula group");
}
- return;
+ else
+ {
+ SAL_INFO("sc.core.formulagroup", "but enabling for threading instead");
+ meVectorState = FormulaVectorEnabledForThreading;
+ }
}
+}
+
+void ScTokenArray::CheckToken( const FormulaToken& r )
+{
+ if (IsFormulaVectorDisabled())
+ // It's already disabled. No more checking needed.
+ return;
+
+ OpCode eOp = r.GetOpCode();
if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION)
{
@@ -1370,6 +1379,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
{
SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp) << " disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledNotInSubSet;
+ CheckForThreading(eOp);
return;
}
@@ -1381,6 +1391,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
{
SAL_INFO("sc.core.formulagroup", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp) << " disables S/W interpreter for formula group");
meVectorState = FormulaVectorDisabledNotInSoftwareSubset;
+ CheckForThreading(eOp);
return;
}
@@ -1608,6 +1619,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
// We don't support vectorization on these.
SAL_INFO("sc.opencl", "opcode ocPush: variable type " << StackVarEnumToString(r.GetType()) << " disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledByStackVariable;
+ CheckForThreading(eOp);
break;
default:
;
@@ -1619,6 +1631,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
{
SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp) << " disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledNotInSubSet;
+ CheckForThreading(eOp);
}
// only when openCL interpreter is not enabled - the assumption is that
// the S/W interpreter blacklist is more strict
@@ -1629,6 +1642,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
{
SAL_INFO("sc.core.formulagroup", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp) << " disables S/W interpreter for formula group");
meVectorState = FormulaVectorDisabledNotInSoftwareSubset;
+ CheckForThreading(eOp);
}
}
@@ -1756,6 +1770,7 @@ bool ScTokenArray::IsFormulaVectorDisabled() const
case FormulaVectorDisabledNotInSoftwareSubset:
case FormulaVectorDisabledByStackVariable:
case FormulaVectorDisabledNotInSubSet:
+ case FormulaVectorEnabledForThreading:
return true;
default:
;
commit 24d93809416b756140a20a3545042e28917d4e04
Author: Tor Lillqvist <tml at collabora.com>
Date: Mon Oct 16 18:40:51 2017 +0300
Add OFFSET to blacklist for threaded calculation
Change-Id: Ia1aaf40aa4e8e6f41ca190272365528bf37bf130
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index b7c73ef7ea3d..5349e2d6dff3 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1341,6 +1341,7 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
static const std::set<OpCode> aThreadedCalcBlackList({
ocIndirect,
ocMacro,
+ ocOffset,
ocTableOp
});
commit 72eec7decb100384af55d9172911218753b467b3
Author: Tor Lillqvist <tml at collabora.com>
Date: Mon Oct 16 18:31:07 2017 +0300
Add INDIRECT to blacklist for threaded calculation
Change-Id: I9a2066c396802551c3eda2c8db32b6d1a4171dfd
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index a24f41949022..b7c73ef7ea3d 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1339,6 +1339,7 @@ bool ScTokenArray::AddFormulaToken(
void ScTokenArray::CheckToken( const FormulaToken& r )
{
static const std::set<OpCode> aThreadedCalcBlackList({
+ ocIndirect,
ocMacro,
ocTableOp
});
commit 0a308354df1570c83cd499b017461ff364458d13
Author: Tor Lillqvist <tml at collabora.com>
Date: Mon Oct 16 18:28:24 2017 +0300
Check whether ScTokenArray::CheckToken() has disabled threading of the group
Otherwise the aThreadedCalcBlackList check in CheckToken() has no
effect, we would still attempt the threaded code path.
Change-Id: I08dc2dd174459615ab8a11dbb819e39fc5437d10
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 615fbb8056f7..cf036ad13734 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -4341,7 +4341,7 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
- if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
+ if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() && pCode->GetVectorState() != FormulaVectorDisabledNotInSubSet && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
{
// iterate over code in the formula ...
// ensure all input is pre-calculated -
commit bcc6e4dd480c708bafafe44fd47591d8566f1997
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 22:55:19 2017 +0300
Avoid unused private field warning in the NDEBUG case
Change-Id: I5e37b9a8325af35a15c01409f9eaa2f92459cc28
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 73f450dc8163..a53258a2fb70 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6747,6 +6747,7 @@ ScMutationGuard::ScMutationGuard(ScDocument* pDocument, ScMutationGuardFlags nFl
mpDocument(pDocument),
mnFlags(nFlags)
{
+ (void) mpDocument;
for (unsigned b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
{
if (static_cast<std::size_t>(mnFlags) & (1 << b))
commit d07638341eade68eae61aa495cb5998c7102327a
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 16:55:59 2017 +0300
Move ScDocument::GetNonThreadedContext() inline
Did not have any impact on performance, though.
Change-Id: I7e769b4a74e0ff9e0aabfb7e291fc4b987441954
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index f37e8e7d856e..8b138378dda3 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -560,7 +560,11 @@ public:
SC_DLLPUBLIC void InitDrawLayer( SfxObjectShell* pDocShell = nullptr );
- SC_DLLPUBLIC ScInterpreterContext GetNonThreadedContext() const;
+ ScInterpreterContext GetNonThreadedContext() const
+ {
+ // GetFormatTable() asserts that we are not in a threaded calculation
+ return ScInterpreterContext(*this, GetFormatTable());
+ }
SC_DLLPUBLIC sfx2::LinkManager* GetLinkManager();
SC_DLLPUBLIC const sfx2::LinkManager* GetLinkManager() const;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 0df71931c355..73f450dc8163 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6769,13 +6769,6 @@ ScMutationGuard::~ScMutationGuard()
#endif
}
-ScInterpreterContext ScDocument::GetNonThreadedContext() const
-{
- // GetFormatTable() asserts that we are not in a threaded calculation
- ScInterpreterContext aResult(*this, GetFormatTable());
- return aResult;
-}
-
thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific;
ScRecursionHelper& ScDocument::GetRecursionHelper()
commit 6147ba802ac891910c7404c697b0e9f57f0a44d4
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 13:11:10 2017 +0300
Display the threaded calculation state in Help:About
Change-Id: I299e555392bb4b09325ad2c92f843b1e12ee4d31
diff --git a/cui/source/dialogs/about.cxx b/cui/source/dialogs/about.cxx
index a7d219407249..c9ba680c8609 100644
--- a/cui/source/dialogs/about.cxx
+++ b/cui/source/dialogs/about.cxx
@@ -53,6 +53,7 @@
#include <opencl/openclwrapper.hxx>
#endif
#include <officecfg/Office/Common.hxx>
+#include <officecfg/Office/Calc.hxx>
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::beans;
@@ -334,19 +335,31 @@ OUString AboutDialog::GetVersionString()
sVersion += m_aLocaleStr.replaceAll("$LOCALE", aLocaleStr);
}
-#if HAVE_FEATURE_OPENCL
OUString aCalcMode = "Calc: "; // Calc calculation mode
+
+#if HAVE_FEATURE_OPENCL
bool bSWInterp = officecfg::Office::Common::Misc::UseSwInterpreter::get();
bool bOpenCL = openclwrapper::GPUEnv::isOpenCLEnabled();
if (bOpenCL)
aCalcMode += "CL";
else if (bSWInterp)
aCalcMode += "group";
- else
- aCalcMode += "single";
- sVersion += "; " + aCalcMode;
+#else
+ const bool bOpenCL = false;
#endif
+ static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
+ bool bThreadedCalc = officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get();
+
+ if (!bThreadingProhibited && !bOpenCL && bThreadedCalc)
+ {
+ if (!aCalcMode.endsWith(" "))
+ aCalcMode += " ";
+ aCalcMode += "threaded";
+ }
+
+ sVersion += "; " + aCalcMode;
+
return sVersion;
}
commit b8d13501fd75c8b71f0ab7a0d3f5b965738a2c2e
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 12:40:20 2017 +0300
Make threaded calculation the default (when OpenCL is not used)
Introduce a configuration setting to turn it off. For now, can also be
turned off with the environment variable SC_NO_THREADED_CALCULATION,
but that is probably not something we want to keep or guarantee
staility of. (LO looks at way too many environment variables already.)
Change-Id: I469cde259eda72cc2d630814a25f707f1210b0ab
diff --git a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
index b1feca1825c6..72ac33b99413 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Calc.xcs
@@ -1416,6 +1416,12 @@
<info>
<desc>Contains settings for how to calculate formulae.</desc>
</info>
+ <prop oor:name="UseThreadedCalculationForFormulaGroups" oor:type="xs:boolean" oor:nillable="false">
+ <info>
+ <desc>Whether to use threaded calculation of forumula groups when applicable.</desc>
+ </info>
+ <value>true</value>
+ </prop>
<!-- Note: The default values below probably must correspond
to those assigned in setOpenCLConfigToDefault() in
sc/source/core/tool/calcconfig.cxx
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index fed52b93ddec..615fbb8056f7 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -54,6 +54,7 @@
#include <svl/intitem.hxx>
#include <o3tl/make_unique.hxx>
#include <rtl/strbuf.hxx>
+#include <officecfg/Office/Calc.hxx>
#include <formulagroup.hxx>
#include <listenercontext.hxx>
#include <types.hxx>
@@ -4322,11 +4323,10 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
- static const bool bThreadingRequested = std::getenv("CPU_THREADED_CALCULATION");
+ static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
// To temporarilu use threading for sc unit tests regardless of the size of the formula group,
- // add the condition !std::getenv("LO_TESTNAME") below (with &&), and run with
- // CPU_THREADED_CALCULATION=yes
+ // add the condition !std::getenv("LO_TESTNAME") below (with &&)
if (GetWeight() < ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize)
{
mxGroup->meCalcState = sc::GroupCalcDisabled;
@@ -4341,7 +4341,7 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false;
}
- if (!ScCalcConfig::isOpenCLEnabled() && bThreadingRequested)
+ if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
{
// iterate over code in the formula ...
// ensure all input is pre-calculated -
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 0a586073c7c6..a24f41949022 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -25,6 +25,7 @@
#include <tools/mempool.hxx>
#include <osl/diagnose.h>
#include <sfx2/docfile.hxx>
+#include <officecfg/Office/Calc.hxx>
#include <token.hxx>
#include <tokenarray.hxx>
@@ -1346,11 +1347,11 @@ void ScTokenArray::CheckToken( const FormulaToken& r )
// It's already disabled. No more checking needed.
return;
- static const bool bThreadingRequested = std::getenv("CPU_THREADED_CALCULATION");
+ static const bool bThreadingProhibited = std::getenv("SC_NO_THREADED_CALCULATION");
OpCode eOp = r.GetOpCode();
- if (!ScCalcConfig::isOpenCLEnabled() && bThreadingRequested)
+ if (!bThreadingProhibited && !ScCalcConfig::isOpenCLEnabled() && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get())
{
if (aThreadedCalcBlackList.count(eOp))
{
commit 0565d230efe0909addf3b9a57edff5d1cb114ae4
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 10:55:13 2017 +0300
Need more ScInterpreterContexts
Change-Id: I1dd679156661bb5cb025ca6cb46d19783524d5a4
diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx
index 0f513c231327..00f399fab47c 100644
--- a/sc/source/core/tool/interpr6.cxx
+++ b/sc/source/core/tool/interpr6.cxx
@@ -846,7 +846,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero )
nFuncFmtIndex = aAction.getNumberFormat();
}
- nFuncFmtType = pDok->GetFormatTable()->GetType( nFuncFmtIndex );
+ nFuncFmtType = mrContext.GetFormatTable()->GetType( nFuncFmtIndex );
}
else
{
commit f80c5f7704decb1e484e5984d5c8d82031b66d5e
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 08:48:05 2017 +0300
-Werror,-Wunused-parameter
Change-Id: If10c6a58f5b6f196f3644f6c592dd6d1dc0d860c
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 62f4baa471c3..0df71931c355 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6794,13 +6794,13 @@ ScRecursionHelper& ScDocument::GetRecursionHelper()
}
}
-void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& rNonThreadedData)
+void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& /*rNonThreadedData*/)
{
// What about the recursion helper?
// Copy the lookup cache?
}
-void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& rNonThreadedData)
+void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& /*rNonThreadedData*/)
{
// What about recursion helper and lookup cache?
}
commit 005051e405687012e31bdb3db1a0cc26d29f70cb
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 08:47:02 2017 +0300
-Werror,-Wsign-compare
Change-Id: Ide03e0ae1fe97e1a09a767908a981a1e803a3474
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index f15107bc3fe7..62f4baa471c3 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6747,7 +6747,7 @@ ScMutationGuard::ScMutationGuard(ScDocument* pDocument, ScMutationGuardFlags nFl
mpDocument(pDocument),
mnFlags(nFlags)
{
- for (auto b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
+ for (unsigned b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
{
if (static_cast<std::size_t>(mnFlags) & (1 << b))
{
@@ -6759,7 +6759,7 @@ ScMutationGuard::ScMutationGuard(ScDocument* pDocument, ScMutationGuardFlags nFl
ScMutationGuard::~ScMutationGuard()
{
#ifndef NDEBUG
- for (auto b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
+ for (unsigned b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
{
if (static_cast<std::size_t>(mnFlags) & (1 << b))
{
commit ae4067e9054f2aba8a8c65a5ae78bf551c0cdd10
Author: Tor Lillqvist <tml at collabora.com>
Date: Wed Oct 4 00:12:31 2017 +0300
Introduce ScInterpreterContext
Possibly later things that need to be thread-local can be handled through
the ScInterpreterContext.
Why handle some thread-local things through the
ScDocument::maNonThreaded and ScDocument::maThreadSpecific mechanism,
and others through this ScInterpreterContext? Good question.
Share SvNumberFormatter across worker threads
and use mutex to protect SvNumberFormatter::IsNumberFormat()
Change-Id: I372e5fbd9a19785f55f0faf4a4bedc5fc1ef3e03
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 67bc6c348c5e..44bee716bf18 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -106,6 +106,7 @@ class ScDocumentImport;
class ScHint;
enum class ScMF;
struct ScFilterEntries;
+struct ScInterpreterContext;
struct ScNeededSizeOptions
{
@@ -447,7 +448,7 @@ public:
const ScPatternAttr* GetPattern( SCROW nRow ) const;
const ScPatternAttr* GetMostUsedPattern( SCROW nStartRow, SCROW nEndRow ) const;
- sal_uInt32 GetNumberFormat( SCROW nRow ) const;
+ sal_uInt32 GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const;
sal_uInt32 GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const;
void MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, bool bDeep ) const;
@@ -582,7 +583,7 @@ public:
void SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen );
void SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen );
- void CalculateInThread( SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
+ void CalculateInThread( const ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal );
void HandleStuffAfterParallelCalculation( SCROW nRow, size_t nLen );
void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat );
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index 544e64ebc9c1..904f471c3c4f 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -45,6 +45,7 @@ struct ScQueryParam;
struct ScDBQueryParamInternal;
struct ScDBQueryParamMatrix;
class ScFormulaCell;
+struct ScInterpreterContext;
class ScValueIterator // walk through all values in an area
{
@@ -84,7 +85,7 @@ public:
ScDocument* pDocument, const ScRange& rRange, SubtotalFlags nSubTotalFlags = SubtotalFlags::NONE,
bool bTextAsZero = false );
- void GetCurNumFmtInfo( short& nType, sal_uLong& nIndex );
+ void GetCurNumFmtInfo( const ScInterpreterContext& rContext, short& nType, sal_uLong& nIndex );
/// Does NOT reset rValue if no value found!
bool GetFirst( double& rValue, FormulaError& rErr );
@@ -125,7 +126,7 @@ private:
{
typedef std::pair<sc::CellStoreType::const_iterator,size_t> PositionType;
public:
- DataAccessInternal(ScDBQueryParamInternal* pParam, ScDocument* pDoc);
+ DataAccessInternal(ScDBQueryParamInternal* pParam, ScDocument* pDoc, const ScInterpreterContext& rContext);
virtual ~DataAccessInternal() override;
virtual bool getCurrent(Value& rValue) override;
virtual bool getFirst(Value& rValue) override;
@@ -139,6 +140,7 @@ private:
PositionType maCurPos;
ScDBQueryParamInternal* mpParam;
ScDocument* mpDoc;
+ const ScInterpreterContext& mrContext;
const ScAttrArray* pAttrArray;
sal_uLong nNumFormat; // for CalcAsShown
sal_uLong nNumFmtIndex;
@@ -171,7 +173,7 @@ private:
::std::unique_ptr<DataAccess> mpData;
public:
- ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam);
+ ScDBQueryDataIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, ScDBQueryParamBase* pParam);
/// Does NOT reset rValue if no value found!
bool GetFirst(Value& rValue);
/// Does NOT reset rValue if no value found!
@@ -266,6 +268,7 @@ class ScQueryCellIterator // walk through all non-empty cells in an ar
std::unique_ptr<ScQueryParam> mpParam;
ScDocument* pDoc;
+ const ScInterpreterContext& mrContext;
SCTAB nTab;
SCCOL nCol;
SCROW nRow;
@@ -292,7 +295,7 @@ class ScQueryCellIterator // walk through all non-empty cells in an ar
bool BinarySearch();
public:
- ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
+ ScQueryCellIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, SCTAB nTable,
const ScQueryParam& aParam, bool bMod);
// when !bMod, the QueryParam has to be filled
// (bIsString)
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index eef7c4c8df07..f37e8e7d856e 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -26,6 +26,7 @@
#include <com/sun/star/uno/Reference.hxx>
#include <vcl/vclptr.hxx>
#include "scdllapi.h"
+#include "interpretercontext.hxx"
#include "rangelst.hxx"
#include "rangenam.hxx"
#include "tabopparams.hxx"
@@ -559,6 +560,8 @@ public:
SC_DLLPUBLIC void InitDrawLayer( SfxObjectShell* pDocShell = nullptr );
+ SC_DLLPUBLIC ScInterpreterContext GetNonThreadedContext() const;
+
SC_DLLPUBLIC sfx2::LinkManager* GetLinkManager();
SC_DLLPUBLIC const sfx2::LinkManager* GetLinkManager() const;
@@ -1111,10 +1114,10 @@ public:
SC_DLLPUBLIC void GetNumberFormat( SCCOL nCol, SCROW nRow, SCTAB nTab,
sal_uInt32& rFormat ) const;
sal_uInt32 GetNumberFormat( const ScRange& rRange ) const;
- SC_DLLPUBLIC sal_uInt32 GetNumberFormat( const ScAddress& ) const;
+ SC_DLLPUBLIC sal_uInt32 GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& ) const;
void SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat );
- void GetNumberFormatInfo( short& nType, sal_uLong& nIndex, const ScAddress& rPos ) const;
+ void GetNumberFormatInfo( const ScInterpreterContext& rContext, short& nType, sal_uLong& nIndex, const ScAddress& rPos ) const;
SC_DLLPUBLIC const ScFormulaCell* GetFormulaCell( const ScAddress& rPos ) const;
SC_DLLPUBLIC ScFormulaCell* GetFormulaCell( const ScAddress& rPos );
SC_DLLPUBLIC void GetFormula( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rFormula ) const;
@@ -2049,7 +2052,7 @@ public:
void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen );
void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const formula::FormulaConstTokenRef* pResults, size_t nLen );
- ScDocumentThreadSpecific CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
+ ScDocumentThreadSpecific CalculateInColumnInThread( const ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
void HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen );
/**
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 40fe21598e28..0185e2629010 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -30,7 +30,7 @@
#include <svl/listener.hxx>
#include "types.hxx"
-
+#include "interpretercontext.hxx"
#include "formularesult.hxx"
namespace sc {
@@ -150,7 +150,7 @@ public:
SCITP_FROM_ITERATION,
SCITP_CLOSE_ITERATION_CIRCLE
};
- void InterpretTail( ScInterpretTailParameter );
+ void InterpretTail( const ScInterpreterContext&, ScInterpretTailParameter );
void HandleStuffAfterParallelCalculation();
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
new file mode 100644
index 000000000000..cbf05349ca5f
--- /dev/null
+++ b/sc/inc/interpretercontext.hxx
@@ -0,0 +1,39 @@
+/* -*- 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/.
+ */
+
+#ifndef INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX
+#define INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX
+
+class ScDocument;
+class SvNumberFormatter;
+
+struct ScInterpreterContext
+{
+ const ScDocument& mrDoc;
+ SvNumberFormatter* mpFormatter;
+
+ ScInterpreterContext(const ScDocument& rDoc, SvNumberFormatter* pFormatter) :
+ mrDoc(rDoc),
+ mpFormatter(pFormatter)
+ {
+ }
+
+ ~ScInterpreterContext()
+ {
+ }
+
+ SvNumberFormatter* GetFormatTable() const
+ {
+ return mpFormatter;
+ }
+};
+
+#endif // INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 9b04a4d019a4..1f77ae4d2e39 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -116,6 +116,7 @@ class ScRangeName;
class ScDBData;
class ScDocumentImport;
class ScHint;
+struct ScInterpreterContext;
class ScColumnsRange final
{
@@ -672,7 +673,7 @@ public:
const ScPatternAttr* GetPattern( SCCOL nCol, SCROW nRow ) const;
const ScPatternAttr* GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const;
- sal_uInt32 GetNumberFormat( const ScAddress& rPos ) const;
+ sal_uInt32 GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const;
sal_uInt32 GetNumberFormat( SCCOL nCol, SCROW nRow ) const;
sal_uInt32 GetNumberFormat( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const;
@@ -997,7 +998,7 @@ public:
void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen );
void SetFormulaResults( SCCOL nCol, SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen );
- void CalculateInColumnInThread( SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
+ void CalculateInColumnInThread( const ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal);
void HandleStuffAfterParallelCalculation( SCCOL nCol, SCROW nRow, size_t nLen);
/**
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index ea93b02156f1..5d021d41aec4 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -418,9 +418,9 @@ sal_uInt32 ScColumn::GetNumberFormat( SCROW nStartRow, SCROW nEndRow ) const
return nFormat;
}
-sal_uInt32 ScColumn::GetNumberFormat( SCROW nRow ) const
+sal_uInt32 ScColumn::GetNumberFormat( const ScInterpreterContext& rContext, SCROW nRow ) const
{
- return pAttrArray->GetPattern( nRow )->GetNumberFormat( pDocument->GetFormatTable() );
+ return pAttrArray->GetPattern( nRow )->GetNumberFormat( rContext.GetFormatTable() );
}
SCROW ScColumn::ApplySelectionCache( SfxItemPoolCache* pCache, const ScMarkData& rMark, ScEditDataArray* pDataArray, bool* const pIsChanged )
@@ -1151,7 +1151,7 @@ void ScColumn::CopyStaticToDocument(
// Dont' forget to copy the number formats over. Charts may reference them.
for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
{
- sal_uInt32 nNumFmt = GetNumberFormat(nRow);
+ sal_uInt32 nNumFmt = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
SvNumberFormatterMergeMap::const_iterator itNum = rMap.find(nNumFmt);
if (itNum != rMap.end())
nNumFmt = itNum->second;
@@ -2890,7 +2890,7 @@ public:
void operator() (size_t nRow, ScFormulaCell* pCell)
{
- sal_uInt32 nFormat = mrCol.GetNumberFormat(nRow);
+ sal_uInt32 nFormat = mrCol.GetNumberFormat(mrCol.GetDoc().GetNonThreadedContext(), nRow);
if( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
// Non-default number format is set.
pCell->SetNeedNumberFormat(false);
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index aaa897889603..daeda62bd881 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2877,8 +2877,10 @@ void ScColumn::SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRe
}
}
-void ScColumn::CalculateInThread( SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
+void ScColumn::CalculateInThread( const ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
{
+ assert(pDocument->mbThreadedGroupCalcInProgress);
+
sc::CellStoreType::position_type aPos = maCells.position(nRow);
sc::CellStoreType::iterator it = aPos.first;
if (it->type != sc::element_type_formula)
@@ -2901,8 +2903,7 @@ void ScColumn::CalculateInThread( SCROW nRow, size_t nLen, unsigned nThisThread,
ScFormulaCell& rCell = **itCell;
// Here we don't call IncInterpretLevel() and DecInterpretLevel() as this call site is
// always in a threaded calculation.
- assert(pDocument->mbThreadedGroupCalcInProgress);
- rCell.InterpretTail(ScFormulaCell::SCITP_NORMAL);
+ rCell.InterpretTail(rContext, ScFormulaCell::SCITP_NORMAL);
}
}
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 646210a8e679..9a5a57205436 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1700,7 +1700,7 @@ bool ScColumn::ParseString(
if (!aParam.mpNumFormatter)
aParam.mpNumFormatter = pDocument->GetFormatTable();
- nIndex = nOldIndex = GetNumberFormat( nRow );
+ nIndex = nOldIndex = GetNumberFormat( pDocument->GetNonThreadedContext(), nRow );
if ( rString.getLength() > 1
&& aParam.mpNumFormatter->GetType(nIndex) != css::util::NumberFormat::TEXT )
cFirstChar = rString[0];
@@ -1922,7 +1922,7 @@ void ScColumn::SetFormula( SCROW nRow, const ScTokenArray& rArray, formula::Form
sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, rArray, eGram);
- sal_uInt32 nCellFormat = GetNumberFormat(nRow);
+ sal_uInt32 nCellFormat = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
pCell->SetNeedNumberFormat(true);
it = maCells.set(it, nRow, pCell);
@@ -1939,7 +1939,7 @@ void ScColumn::SetFormula( SCROW nRow, const OUString& rFormula, formula::Formul
sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
ScFormulaCell* pCell = new ScFormulaCell(pDocument, aPos, rFormula, eGram);
- sal_uInt32 nCellFormat = GetNumberFormat(nRow);
+ sal_uInt32 nCellFormat = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
pCell->SetNeedNumberFormat(true);
it = maCells.set(it, nRow, pCell);
@@ -1954,7 +1954,7 @@ ScFormulaCell* ScColumn::SetFormulaCell(
SCROW nRow, ScFormulaCell* pCell, sc::StartListeningType eListenType )
{
sc::CellStoreType::iterator it = GetPositionToInsert(nRow);
- sal_uInt32 nCellFormat = GetNumberFormat(nRow);
+ sal_uInt32 nCellFormat = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
pCell->SetNeedNumberFormat(true);
it = maCells.set(it, nRow, pCell);
@@ -1971,7 +1971,7 @@ void ScColumn::SetFormulaCell(
sc::StartListeningType eListenType )
{
rBlockPos.miCellPos = GetPositionToInsert(rBlockPos.miCellPos, nRow);
- sal_uInt32 nCellFormat = GetNumberFormat(nRow);
+ sal_uInt32 nCellFormat = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
if( (nCellFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
pCell->SetNeedNumberFormat(true);
rBlockPos.miCellPos = maCells.set(rBlockPos.miCellPos, nRow, pCell);
@@ -2002,7 +2002,7 @@ bool ScColumn::SetFormulaCells( SCROW nRow, std::vector<ScFormulaCell*>& rCells
for (size_t i = 0, n = rCells.size(); i < n; ++i)
{
SCROW nThisRow = nRow + i;
- sal_uInt32 nFmt = GetNumberFormat(nThisRow);
+ sal_uInt32 nFmt = GetNumberFormat(pDocument->GetNonThreadedContext(), nThisRow);
if ((nFmt % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
rCells[i]->SetNeedNumberFormat(true);
}
@@ -2055,7 +2055,7 @@ class FilterEntriesHandler
{
SvNumberFormatter* pFormatter = mrColumn.GetDoc().GetFormatTable();
OUString aStr;
- sal_uLong nFormat = mrColumn.GetNumberFormat(nRow);
+ sal_uLong nFormat = mrColumn.GetNumberFormat(mrColumn.GetDoc().GetNonThreadedContext(), nRow);
ScCellFormat::GetInputString(rCell, nFormat, aStr, *pFormatter, &mrColumn.GetDoc());
if (rCell.hasString())
@@ -2543,7 +2543,7 @@ void ScColumn::GetString( SCROW nRow, OUString& rString ) const
if (aCell.meType == CELLTYPE_FORMULA)
aCell.mpFormula->MaybeInterpret();
- sal_uLong nFormat = GetNumberFormat(nRow);
+ sal_uLong nFormat = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
Color* pColor = nullptr;
ScCellFormat::GetString(aCell, nFormat, rString, &pColor, *(pDocument->GetFormatTable()), pDocument);
}
@@ -2564,7 +2564,7 @@ double* ScColumn::GetValueCell( SCROW nRow )
void ScColumn::GetInputString( SCROW nRow, OUString& rString ) const
{
ScRefCellValue aCell = GetCellValue(nRow);
- sal_uLong nFormat = GetNumberFormat(nRow);
+ sal_uLong nFormat = GetNumberFormat(pDocument->GetNonThreadedContext(), nRow);
ScCellFormat::GetInputString(aCell, nFormat, rString, *(pDocument->GetFormatTable()), pDocument);
}
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 358774153027..fa7f9dfb8c05 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -262,14 +262,14 @@ bool ScValueIterator::GetThis(double& rValue, FormulaError& rErr)
}
}
-void ScValueIterator::GetCurNumFmtInfo( short& nType, sal_uLong& nIndex )
+void ScValueIterator::GetCurNumFmtInfo( const ScInterpreterContext& rContext, short& nType, sal_uLong& nIndex )
{
if (!bNumValid && mnTab < pDoc->GetTableCount())
{
SCROW nCurRow = GetRow();
const ScColumn* pCol = &(pDoc->maTabs[mnTab])->aCol[mnCol];
- nNumFmtIndex = pCol->GetNumberFormat(nCurRow);
- nNumFmtType = pDoc->GetFormatTable()->GetType( nNumFmtIndex );
+ nNumFmtIndex = pCol->GetNumberFormat(rContext, nCurRow);
+ nNumFmtType = rContext.GetFormatTable()->GetType( nNumFmtIndex );
bNumValid = true;
}
@@ -334,11 +334,12 @@ bool ScDBQueryDataIterator::IsQueryValid(
return rDoc.maTabs[nTab]->ValidQuery(nRow, rParam, pCell);
}
-ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(ScDBQueryParamInternal* pParam, ScDocument* pDoc)
+ScDBQueryDataIterator::DataAccessInternal::DataAccessInternal(ScDBQueryParamInternal* pParam, ScDocument* pDoc, const ScInterpreterContext& rContext)
: DataAccess()
, mpCells(nullptr)
, mpParam(pParam)
, mpDoc(pDoc)
+ , mrContext(rContext)
, pAttrArray(nullptr)
, nNumFormat(0) // Initialized in GetNumberFormat
, nNumFmtIndex(0)
@@ -432,7 +433,7 @@ bool ScDBQueryDataIterator::DataAccessInternal::getCurrent(Value& rValue)
rValue.mfValue = aCell.mpFormula->GetValue();
rValue.mbIsNumber = true;
mpDoc->GetNumberFormatInfo(
- nNumFmtType, nNumFmtIndex, ScAddress(nCol, nRow, nTab));
+ mrContext, nNumFmtType, nNumFmtIndex, ScAddress(nCol, nRow, nTab));
rValue.mnError = aCell.mpFormula->GetErrCode();
return true; // Found it!
}
@@ -744,7 +745,7 @@ ScDBQueryDataIterator::Value::Value() :
::rtl::math::setNan(&mfValue);
}
-ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryParamBase* pParam) :
+ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, ScDBQueryParamBase* pParam) :
mpParam (pParam)
{
switch (mpParam->GetType())
@@ -752,7 +753,7 @@ ScDBQueryDataIterator::ScDBQueryDataIterator(ScDocument* pDocument, ScDBQueryPar
case ScDBQueryParamBase::INTERNAL:
{
ScDBQueryParamInternal* p = static_cast<ScDBQueryParamInternal*>(pParam);
- mpData.reset(new DataAccessInternal(p, pDocument));
+ mpData.reset(new DataAccessInternal(p, pDocument, rContext));
}
break;
case ScDBQueryParamBase::MATRIX:
@@ -1046,10 +1047,11 @@ bool ScCellIterator::next()
return getCurrent();
}
-ScQueryCellIterator::ScQueryCellIterator(ScDocument* pDocument, SCTAB nTable,
+ScQueryCellIterator::ScQueryCellIterator(ScDocument* pDocument, const ScInterpreterContext& rContext, SCTAB nTable,
const ScQueryParam& rParam, bool bMod ) :
mpParam(new ScQueryParam(rParam)),
pDoc( pDocument ),
+ mrContext( rContext ),
nTab( nTable),
nStopOnMismatch( nStopOnMismatchDisabled ),
nTestEqualCondition( nTestEqualConditionDisabled ),
@@ -1681,7 +1683,7 @@ bool ScQueryCellIterator::BinarySearch()
if (aPos.first->type == sc::element_type_string || aPos.first->type == sc::element_type_edittext)
{
aCell = sc::toRefCell(aPos.first, aPos.second);
- sal_uLong nFormat = pCol->GetNumberFormat(nRow);
+ sal_uLong nFormat = pCol->GetNumberFormat(mrContext, nRow);
OUString aCellStr;
ScCellFormat::GetInputString(aCell, nFormat, aCellStr, rFormatter, pDoc);
sal_Int32 nTmp = pCollator->compareString(aCellStr, rEntry.GetQueryItem().maString.getString());
@@ -1715,7 +1717,7 @@ bool ScQueryCellIterator::BinarySearch()
aCell = aCellData.first;
if (aCell.hasString())
{
- sal_uLong nFormat = pCol->GetNumberFormat(aCellData.second);
+ sal_uLong nFormat = pCol->GetNumberFormat(mrContext, aCellData.second);
OUString aStr;
ScCellFormat::GetInputString(aCell, nFormat, aStr, rFormatter, pDoc);
aLastInRangeString = aStr;
@@ -1814,7 +1816,7 @@ bool ScQueryCellIterator::BinarySearch()
else if (bStr && bByString)
{
OUString aCellStr;
- sal_uLong nFormat = pCol->GetNumberFormat(aCellData.second);
+ sal_uLong nFormat = pCol->GetNumberFormat(mrContext, aCellData.second);
ScCellFormat::GetInputString(aCell, nFormat, aCellStr, rFormatter, pDoc);
nRes = pCollator->compareString(aCellStr, rEntry.GetQueryItem().maString.getString());
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 283c082199b2..b15ee591a7e2 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -502,6 +502,7 @@ void ScDocument::InitClipPtrs( ScDocument* pSourceDoc )
SvNumberFormatter* ScDocument::GetFormatTable() const
{
+ assert(!mbThreadedGroupCalcInProgress);
return mxPoolHelper->GetFormTable();
}
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index b29de4004c90..8bf1de3fb191 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -427,7 +427,7 @@ void ScDocument::SetFormulaResults(
pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
}
-ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
+ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( const ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
{
ScTable* pTab = FetchTable(rTopPos.Tab());
if (!pTab)
@@ -436,7 +436,7 @@ ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( const ScAddress&
assert(mbThreadedGroupCalcInProgress);
maThreadSpecific.SetupFromNonThreadedData(maNonThreaded);
- pTab->CalculateInColumnInThread(rTopPos.Col(), rTopPos.Row(), nLen, nThisThread, nThreadsTotal);
+ pTab->CalculateInColumnInThread(rContext, rTopPos.Col(), rTopPos.Row(), nLen, nThisThread, nThreadsTotal);
assert(mbThreadedGroupCalcInProgress);
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 185115ac8ad7..f15107bc3fe7 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3702,13 +3702,13 @@ sal_uInt32 ScDocument::GetNumberFormat( const ScRange& rRange ) const
return nFormat;
}
-sal_uInt32 ScDocument::GetNumberFormat( const ScAddress& rPos ) const
+sal_uInt32 ScDocument::GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const
{
SCTAB nTab = rPos.Tab();
if (!TableExists(nTab))
return 0;
- return maTabs[nTab]->GetNumberFormat( rPos );
+ return maTabs[nTab]->GetNumberFormat( rContext, rPos );
}
void ScDocument::SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberFormat )
@@ -3720,14 +3720,14 @@ void ScDocument::SetNumberFormat( const ScAddress& rPos, sal_uInt32 nNumberForma
maTabs[nTab]->SetNumberFormat(rPos.Col(), rPos.Row(), nNumberFormat);
}
-void ScDocument::GetNumberFormatInfo( short& nType, sal_uLong& nIndex,
+void ScDocument::GetNumberFormatInfo( const ScInterpreterContext& rContext, short& nType, sal_uLong& nIndex,
const ScAddress& rPos ) const
{
SCTAB nTab = rPos.Tab();
if ( nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
{
- nIndex = maTabs[nTab]->GetNumberFormat( rPos );
- nType = GetFormatTable()->GetType( nIndex );
+ nIndex = maTabs[nTab]->GetNumberFormat( rContext, rPos );
+ nType = rContext.GetFormatTable()->GetType( nIndex );
}
else
{
@@ -6769,6 +6769,13 @@ ScMutationGuard::~ScMutationGuard()
#endif
}
+ScInterpreterContext ScDocument::GetNonThreadedContext() const
+{
+ // GetFormatTable() asserts that we are not in a threaded calculation
+ ScInterpreterContext aResult(*this, GetFormatTable());
+ return aResult;
+}
+
thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific;
ScRecursionHelper& ScDocument::GetRecursionHelper()
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 7e4a92b1e146..fed52b93ddec 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1528,10 +1528,10 @@ void ScFormulaCell::Interpret()
bool bGroupInterpreted = InterpretFormulaGroup();
aDC.leaveGroup();
if (!bGroupInterpreted)
- InterpretTail( SCITP_NORMAL);
+ InterpretTail( pDocument->GetNonThreadedContext(), SCITP_NORMAL);
#else
if (!InterpretFormulaGroup())
- InterpretTail( SCITP_NORMAL);
+ InterpretTail( pDocument->GetNonThreadedContext(), SCITP_NORMAL);
#endif
pDocument->DecInterpretLevel();
}
@@ -1595,8 +1595,8 @@ void ScFormulaCell::Interpret()
bResumeIteration = false;
// Close circle once.
pDocument->IncInterpretLevel();
- rRecursionHelper.GetList().back().pCell->InterpretTail(
- SCITP_CLOSE_ITERATION_CIRCLE);
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list