Rebased ref, commits from common ancestor: commit a0e25475cee4cce0dbd082d1c893bd711d7a9962 Author: Tor Lillqvist <t...@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 db28d42ebcf3..43f0825b3f1e 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 babc1820b780689b41097a9dc0346f0c1288bf90 Author: Tor Lillqvist <t...@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 fe007d680b30..db28d42ebcf3 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 6c74f5ad2696446261a7b902c284c95fa6ad1949 Author: Tor Lillqvist <t...@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 002d72dbad88..61b0f5a87702 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -4345,7 +4345,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 9e7bf2c755ee3cb01572d36141d6ea7cc6dc18ab Author: Tor Lillqvist <t...@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 6442b4ccb2b7845918d99eebfaf786a2665fc04c Author: Tor Lillqvist <t...@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 c86d48b6c3cf..04544fe5a64e 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -564,7 +564,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 4cfe1747eb16f62fda4150efe27a7a522e726216 Author: Tor Lillqvist <t...@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 f72a7976662e8851ccff18c05e8d207dfae0ca4b Author: Tor Lillqvist <t...@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 2d6d49bc191a..002d72dbad88 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> @@ -4326,11 +4327,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; @@ -4345,7 +4345,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 d0ebe0ca2e76..fe007d680b30 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 9b01b676860e421d2b7438f33439e80597943d0a Author: Tor Lillqvist <t...@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 cc12cf3a86e04e4bffecd0209db2dfb8530e0d4e Author: Tor Lillqvist <t...@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 93030470bbf89cff4156435b849198fe5973f459 Author: Tor Lillqvist <t...@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 f66c6fab8791d52b97337570510bca415feaa961 Author: Tor Lillqvist <t...@collabora.com> Date: Wed Oct 4 00:12:31 2017 +0300 Introduce ScInterpreterContext When calculating a formula group in multiple threads in parallel, we need to use separate SvNumberFormatters in the threads. Possibly later also other 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. 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 e85b4ba29365..c86d48b6c3cf 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" @@ -563,6 +564,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; @@ -1118,10 +1121,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; @@ -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 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 48a551462c60..11bd7010ce32 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; @@ -2887,7 +2887,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 705b5ed83ae5..f436d4b11bea 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 bc6fd157e34b..2d6d49bc191a 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); + rRecursionHelper.GetList().back().pCell->InterpretTail( pDocument->GetNonThreadedContext(), + SCITP_CLOSE_ITERATION_CIRCLE); pDocument->DecInterpretLevel(); // Start at 1, init things. rRecursionHelper.StartIteration(); @@ -1627,7 +1627,7 @@ void ScFormulaCell::Interpret() { (*aIter).aPreviousResult = pIterCell->aResult; pDocument->IncInterpretLevel(); - pIterCell->InterpretTail( SCITP_FROM_ITERATION); + pIterCell->InterpretTail( pDocument->GetNonThreadedContext(), SCITP_FROM_ITERATION); pDocument->DecInterpretLevel(); } rDone = rDone && !pIterCell->IsDirtyOrInTableOpDirty(); @@ -1699,7 +1699,7 @@ void ScFormulaCell::Interpret() if (pCell->IsDirtyOrInTableOpDirty()) { pDocument->IncInterpretLevel(); - pCell->InterpretTail( SCITP_NORMAL); + pCell->InterpretTail( pDocument->GetNonThreadedContext(), SCITP_NORMAL); pDocument->DecInterpretLevel(); if (!pCell->IsDirtyOrInTableOpDirty() && !pCell->IsIterCell()) pCell->bRunning = (*aIter).bOldRunning; @@ -1748,7 +1748,7 @@ class StackCleaner }; } -void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) +void ScFormulaCell::InterpretTail( const ScInterpreterContext& rContext, ScInterpretTailParameter eTailParam ) { RecursionCounter aRecursionCounter( pDocument->GetRecursionHelper(), this); nSeenInIteration = pDocument->GetRecursionHelper().GetIteration(); @@ -1775,7 +1775,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) if( pCode->GetCodeLen() && pDocument ) { - ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, aPos, *pCode ); + ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, rContext, aPos, *pCode ); StackCleaner aStackCleaner(pInterpreter); FormulaError nOldErrCode = aResult.GetResultError(); if ( nSeenInIteration == 0 ) @@ -1981,7 +1981,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) } if (bSetFormat && (bForceNumberFormat || ((nFormatIndex % SV_COUNTRY_LANGUAGE_OFFSET) == 0))) - nFormatIndex = ScGlobal::GetStandardFormat(*pDocument->GetFormatTable(), + nFormatIndex = ScGlobal::GetStandardFormat(*rContext.GetFormatTable(), nFormatIndex, nFormatType); // Do not replace a General format (which was the reason why @@ -2168,7 +2168,7 @@ void ScFormulaCell::HandleStuffAfterParallelCalculation() if ( !pCode->IsRecalcModeAlways() ) pDocument->RemoveFromFormulaTree( this ); - ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, aPos, *pCode ); + ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, pDocument->GetNonThreadedContext(), aPos, *pCode ); StackCleaner aStackCleaner(pInterpreter); switch (pInterpreter->GetVolatileType()) @@ -4328,6 +4328,9 @@ bool ScFormulaCell::InterpretFormulaGroup() static const bool bThreadingRequested = std::getenv("CPU_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 if (GetWeight() < ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize) { mxGroup->meCalcState = sc::GroupCalcDisabled; @@ -4367,6 +4370,7 @@ bool ScFormulaCell::InterpretFormulaGroup() const unsigned mnThisThread; const unsigned mnThreadsTotal; ScDocument* mpDocument; + SvNumberFormatter* mpFormatter; const ScAddress& mrTopPos; SCROW mnLength; @@ -4375,12 +4379,14 @@ bool ScFormulaCell::InterpretFormulaGroup() unsigned nThisThread, unsigned nThreadsTotal, ScDocument* pDocument, + SvNumberFormatter* pFormatter, const ScAddress& rTopPos, SCROW nLength) : comphelper::ThreadTask(rTag), mnThisThread(nThisThread), mnThreadsTotal(nThreadsTotal), mpDocument(pDocument), + mpFormatter(pFormatter), mrTopPos(rTopPos), mnLength(nLength) { @@ -4388,11 +4394,18 @@ bool ScFormulaCell::InterpretFormulaGroup() virtual void doWork() override { - mpDocument->CalculateInColumnInThread(mrTopPos, mnLength, mnThisThread, mnThreadsTotal).MergeBackIntoNonThreadedData(mpDocument->maNonThreaded); + std::unique_ptr<SvNumberFormatter> pFormatterForThisThread + (new SvNumberFormatter(mpFormatter->GetComponentContext(), + mpFormatter->GetLanguage())); + ScInterpreterContext aContext(*mpDocument, pFormatterForThisThread.get()); + + mpDocument->CalculateInColumnInThread(aContext, mrTopPos, mnLength, mnThisThread, mnThreadsTotal).MergeBackIntoNonThreadedData(mpDocument->maNonThreaded); } }; + SvNumberFormatter* pNonThreadedFormatter = pDocument->GetNonThreadedContext().GetFormatTable(); + comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool()); sal_Int32 nThreadCount = rThreadPool.getWorkerCount(); @@ -4408,7 +4421,7 @@ bool ScFormulaCell::InterpretFormulaGroup() std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag(); for (int i = 0; i < nThreadCount; ++i) { - rThreadPool.pushTask(new Executor(aTag, i, nThreadCount, pDocument, mxGroup->mpTopCell->aPos, mxGroup->mnLength)); + rThreadPool.pushTask(new Executor(aTag, i, nThreadCount, pDocument, pNonThreadedFormatter, mxGroup->mpTopCell->aPos, mxGroup->mnLength)); } SAL_INFO("sc.threaded", "Joining threads"); @@ -4606,14 +4619,14 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup() ScCompiler aComp(pDocument, aPos, aCode, pDocument->GetGrammar()); aComp.CompileTokenArray(); // Create RPN token array. - ScInterpreter aInterpreter(this, pDocument, aPos, aCode); + ScInterpreter aInterpreter(this, pDocument, pDocument->GetNonThreadedContext(), aPos, aCode); aInterpreter.Interpret(); aResult.SetToken(aInterpreter.GetResultToken().get()); } else { // Formula contains no references. - ScInterpreter aInterpreter(this, pDocument, aPos, *pCode); + ScInterpreter aInterpreter(this, pDocument, pDocument->GetNonThreadedContext(), aPos, *pCode); aInterpreter.Interpret(); aResult.SetToken(aInterpreter.GetResultToken().get()); } diff --git a/sc/source/core/data/simpleformulacalc.cxx b/sc/source/core/data/simpleformulacalc.cxx index b1e0f65f9ff7..859114515e5c 100644 --- a/sc/source/core/data/simpleformulacalc.cxx +++ b/sc/source/core/data/simpleformulacalc.cxx @@ -44,7 +44,7 @@ void ScSimpleFormulaCalculator::Calculate() return; mbCalculated = true; - ScInterpreter aInt(nullptr, mpDoc, maAddr, *mpCode.get()); + ScInterpreter aInt(nullptr, mpDoc, mpDoc->GetNonThreadedContext(), maAddr, *mpCode.get()); std::unique_ptr<sfx2::LinkManager> pNewLinkMgr( new sfx2::LinkManager(mpDoc->GetDocumentShell()) ); aInt.SetLinkManager( pNewLinkMgr.get() ); diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 961b2f443568..e43ab0efc7ac 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -2338,12 +2338,12 @@ void ScTable::SetFormulaResults( aCol[nCol].SetFormulaResults(nRow, pResults, nLen); } -void ScTable::CalculateInColumnInThread( SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) +void ScTable::CalculateInColumnInThread( const ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) { if (!ValidCol(nCol)) return; - aCol[nCol].CalculateInThread( nRow, nLen, nThisThread, nThreadsTotal ); + aCol[nCol].CalculateInThread( rContext, nRow, nLen, nThisThread, nThreadsTotal ); } void ScTable::HandleStuffAfterParallelCalculation( SCCOL nCol, SCROW nRow, size_t nLen) diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 60e05b323be9..56be6df03201 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1899,17 +1899,17 @@ const SfxPoolItem* ScTable::GetAttr( SCCOL nCol, SCROW nRow, sal_uInt16 nWhich ) return nullptr; } -sal_uInt32 ScTable::GetNumberFormat( const ScAddress& rPos ) const +sal_uInt32 ScTable::GetNumberFormat( const ScInterpreterContext& rContext, const ScAddress& rPos ) const { return ValidColRow(rPos.Col(),rPos.Row()) ? - aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) : + aCol[rPos.Col()].GetNumberFormat( rContext, rPos.Row() ) : 0; } sal_uInt32 ScTable::GetNumberFormat( SCCOL nCol, SCROW nRow ) const { if (ValidColRow(nCol,nRow)) - return aCol[nCol].GetNumberFormat( nRow ); + return aCol[nCol].GetNumberFormat( pDocument->GetNonThreadedContext(), nRow ); else return 0; } diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index 2579545c4c91..45927fe4de8f 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -1380,14 +1380,14 @@ void ScTable::FillAutoSimple( return; } bBooleanCell = (pDocument->GetFormatTable()->GetType( - aCol[rCol].GetNumberFormat( nSource)) == css::util::NumberFormat::LOGICAL); + aCol[rCol].GetNumberFormat( pDocument->GetNonThreadedContext(), nSource)) == css::util::NumberFormat::LOGICAL); } else // rInner&:=nCol, rOuter&:=nRow { aSrcCell = aCol[nSource].GetCellValue(rRow); bBooleanCell = (pDocument->GetFormatTable()->GetType( - aCol[nSource].GetNumberFormat( rRow)) == css::util::NumberFormat::LOGICAL); + aCol[nSource].GetNumberFormat( pDocument->GetNonThreadedContext(), rRow)) == css::util::NumberFormat::LOGICAL); } bGetCell = false; diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 9917e943fe59..9c754c2e9386 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -29,6 +29,7 @@ #include <sfx2/linkmgr.hxx> #include <scdll.hxx> #include <scdllapi.h> +#include <interpretercontext.hxx> #include <types.hxx> #include <externalrefmgr.hxx> #include <calcconfig.hxx> @@ -198,6 +199,7 @@ private: formula::FormulaTokenIterator aCode; ScAddress aPos; ScTokenArray& rArr; + const ScInterpreterContext& mrContext; ScDocument* pDok; sfx2::LinkManager* mpLinkManager; svl::SharedStringPool& mrStrPool; @@ -988,7 +990,7 @@ private: double GetTInv( double fAlpha, double fSize, int nType ); public: - ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, + ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, const ScInterpreterContext& rContext, const ScAddress&, ScTokenArray& ); ~ScInterpreter(); diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index 0730bae98a4d..f637ab5753bc 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -251,7 +251,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres ScCompiler aComp(&rDoc, aTmpPos, aCode2); aComp.CompileTokenArray(); - ScInterpreter aInterpreter(pDest, &rDoc, aTmpPos, aCode2); + ScInterpreter aInterpreter(pDest, &rDoc, rDoc.GetNonThreadedContext(), aTmpPos, aCode2); aInterpreter.Interpret(); aResults.push_back(aInterpreter.GetResultToken()); } // for loop end (xGroup->mnLength) diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 157c8a2dcedd..9fac42814541 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -3550,7 +3550,7 @@ void ScInterpreter::ScMin( bool bTextAsZero ) { if (nMin > nVal) nMin = nVal; - aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex ); + aValIter.GetCurNumFmtInfo( mrContext, nFuncFmtType, nFuncFmtIndex ); while ((nErr == FormulaError::NONE) && aValIter.GetNext(nVal, nErr)) { if (nMin > nVal) @@ -3707,7 +3707,7 @@ void ScInterpreter::ScMax( bool bTextAsZero ) { if (nMax < nVal) nMax = nVal; - aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex ); + aValIter.GetCurNumFmtInfo( mrContext, nFuncFmtType, nFuncFmtIndex ); while ((nErr == FormulaError::NONE) && aValIter.GetNext(nVal, nErr)) { if (nMax < nVal) @@ -4864,7 +4864,7 @@ void ScInterpreter::ScMatch() rParam.bByRow = false; rParam.nRow2 = nRow1; rEntry.nField = nCol1; - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false); + ScQueryCellIterator aCellIter(pDok, mrContext, nTab1, rParam, false); // Advance Entry.nField in Iterator if column changed aCellIter.SetAdvanceQueryParamEntryField( true ); if (fTyp == 0.0) @@ -5343,7 +5343,7 @@ void ScInterpreter::IterateParametersIf( ScIterFuncIf eFunc ) } else { - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false); + ScQueryCellIterator aCellIter(pDok, mrContext, nTab1, rParam, false); // Increment Entry.nField in iterator when switching to next column. aCellIter.SetAdvanceQueryParamEntryField( true ); if ( aCellIter.GetFirst() ) @@ -5605,7 +5605,7 @@ void ScInterpreter::ScCountIf() } else { - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false); + ScQueryCellIterator aCellIter(pDok, mrContext, nTab1, rParam, false); // Keep Entry.nField in iterator on column change aCellIter.SetAdvanceQueryParamEntryField( true ); if ( aCellIter.GetFirst() ) @@ -5898,7 +5898,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf } else { - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, false); + ScQueryCellIterator aCellIter(pDok, mrContext, nTab1, rParam, false); // Increment Entry.nField in iterator when switching to next column. aCellIter.SetAdvanceQueryParamEntryField( true ); if ( aCellIter.GetFirst() ) @@ -6724,7 +6724,7 @@ void ScInterpreter::ScLookup() if (rItem.meType == ScQueryEntry::ByString) aParam.eSearchType = DetectSearchType(rItem.maString.getString(), pDok); - ScQueryCellIterator aCellIter(pDok, nTab1, aParam, false); + ScQueryCellIterator aCellIter(pDok, mrContext, nTab1, aParam, false); SCCOL nC; SCROW nR; // Advance Entry.nField in iterator upon switching columns if @@ -7071,7 +7071,7 @@ void ScInterpreter::CalculateLookup(bool bHLookup) rEntry.eOp = SC_LESS_EQUAL; if ( bHLookup ) { - ScQueryCellIterator aCellIter(pDok, nTab1, aParam, false); + ScQueryCellIterator aCellIter(pDok, mrContext, nTab1, aParam, false); // advance Entry.nField in Iterator upon switching columns aCellIter.SetAdvanceQueryParamEntryField( true ); if ( bSorted ) @@ -7447,7 +7447,7 @@ void ScInterpreter::DBIterator( ScIterFunc eFunc ) SetError(FormulaError::NoValue); return; } - ScDBQueryDataIterator aValIter(pDok, pQueryParam.release()); + ScDBQueryDataIterator aValIter(pDok, mrContext, pQueryParam.release()); ScDBQueryDataIterator::Value aValue; if ( aValIter.GetFirst(aValue) && aValue.mnError == FormulaError::NONE ) { @@ -7535,7 +7535,7 @@ void ScInterpreter::ScDBCount() // so the source range has to be restricted, like before the introduction // of ScDBQueryParamBase. p->nCol1 = p->nCol2 = p->mnField; - ScQueryCellIterator aCellIter( pDok, nTab, *p, true); + ScQueryCellIterator aCellIter( pDok, mrContext, nTab, *p, true); if ( aCellIter.GetFirst() ) { do @@ -7551,7 +7551,7 @@ void ScInterpreter::ScDBCount() SetError(FormulaError::NoValue); return; } - ScDBQueryDataIterator aValIter( pDok, pQueryParam.release()); + ScDBQueryDataIterator aValIter( pDok, mrContext, pQueryParam.release()); ScDBQueryDataIterator::Value aValue; if ( aValIter.GetFirst(aValue) && aValue.mnError == FormulaError::NONE ) { @@ -7582,7 +7582,7 @@ void ScInterpreter::ScDBCount2() } sal_uLong nCount = 0; pQueryParam->mbSkipString = false; - ScDBQueryDataIterator aValIter( pDok, pQueryParam.release()); + ScDBQueryDataIterator aValIter( pDok, mrContext, pQueryParam.release()); ScDBQueryDataIterator::Value aValue; if ( aValIter.GetFirst(aValue) && aValue.mnError == FormulaError::NONE ) { @@ -7636,7 +7636,7 @@ void ScInterpreter::GetDBStVarParams( double& rVal, double& rValCount ) SetError(FormulaError::NoValue); return; } - ScDBQueryDataIterator aValIter(pDok, pQueryParam.release()); + ScDBQueryDataIterator aValIter(pDok, mrContext, pQueryParam.release()); ScDBQueryDataIterator::Value aValue; if (aValIter.GetFirst(aValue) && aValue.mnError == FormulaError::NONE) { @@ -9297,11 +9297,11 @@ utl::SearchParam::SearchType ScInterpreter::DetectSearchType( const OUString& rS return utl::SearchParam::SearchType::Normal; } -static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument * pDoc, +static bool lcl_LookupQuery( ScAddress & o_rResultPos, ScDocument * pDoc, const ScInterpreterContext& rContext, const ScQueryParam & rParam, const ScQueryEntry & rEntry ) { bool bFound = false; - ScQueryCellIterator aCellIter( pDoc, rParam.nTab, rParam, false); + ScQueryCellIterator aCellIter( pDoc, rContext, rParam.nTab, rParam, false); if (rEntry.eOp != SC_EQUAL) { // range lookup <= or >= @@ -9338,7 +9338,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos, * direct lookups here. We could even further attribute volatility per * parameter so it would affect only the lookup range parameter. */ if (!bColumnsMatch || GetVolatileType() != NOT_VOLATILE) - bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry); + bFound = lcl_LookupQuery( o_rResultPos, pDok, mrContext, rParam, rEntry); else { ScRange aLookupRange( rParam.nCol1, rParam.nRow1, rParam.nTab, @@ -9351,7 +9351,7 @@ bool ScInterpreter::LookupQueryWithCache( ScAddress & o_rResultPos, { case ScLookupCache::NOT_CACHED : case ScLookupCache::CRITERIA_DIFFERENT : - bFound = lcl_LookupQuery( o_rResultPos, pDok, rParam, rEntry); + bFound = lcl_LookupQuery( o_rResultPos, pDok, mrContext, rParam, rEntry); if (eCacheResult == ScLookupCache::NOT_CACHED) rCache.insert( o_rResultPos, aCriteria, aPos, bFound); break; diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 50350fac8e85..e62610b1d50b 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -203,7 +203,7 @@ double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& if (pFCell->IsValue()) { fValue = pFCell->GetValue(); - pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex, + pDok->GetNumberFormatInfo( mrContext, nCurFmtType, nCurFmtIndex, rPos ); } else @@ -221,7 +221,7 @@ double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& case CELLTYPE_VALUE: { fValue = rCell.mfValue; - nCurFmtIndex = pDok->GetNumberFormat( rPos ); + nCurFmtIndex = pDok->GetNumberFormat( mrContext, rPos ); nCurFmtType = pFormatter->GetType( nCurFmtIndex ); if ( bCalcAsShown && fValue != 0.0 ) fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex ); @@ -697,7 +697,7 @@ void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString, { bool bInherited = (aCell.meType == CELLTYPE_FORMULA); if (pRetTypeExpr && pRetIndexExpr) - pDok->GetNumberFormatInfo(*pRetTypeExpr, *pRetIndexExpr, rAddress); + pDok->GetNumberFormatInfo(mrContext, *pRetTypeExpr, *pRetIndexExpr, rAddress); PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString)); return; } @@ -2503,7 +2503,7 @@ void ScInterpreter::ScDBGet() } pQueryParam->mbSkipString = false; - ScDBQueryDataIterator aValIter(pDok, pQueryParam.release()); + ScDBQueryDataIterator aValIter(pDok, mrContext, pQueryParam.release()); ScDBQueryDataIterator::Value aValue; if (!aValIter.GetFirst(aValue) || aValue.mnError != FormulaError::NONE) { @@ -3782,18 +3782,19 @@ void ScInterpreter::ScTTT() PushError(FormulaError::NoValue); } -ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, +ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, const ScInterpreterContext& rContext, const ScAddress& rPos, ScTokenArray& r ) : aCode(r) , aPos(rPos) , rArr(r) + , mrContext(rContext) , pDok(pDoc) , mpLinkManager(pDok->GetLinkManager()) , mrStrPool(pDoc->GetSharedStringPool()) , pJumpMatrix(nullptr) , pTokenMatrixMap(nullptr) , pMyFormulaCell(pCell) - , pFormatter(pDoc->GetFormatTable()) + , pFormatter(rContext.GetFormatTable()) , pCur(nullptr) , nGlobalError(FormulaError::NONE) , sp(0) diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index 0fe8cced4c6f..909965676139 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -3224,7 +3224,7 @@ void ScInterpreter::ScMatRef() else { // Determine nFuncFmtType type before PushDouble(). - pDok->GetNumberFormatInfo(nCurFmtType, nCurFmtIndex, aAdr); + pDok->GetNumberFormatInfo(mrContext, nCurFmtType, nCurFmtIndex, aAdr); nFuncFmtType = nCurFmtType; nFuncFmtIndex = nCurFmtIndex; PushDouble(nMatVal.fVal); // handles DoubleError @@ -3234,7 +3234,7 @@ void ScInterpreter::ScMatRef() else { // Determine nFuncFmtType type before PushDouble(). - pDok->GetNumberFormatInfo(nCurFmtType, nCurFmtIndex, aAdr); + pDok->GetNumberFormatInfo(mrContext, nCurFmtType, nCurFmtIndex, aAdr); nFuncFmtType = nCurFmtType; nFuncFmtIndex = nCurFmtIndex; // If not a result matrix, obtain the cell value. diff --git a/sc/source/core/tool/interpr6.cxx b/sc/source/core/tool/interpr6.cxx index ea19289230a2..0f513c231327 100644 --- a/sc/source/core/tool/interpr6.cxx +++ b/sc/source/core/tool/interpr6.cxx @@ -319,13 +319,14 @@ public: class FuncCount : public sc::ColumnSpanSet::ColumnAction { + const ScInterpreterContext& mrContext; sc::ColumnBlockConstPosition maPos; ScColumn* mpCol; size_t mnCount; sal_uInt32 mnNumFmt; public: - FuncCount() : mpCol(nullptr), mnCount(0), mnNumFmt(0) {} + FuncCount(const ScInterpreterContext& rContext) : mrContext(rContext), mpCol(nullptr), mnCount(0), mnNumFmt(0) {} virtual void startColumn(ScColumn* pCol) override { @@ -341,7 +342,7 @@ public: NumericCellCounter aFunc; maPos.miCellPos = sc::ParseBlock(maPos.miCellPos, mpCol->GetCellStore(), aFunc, nRow1, nRow2); mnCount += aFunc.getCount(); - mnNumFmt = mpCol->GetNumberFormat(nRow2); + mnNumFmt = mpCol->GetNumberFormat(mrContext, nRow2); }; size_t getCount() const { return mnCount; } @@ -350,6 +351,7 @@ public: class FuncSum : public sc::ColumnSpanSet::ColumnAction { + const ScInterpreterContext& mrContext; sc::ColumnBlockConstPosition maPos; ScColumn* mpCol; double mfSum; @@ -357,7 +359,7 @@ class FuncSum : public sc::ColumnSpanSet::ColumnAction sal_uInt32 mnNumFmt; public: - FuncSum() : mpCol(nullptr), mfSum(0.0), mnError(FormulaError::NONE), mnNumFmt(0) {} + FuncSum(const ScInterpreterContext& rContext) : mrContext(rContext), mpCol(nullptr), mfSum(0.0), mnError(FormulaError::NONE), mnNumFmt(0) {} virtual void startColumn(ScColumn* pCol) override { @@ -389,7 +391,7 @@ public: mfSum += aFunc.getRest(); } - mnNumFmt = mpCol->GetNumberFormat(nRow2); + mnNumFmt = mpCol->GetNumberFormat(mrContext, nRow2); }; FormulaError getError() const { return mnError; } @@ -821,7 +823,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero ) if ( eFunc == ifSUM ) { - FuncSum aAction; + FuncSum aAction(mrContext); aSet.executeColumnAction( *pDok, aAction, fMem ); FormulaError nErr = aAction.getError(); if ( nErr != FormulaError::NONE ) @@ -836,7 +838,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero ) } else { - FuncCount aAction; + FuncCount aAction(mrContext); aSet.executeColumnAction(*pDok, aAction); nCount += aAction.getCount(); @@ -853,7 +855,7 @@ void ScInterpreter::IterateParameters( ScIterFunc eFunc, bool bTextAsZero ) if (aValIter.GetFirst(fVal, nErr)) { // placed the loop on the inside for performance reasons: - aValIter.GetCurNumFmtInfo( nFuncFmtType, nFuncFmtIndex ); + aValIter.GetCurNumFmtInfo( mrContext, nFuncFmtType, nFuncFmtIndex ); switch( eFunc ) { case ifAVERAGE: diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx index 999600c58cc3..21f2963f8abb 100644 --- a/sc/source/filter/excel/xepivot.cxx +++ b/sc/source/filter/excel/xepivot.cxx @@ -341,7 +341,7 @@ void XclExpPCField::InitStandardField( const ScRange& rRange ) if( rDoc.HasValueData( aPos.Col(), aPos.Row(), aPos.Tab() ) ) { double fValue = rDoc.GetValue( aPos ); - short nFmtType = rFormatter.GetType( rDoc.GetNumberFormat( aPos ) ); + short nFmtType = rFormatter.GetType( rDoc.GetNumberFormat( rDoc.GetNonThreadedContext(), aPos ) ); if( nFmtType == css::util::NumberFormat::LOGICAL ) InsertOrigBoolItem( fValue != 0, aText ); else if( nFmtType & css::util::NumberFormat::DATETIME ) diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index cf4163c82cff..8cdbde3bb22d 100644 --- a/sc/source/filter/excel/xicontent.cxx +++ b/sc/source/filter/excel/xicontent.cxx @@ -173,7 +173,7 @@ void lclInsertUrl( XclImpRoot& rRoot, const OUString& rUrl, SCCOL nScCol, SCROW case CELLTYPE_STRING: case CELLTYPE_EDIT: { - sal_uLong nNumFmt = rDoc.getDoc().GetNumberFormat(aScPos); + sal_uLong nNumFmt = rDoc.getDoc().GetNumberFormat(rDoc.getDoc().GetNonThreadedContext(), aScPos); SvNumberFormatter* pFormatter = rDoc.getDoc().GetFormatTable(); Color* pColor; OUString aDisplText; diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index beb47fc010dd..c7c380178e74 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -2878,7 +2878,7 @@ public: if (pTok) { // Cache this cell. - mpRefTab->setCell(mpCurCol->GetCol(), nRow, pTok, mpCurCol->GetNumberFormat(nRow)); + mpRefTab->setCell(mpCurCol->GetCol(), nRow, pTok, mpCurCol->GetNumberFormat(mpCurCol->GetDoc().GetNonThreadedContext(), nRow)); mpRefTab->setCachedCell(mpCurCol->GetCol(), nRow); } } commit 3695439ada8f9a85a2ef405d07875e4b73f09c6c Author: Tor Lillqvist <t...@collabora.com> Date: Fri Sep 29 17:43:24 2017 +0300 Disable formula group threading for macros and table ops Those are likely highly problematic to do in parallel. Change-Id: I50cc32eb72f6b7951d247ecd787b2942cd7d9163 diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index d6ee44cf86c0..d0ebe0ca2e76 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1337,16 +1337,28 @@ bool ScTokenArray::AddFormulaToken( void ScTokenArray::CheckToken( const FormulaToken& r ) { + static const std::set<OpCode> aThreadedCalcBlackList({ + ocMacro, + ocTableOp + }); + if (IsFormulaVectorDisabled()) // It's already disabled. No more checking needed. return; static const bool bThreadingRequested = std::getenv("CPU_THREADED_CALCULATION"); + OpCode eOp = r.GetOpCode(); + if (!ScCalcConfig::isOpenCLEnabled() && bThreadingRequested) + { + 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; - - OpCode eOp = r.GetOpCode(); + } if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION) { commit 07c7ab11ead9345998b10d5613648953ad09c9e5 Author: Tor Lillqvist <t...@collabora.com> Date: Fri Sep 29 17:01:03 2017 +0300 Move nInterpreterTableOpLevel back to ScDocument Change-Id: I4de0051d9fa5de9147954c6021d47076145a3e59 diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index d8d0879f6a87..e85b4ba29365 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -276,14 +276,11 @@ const sal_uInt8 SC_DDE_IGNOREMODE = 255; /// For usage in FindDdeLink() // During threaded calculation fields being mutated are kept in this struct struct ScDocumentThreadSpecific { - sal_uInt16 nInterpreterTableOpLevel; // >0 if in interpreter TableOp - ScRecursionHelper* pRecursionHelper; // information for recursive and iterative cell formulas ScLookupCacheMapImpl* pLookupCacheMapImpl; // cache for lookups like VLOOKUP and MATCH ScDocumentThreadSpecific() : - nInterpreterTableOpLevel(0), pRecursionHelper(nullptr), pLookupCacheMapImpl(nullptr) { @@ -456,6 +453,7 @@ private: sal_uLong nXMLImportedFormulaCount; // progress count during XML import sal_uInt16 nInterpretLevel; // >0 if in interpreter sal_uInt16 nMacroInterpretLevel; // >0 if macro in interpreter + sal_uInt16 nInterpreterTableOpLevel; // >0 if in interpreter TableOp ScDocumentThreadSpecific maNonThreaded; @@ -2193,9 +2191,17 @@ public: if ( nMacroInterpretLevel ) nMacroInterpretLevel--; } - bool IsInInterpreterTableOp() const; - void IncInterpreterTableOpLevel(); - void DecInterpreterTableOpLevel(); + bool IsInInterpreterTableOp() const { return nInterpreterTableOpLevel != 0; } + void IncInterpreterTableOpLevel() + { + if ( nInterpreterTableOpLevel < USHRT_MAX ) + nInterpreterTableOpLevel++; + } + void DecInterpreterTableOpLevel() + { + if ( nInterpreterTableOpLevel ) + nInterpreterTableOpLevel--; + } // add a formula to be remembered for TableOp broadcasts void AddTableOpFormulaCell( ScFormulaCell* ); diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 9fab88f4e910..283c082199b2 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -176,6 +176,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : nXMLImportedFormulaCount( 0 ), nInterpretLevel(0), nMacroInterpretLevel(0), + nInterpreterTableOpLevel(0), nSrcVer( SC_CURRENT_VERSION ), nFormulaTrackCount(0), eHardRecalcState(HardRecalcState::OFF), diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 1706342ccd36..185115ac8ad7 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -6771,42 +6771,6 @@ ScMutationGuard::~ScMutationGuard() thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific; -bool ScDocument::IsInInterpreterTableOp() const -{ - if (!mbThreadedGroupCalcInProgress) - return maNonThreaded.nInterpreterTableOpLevel != 0; - else - return maThreadSpecific.nInterpreterTableOpLevel != 0; -} - -void ScDocument::IncInterpreterTableOpLevel() -{ - if (!mbThreadedGroupCalcInProgress) - { - if (maNonThreaded.nInterpreterTableOpLevel < USHRT_MAX) - maNonThreaded.nInterpreterTableOpLevel++; - } - else - { - if (maThreadSpecific.nInterpreterTableOpLevel < USHRT_MAX) - maThreadSpecific.nInterpreterTableOpLevel++; - } -} - -void ScDocument::DecInterpreterTableOpLevel() -{ - if (!mbThreadedGroupCalcInProgress) - { - if (maNonThreaded.nInterpreterTableOpLevel) - maNonThreaded.nInterpreterTableOpLevel--; - } - else - { - if (maThreadSpecific.nInterpreterTableOpLevel) - maThreadSpecific.nInterpreterTableOpLevel--; - } -} - ScRecursionHelper& ScDocument::GetRecursionHelper() { if (!mbThreadedGroupCalcInProgress) @@ -6825,16 +6789,12 @@ ScRecursionHelper& ScDocument::GetRecursionHelper() void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& rNonThreadedData) { - nInterpreterTableOpLevel = rNonThreadedData.nInterpreterTableOpLevel; - // What about the recursion helper? // Copy the lookup cache? } void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& rNonThreadedData) { - assert(nInterpreterTableOpLevel == rNonThreadedData.nInterpreterTableOpLevel); - // What about recursion helper and lookup cache? } commit e40902d30f596d3fd804728240288a92ccc66e5d Author: Tor Lillqvist <t...@collabora.com> Date: Fri Sep 29 16:00:18 2017 +0300 Move nMacroInterpretLevel back to ScDocument Change-Id: I48748434c845af963af160f8bbd75e4ab7ce95bd diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index d253a17c60ef..d8d0879f6a87 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -276,7 +276,6 @@ const sal_uInt8 SC_DDE_IGNOREMODE = 255; /// For usage in FindDdeLink() // During threaded calculation fields being mutated are kept in this struct struct ScDocumentThreadSpecific { - sal_uInt16 nMacroInterpretLevel; // >0 if macro in interpreter sal_uInt16 nInterpreterTableOpLevel; // >0 if in interpreter TableOp ScRecursionHelper* pRecursionHelper; // information for recursive and iterative cell formulas @@ -284,7 +283,6 @@ struct ScDocumentThreadSpecific ScLookupCacheMapImpl* pLookupCacheMapImpl; // cache for lookups like VLOOKUP and MATCH ScDocumentThreadSpecific() : - nMacroInterpretLevel(0), nInterpreterTableOpLevel(0), pRecursionHelper(nullptr), pLookupCacheMapImpl(nullptr) @@ -457,6 +455,7 @@ private: sal_uLong nFormulaCodeInTree; // formula RPN in the formula tree sal_uLong nXMLImportedFormulaCount; // progress count during XML import sal_uInt16 nInterpretLevel; // >0 if in interpreter + sal_uInt16 nMacroInterpretLevel; // >0 if macro in interpreter ScDocumentThreadSpecific maNonThreaded; @@ -2181,9 +2180,19 @@ public: if ( nInterpretLevel ) nInterpretLevel--; } - sal_uInt16 GetMacroInterpretLevel(); - void IncMacroInterpretLevel(); - void DecMacroInterpretLevel(); + sal_uInt16 GetMacroInterpretLevel() { return nMacroInterpretLevel; } + void IncMacroInterpretLevel() + { + assert(!mbThreadedGroupCalcInProgress); + if ( nMacroInterpretLevel < USHRT_MAX ) + nMacroInterpretLevel++; + } + void DecMacroInterpretLevel() + { + assert(!mbThreadedGroupCalcInProgress); + if ( nMacroInterpretLevel ) + nMacroInterpretLevel--; + } bool IsInInterpreterTableOp() const; void IncInterpreterTableOpLevel(); void DecInterpreterTableOpLevel(); diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index c5d0c7e8cea2..9fab88f4e910 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -175,6 +175,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : nFormulaCodeInTree(0), nXMLImportedFormulaCount( 0 ), nInterpretLevel(0), + nMacroInterpretLevel(0), nSrcVer( SC_CURRENT_VERSION ), nFormulaTrackCount(0), eHardRecalcState(HardRecalcState::OFF), diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 2df3f8e10a8b..1706342ccd36 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -6771,30 +6771,6 @@ ScMutationGuard::~ScMutationGuard() thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific; -sal_uInt16 ScDocument::GetMacroInterpretLevel() -{ - if (!mbThreadedGroupCalcInProgress) - return maNonThreaded.nMacroInterpretLevel; - else - return maThreadSpecific.nMacroInterpretLevel; -} - -void ScDocument::IncMacroInterpretLevel() -{ - if (!mbThreadedGroupCalcInProgress) - maNonThreaded.nMacroInterpretLevel++; - else - maThreadSpecific.nMacroInterpretLevel++; -} - -void ScDocument::DecMacroInterpretLevel() -{ - if (!mbThreadedGroupCalcInProgress) - maNonThreaded.nMacroInterpretLevel--; - else - maThreadSpecific.nMacroInterpretLevel--; -} - bool ScDocument::IsInInterpreterTableOp() const { if (!mbThreadedGroupCalcInProgress) @@ -6849,7 +6825,6 @@ ScRecursionHelper& ScDocument::GetRecursionHelper() void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& rNonThreadedData) { - nMacroInterpretLevel = rNonThreadedData.nMacroInterpretLevel; nInterpreterTableOpLevel = rNonThreadedData.nInterpreterTableOpLevel; // What about the recursion helper? @@ -6858,7 +6833,6 @@ void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSp void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& rNonThreadedData) { - assert(nMacroInterpretLevel == rNonThreadedData.nMacroInterpretLevel); assert(nInterpreterTableOpLevel == rNonThreadedData.nInterpreterTableOpLevel); // What about recursion helper and lookup cache? commit 6f78078499a7c9f091fa828bcc8970686880e3cf Author: Tor Lillqvist <t...@collabora.com> Date: Fri Sep 29 14:26:29 2017 +0300 Move nInterpretLevel back to ScDocument Move the calls to increment and decrement it out of InterpretTail(), to those call sites that aren't reached during parallelized calculations. Change-Id: Ie1bd03dd62aea5f6c71c383df21afff29391dade diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index c5ab947feb95..d253a17c60ef 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -276,7 +276,6 @@ const sal_uInt8 SC_DDE_IGNOREMODE = 255; /// For usage in FindDdeLink() // During threaded calculation fields being mutated are kept in this struct struct ScDocumentThreadSpecific { - sal_uInt16 nInterpretLevel; // >0 if in interpreter sal_uInt16 nMacroInterpretLevel; // >0 if macro in interpreter sal_uInt16 nInterpreterTableOpLevel; // >0 if in interpreter TableOp @@ -285,7 +284,6 @@ struct ScDocumentThreadSpecific ScLookupCacheMapImpl* pLookupCacheMapImpl; // cache for lookups like VLOOKUP and MATCH ScDocumentThreadSpecific() : - nInterpretLevel(0), nMacroInterpretLevel(0), nInterpreterTableOpLevel(0), pRecursionHelper(nullptr), @@ -458,6 +456,8 @@ private: sal_uLong nFormulaCodeInTree; // formula RPN in the formula tree sal_uLong nXMLImportedFormulaCount; // progress count during XML import + sal_uInt16 nInterpretLevel; // >0 if in interpreter + ScDocumentThreadSpecific maNonThreaded; // There can be only one ScDocument being calculated in a thread at a time, so we can use a @@ -2167,9 +2167,20 @@ public: void SetForcedFormulas( bool bVal ) { bHasForcedFormulas = bVal; } sal_uLong GetFormulaCodeInTree() const { return nFormulaCodeInTree; } - bool IsInInterpreter() const; - void IncInterpretLevel(); - void DecInterpretLevel(); + bool IsInInterpreter() const { return nInterpretLevel != 0; } + + void IncInterpretLevel() + { + assert(!mbThreadedGroupCalcInProgress); + if ( nInterpretLevel < USHRT_MAX ) + nInterpretLevel++; + } + void DecInterpretLevel() + { + assert(!mbThreadedGroupCalcInProgress); + if ( nInterpretLevel ) + nInterpretLevel--; + } sal_uInt16 GetMacroInterpretLevel(); void IncMacroInterpretLevel(); void DecMacroInterpretLevel(); diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 701305d708f4..705b5ed83ae5 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * @@ -2899,6 +2899,9 @@ void ScColumn::CalculateInThread( SCROW nRow, size_t nLen, unsigned nThisThread, continue; 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); } } diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 43332c2ec873..c5d0c7e8cea2 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -174,6 +174,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : mbThreadedGroupCalcInProgress( false ), nFormulaCodeInTree(0), nXMLImportedFormulaCount( 0 ), + nInterpretLevel(0), nSrcVer( SC_CURRENT_VERSION ), nFormulaTrackCount(0), eHardRecalcState(HardRecalcState::OFF), diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 2f2a0dabe995..2df3f8e10a8b 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -6771,30 +6771,6 @@ ScMutationGuard::~ScMutationGuard() thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific; -bool ScDocument::IsInInterpreter() const -{ - if (!mbThreadedGroupCalcInProgress) - return maNonThreaded.nInterpretLevel != 0; - else - return maThreadSpecific.nInterpretLevel != 0; -} - -void ScDocument::IncInterpretLevel() -{ - if (!mbThreadedGroupCalcInProgress) - maNonThreaded.nInterpretLevel++; - else - maThreadSpecific.nInterpretLevel++; -} - -void ScDocument::DecInterpretLevel() -{ - if (!mbThreadedGroupCalcInProgress) - maNonThreaded.nInterpretLevel--; - else - maThreadSpecific.nInterpretLevel--; -} - sal_uInt16 ScDocument::GetMacroInterpretLevel() { if (!mbThreadedGroupCalcInProgress) @@ -6873,7 +6849,6 @@ ScRecursionHelper& ScDocument::GetRecursionHelper() void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& rNonThreadedData) { - nInterpretLevel = rNonThreadedData.nInterpretLevel; nMacroInterpretLevel = rNonThreadedData.nMacroInterpretLevel; nInterpreterTableOpLevel = rNonThreadedData.nInterpreterTableOpLevel; @@ -6883,7 +6858,6 @@ void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSp void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& rNonThreadedData) { - assert(nInterpretLevel == rNonThreadedData.nInterpretLevel); assert(nMacroInterpretLevel == rNonThreadedData.nMacroInterpretLevel); assert(nInterpreterTableOpLevel == rNonThreadedData.nInterpreterTableOpLevel); diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index e0bc6aab9037..bc6fd157e34b 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1522,6 +1522,7 @@ void ScFormulaCell::Interpret() } else { + pDocument->IncInterpretLevel(); #if DEBUG_CALCULATION aDC.enterGroup(); bool bGroupInterpreted = InterpretFormulaGroup(); @@ -1532,6 +1533,7 @@ void ScFormulaCell::Interpret() if (!InterpretFormulaGroup()) InterpretTail( SCITP_NORMAL); #endif + pDocument->DecInterpretLevel(); } // While leaving a recursion or iteration stack, insert its cells to the @@ -1592,8 +1594,10 @@ void ScFormulaCell::Interpret() { bResumeIteration = false; // Close circle once. + pDocument->IncInterpretLevel(); rRecursionHelper.GetList().back().pCell->InterpretTail( SCITP_CLOSE_ITERATION_CIRCLE); + pDocument->DecInterpretLevel(); // Start at 1, init things. rRecursionHelper.StartIteration(); // Mark all cells being in iteration. @@ -1622,7 +1626,9 @@ void ScFormulaCell::Interpret() pIterCell->GetSeenInIteration()) { (*aIter).aPreviousResult = pIterCell->aResult; + pDocument->IncInterpretLevel(); pIterCell->InterpretTail( SCITP_FROM_ITERATION); + pDocument->DecInterpretLevel(); } rDone = rDone && !pIterCell->IsDirtyOrInTableOpDirty(); } @@ -1692,7 +1698,9 @@ void ScFormulaCell::Interpret() ScFormulaCell* pCell = (*aIter).pCell; if (pCell->IsDirtyOrInTableOpDirty()) { + pDocument->IncInterpretLevel(); pCell->InterpretTail( SCITP_NORMAL); + pDocument->DecInterpretLevel(); if (!pCell->IsDirtyOrInTableOpDirty() && !pCell->IsIterCell()) pCell->bRunning = (*aIter).bOldRunning; } @@ -1728,16 +1736,14 @@ void ScFormulaCell::Interpret() namespace { class StackCleaner { - ScDocument* pDoc; ScInterpreter* pInt; public: - StackCleaner( ScDocument* pD, ScInterpreter* pI ) - : pDoc(pD), pInt(pI) + StackCleaner( ScInterpreter* pI ) + : pInt(pI) {} ~StackCleaner() { delete pInt; - pDoc->DecInterpretLevel(); } }; } @@ -1769,9 +1775,8 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) if( pCode->GetCodeLen() && pDocument ) { - pDocument->IncInterpretLevel(); ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, aPos, *pCode ); - StackCleaner aStackCleaner( pDocument, pInterpreter); + StackCleaner aStackCleaner(pInterpreter); FormulaError nOldErrCode = aResult.GetResultError(); if ( nSeenInIteration == 0 ) { // Only the first time @@ -2163,9 +2168,8 @@ void ScFormulaCell::HandleStuffAfterParallelCalculation() if ( !pCode->IsRecalcModeAlways() ) pDocument->RemoveFromFormulaTree( this ); - pDocument->IncInterpretLevel(); ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, aPos, *pCode ); - StackCleaner aStackCleaner( pDocument, pInterpreter); + StackCleaner aStackCleaner(pInterpreter); switch (pInterpreter->GetVolatileType()) { commit 0a2e85e7f2852cadad0a1fab7e13323d06478b00 Author: Tor Lillqvist <t...@collabora.com> Date: Fri Sep 29 11:04:17 2017 +0300 Re-work how the thread-specific data in ScDocument works We can use normal thread_local data for it as a thread can only be acting on one ScDocument in parallelized formula group calculation anyway. Use separate data instance for the non-threaded data, and when a thread starts, copy that to the thread-specific data. Change-Id: I3e58320a728d1c5639a8a078748b3d4d7a451b25 diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 64929d7e43ac..c5ab947feb95 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * This file is part of the LibreOffice project. * @@ -273,6 +273,7 @@ const sal_uInt8 SC_DDE_ENGLISH = 1; const sal_uInt8 SC_DDE_TEXT = 2; const sal_uInt8 SC_DDE_IGNOREMODE = 255; /// For usage in FindDdeLink() only! +// During threaded calculation fields being mutated are kept in this struct struct ScDocumentThreadSpecific { sal_uInt16 nInterpretLevel; // >0 if in interpreter @@ -295,6 +296,12 @@ struct ScDocumentThreadSpecific ~ScDocumentThreadSpecific() { } + + // To be called in the thread at start + void SetupFromNonThreadedData(const ScDocumentThreadSpecific& rNonThreadedData); + + // To be called in the main thread after the thread has finished + void MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& rNonThreadedData); }; enum class ScMutationGuardFlags @@ -437,6 +444,7 @@ public: /// list of ScInterpreterTableOpParams currently in use std::vector<std::unique_ptr<ScInterpreterTableOpParams>> m_TableOpList; ScInterpreterTableOpParams aLastTableOpParams; // remember last params + private: LanguageType eLanguage; // default language @@ -450,7 +458,12 @@ private: sal_uLong nFormulaCodeInTree; // formula RPN in the formula tree sal_uLong nXMLImportedFormulaCount; // progress count during XML import - static thread_local std::map<const ScDocument *, ScDocumentThreadSpecific> maThreadSpecific; + ScDocumentThreadSpecific maNonThreaded; + + // There can be only one ScDocument being calculated in a thread at a time, so we can use a + // plain thread_local static member. + thread_local static ScDocumentThreadSpecific maThreadSpecific; + sal_uInt16 nSrcVer; // file version (load/save) sal_uInt16 nFormulaTrackCount; HardRecalcState eHardRecalcState; // off, temporary, eternal @@ -2046,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 ); - void CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); + ScDocumentThreadSpecific CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); void HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen ); /** diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 3c3266225c1b..43332c2ec873 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -396,10 +396,8 @@ ScDocument::~ScDocument() ScAddInListener::RemoveDocument( this ); DELETEZ( pChartListenerCollection); // before pBASM because of potential Listener! - if (maThreadSpecific.find(this) != maThreadSpecific.end()) - { - DELETEZ( maThreadSpecific[this].pLookupCacheMapImpl ); // before pBASM because of listeners - } + DELETEZ(maNonThreaded.pLookupCacheMapImpl); // before pBASM because of listeners + DELETEZ(maThreadSpecific.pLookupCacheMapImpl); // destroy BroadcastAreas first to avoid un-needed Single-EndListenings of Formula-Cells delete pBASM; // BroadcastAreaSlotMachine @@ -449,16 +447,14 @@ ScDocument::~ScDocument() mxPoolHelper.clear(); delete pScriptTypeData; - if (maThreadSpecific.find(this) != maThreadSpecific.end()) - delete maThreadSpecific[this].pRecursionHelper; + delete maNonThreaded.pRecursionHelper; + delete maThreadSpecific.pRecursionHelper; delete pPreviewFont; SAL_WARN_IF( pAutoNameCache, "sc.core", "AutoNameCache still set in dtor" ); mpFormulaGroupCxt.reset(); mpCellStringPool.reset(); - - maThreadSpecific.erase(this); } void ScDocument::InitClipPtrs( ScDocument* pSourceDoc ) @@ -1234,50 +1230,103 @@ ScRecursionHelper* ScDocument::CreateRecursionHelperInstance() ScLookupCache & ScDocument::GetLookupCache( const ScRange & rRange ) { ScLookupCache* pCache = nullptr; - if (!maThreadSpecific[this].pLookupCacheMapImpl) - maThreadSpecific[this].pLookupCacheMapImpl = new ScLookupCacheMapImpl; ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits