summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2017-09-29 11:04:17 +0300
committerDennis Francis <dennis.francis@collabora.co.uk>2017-11-21 16:09:42 +0530
commit9732f2b1588e2686f5bdec416972c1686289b635 (patch)
treece05fddf6e3c7d190d34c94bfc71202609f2fef7 /sc
parent973953bff0455c48b4ea43f6f4dd27778661eff3 (diff)
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
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/document.hxx18
-rw-r--r--sc/source/core/data/documen2.cxx105
-rw-r--r--sc/source/core/data/documen8.cxx11
-rw-r--r--sc/source/core/data/document.cxx105
-rw-r--r--sc/source/core/data/formulacell.cxx2
5 files changed, 182 insertions, 59 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 4f798d2ef6ce..fd13f36d22ee 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
@@ -292,6 +293,11 @@ struct 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
@@ -434,6 +440,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
@@ -447,7 +454,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
@@ -2040,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 );
- 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;
- auto it( maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.find( rRange));
- if (it == maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.end())
+ if (!mbThreadedGroupCalcInProgress)
{
- pCache = new ScLookupCache( this, rRange);
- AddLookupCache( *pCache);
+ if (!maNonThreaded.pLookupCacheMapImpl)
+ maNonThreaded.pLookupCacheMapImpl = new ScLookupCacheMapImpl;
+ auto it(maNonThreaded.pLookupCacheMapImpl->aCacheMap.find(rRange));
+ if (it == maNonThreaded.pLookupCacheMapImpl->aCacheMap.end())
+ {
+ pCache = new ScLookupCache(this, rRange);
+ AddLookupCache(*pCache);
+ }
+ else
+ pCache = (*it).second;
}
else
- pCache = (*it).second;
+ {
+ if (!maThreadSpecific.pLookupCacheMapImpl)
+ maThreadSpecific.pLookupCacheMapImpl = new ScLookupCacheMapImpl;
+ auto it(maThreadSpecific.pLookupCacheMapImpl->aCacheMap.find(rRange));
+ if (it == maThreadSpecific.pLookupCacheMapImpl->aCacheMap.end())
+ {
+ pCache = new ScLookupCache(this, rRange);
+ AddLookupCache(*pCache);
+ }
+ else
+ pCache = (*it).second;
+ }
return *pCache;
}
void ScDocument::AddLookupCache( ScLookupCache & rCache )
{
- if (!maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.insert( ::std::pair< const ScRange,
- ScLookupCache*>( rCache.getRange(), &rCache)).second)
+ if (!mbThreadedGroupCalcInProgress)
{
- OSL_FAIL( "ScDocument::AddLookupCache: couldn't add to hash map");
+ if (!maNonThreaded.pLookupCacheMapImpl->aCacheMap.insert( ::std::pair< const ScRange,
+ ScLookupCache*>(rCache.getRange(), &rCache)).second)
+ {
+ OSL_FAIL( "ScDocument::AddLookupCache: couldn't add to hash map");
+ }
+ else
+ StartListeningArea(rCache.getRange(), false, &rCache);
}
else
- StartListeningArea( rCache.getRange(), false, &rCache);
+ {
+ if (!maThreadSpecific.pLookupCacheMapImpl->aCacheMap.insert( ::std::pair< const ScRange,
+ ScLookupCache*>(rCache.getRange(), &rCache)).second)
+ {
+ OSL_FAIL( "ScDocument::AddLookupCache: couldn't add to hash map");
+ }
+ else
+ StartListeningArea(rCache.getRange(), false, &rCache);
+ }
}
void ScDocument::RemoveLookupCache( ScLookupCache & rCache )
{
- auto it( maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.find(
- rCache.getRange()));
- if (it == maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.end())
+ if (!mbThreadedGroupCalcInProgress)
{
- OSL_FAIL( "ScDocument::RemoveLookupCache: range not found in hash map");
+ auto it(maNonThreaded.pLookupCacheMapImpl->aCacheMap.find(rCache.getRange()));
+ if (it == maNonThreaded.pLookupCacheMapImpl->aCacheMap.end())
+ {
+ OSL_FAIL( "ScDocument::RemoveLookupCache: range not found in hash map");
+ }
+ else
+ {
+ ScLookupCache* pCache = (*it).second;
+ maNonThreaded.pLookupCacheMapImpl->aCacheMap.erase(it);
+ EndListeningArea(pCache->getRange(), false, &rCache);
+ }
}
else
{
- ScLookupCache* pCache = (*it).second;
- maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.erase( it);
- EndListeningArea( pCache->getRange(), false, &rCache);
+ auto it( maThreadSpecific.pLookupCacheMapImpl->aCacheMap.find(rCache.getRange()));
+ if (it == maThreadSpecific.pLookupCacheMapImpl->aCacheMap.end())
+ {
+ OSL_FAIL( "ScDocument::RemoveLookupCache: range not found in hash map");
+ }
+ else
+ {
+ ScLookupCache* pCache = (*it).second;
+ maThreadSpecific.pLookupCacheMapImpl->aCacheMap.erase(it);
+ EndListeningArea(pCache->getRange(), false, &rCache);
+ }
}
}
void ScDocument::ClearLookupCaches()
{
- if( maThreadSpecific[this].pLookupCacheMapImpl )
- maThreadSpecific[this].pLookupCacheMapImpl->clear();
+ if (!mbThreadedGroupCalcInProgress)
+ {
+ if (maNonThreaded.pLookupCacheMapImpl )
+ maNonThreaded.pLookupCacheMapImpl->clear();
+ }
+ else
+ {
+ if( maThreadSpecific.pLookupCacheMapImpl )
+ maThreadSpecific.pLookupCacheMapImpl->clear();
+ }
}
bool ScDocument::IsCellInChangeTrack(const ScAddress &cell,Color *pColCellBorder)
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 7e31c2f6ab35..b29de4004c90 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -427,13 +427,20 @@ void ScDocument::SetFormulaResults(
pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen);
}
-void ScDocument::CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
+ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal)
{
ScTable* pTab = FetchTable(rTopPos.Tab());
if (!pTab)
- return;
+ return maNonThreaded;
+
+ assert(mbThreadedGroupCalcInProgress);
+ maThreadSpecific.SetupFromNonThreadedData(maNonThreaded);
pTab->CalculateInColumnInThread(rTopPos.Col(), rTopPos.Row(), nLen, nThisThread, nThreadsTotal);
+
+ assert(mbThreadedGroupCalcInProgress);
+
+ return maThreadSpecific;
}
void ScDocument::HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen )
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index ce5e9b6c4627..2f2a0dabe995 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6769,70 +6769,125 @@ ScMutationGuard::~ScMutationGuard()
#endif
}
-thread_local std::map<const ScDocument *, ScDocumentThreadSpecific> ScDocument::maThreadSpecific;
+thread_local ScDocumentThreadSpecific ScDocument::maThreadSpecific;
bool ScDocument::IsInInterpreter() const
{
- if (maThreadSpecific.find(this) != maThreadSpecific.end())
- return maThreadSpecific[this].nInterpretLevel != 0;
- return false;
+ if (!mbThreadedGroupCalcInProgress)
+ return maNonThreaded.nInterpretLevel != 0;
+ else
+ return maThreadSpecific.nInterpretLevel != 0;
}
void ScDocument::IncInterpretLevel()
{
- if (maThreadSpecific[this].nInterpretLevel < USHRT_MAX)
- maThreadSpecific[this].nInterpretLevel++;
+ if (!mbThreadedGroupCalcInProgress)
+ maNonThreaded.nInterpretLevel++;
+ else
+ maThreadSpecific.nInterpretLevel++;
}
void ScDocument::DecInterpretLevel()
{
- if (maThreadSpecific[this].nInterpretLevel)
- maThreadSpecific[this].nInterpretLevel--;
+ if (!mbThreadedGroupCalcInProgress)
+ maNonThreaded.nInterpretLevel--;
+ else
+ maThreadSpecific.nInterpretLevel--;
}
sal_uInt16 ScDocument::GetMacroInterpretLevel()
{
- if (maThreadSpecific.find(this) != maThreadSpecific.end())
- return maThreadSpecific[this].nMacroInterpretLevel;
- return 0;
+ if (!mbThreadedGroupCalcInProgress)
+ return maNonThreaded.nMacroInterpretLevel;
+ else
+ return maThreadSpecific.nMacroInterpretLevel;
}
void ScDocument::IncMacroInterpretLevel()
{
- if (maThreadSpecific[this].nMacroInterpretLevel < USHRT_MAX)
- maThreadSpecific[this].nMacroInterpretLevel++;
+ if (!mbThreadedGroupCalcInProgress)
+ maNonThreaded.nMacroInterpretLevel++;
+ else
+ maThreadSpecific.nMacroInterpretLevel++;
}
void ScDocument::DecMacroInterpretLevel()
{
- if (maThreadSpecific[this].nMacroInterpretLevel)
- maThreadSpecific[this].nMacroInterpretLevel--;
+ if (!mbThreadedGroupCalcInProgress)
+ maNonThreaded.nMacroInterpretLevel--;
+ else
+ maThreadSpecific.nMacroInterpretLevel--;
}
bool ScDocument::IsInInterpreterTableOp() const
{
- if (maThreadSpecific.find(this) != maThreadSpecific.end())
- return maThreadSpecific[this].nInterpreterTableOpLevel != 0;
- return false;
+ if (!mbThreadedGroupCalcInProgress)
+ return maNonThreaded.nInterpreterTableOpLevel != 0;
+ else
+ return maThreadSpecific.nInterpreterTableOpLevel != 0;
}
void ScDocument::IncInterpreterTableOpLevel()
{
- if (maThreadSpecific[this].nInterpreterTableOpLevel < USHRT_MAX)
- maThreadSpecific[this].nInterpreterTableOpLevel++;
+ if (!mbThreadedGroupCalcInProgress)
+ {
+ if (maNonThreaded.nInterpreterTableOpLevel < USHRT_MAX)
+ maNonThreaded.nInterpreterTableOpLevel++;
+ }
+ else
+ {
+ if (maThreadSpecific.nInterpreterTableOpLevel < USHRT_MAX)
+ maThreadSpecific.nInterpreterTableOpLevel++;
+ }
}
void ScDocument::DecInterpreterTableOpLevel()
{
- if (maThreadSpecific[this].nInterpreterTableOpLevel)
- maThreadSpecific[this].nInterpreterTableOpLevel--;
+ if (!mbThreadedGroupCalcInProgress)
+ {
+ if (maNonThreaded.nInterpreterTableOpLevel)
+ maNonThreaded.nInterpreterTableOpLevel--;
+ }
+ else
+ {
+ if (maThreadSpecific.nInterpreterTableOpLevel)
+ maThreadSpecific.nInterpreterTableOpLevel--;
+ }
}
ScRecursionHelper& ScDocument::GetRecursionHelper()
{
- if (!maThreadSpecific[this].pRecursionHelper)
- maThreadSpecific[this].pRecursionHelper = CreateRecursionHelperInstance();
- return *maThreadSpecific[this].pRecursionHelper;
+ if (!mbThreadedGroupCalcInProgress)
+ {
+ if (!maNonThreaded.pRecursionHelper)
+ maNonThreaded.pRecursionHelper = CreateRecursionHelperInstance();
+ return *maNonThreaded.pRecursionHelper;
+ }
+ else
+ {
+ if (!maThreadSpecific.pRecursionHelper)
+ maThreadSpecific.pRecursionHelper = CreateRecursionHelperInstance();
+ return *maThreadSpecific.pRecursionHelper;
+ }
+}
+
+void ScDocumentThreadSpecific::SetupFromNonThreadedData(const ScDocumentThreadSpecific& rNonThreadedData)
+{
+ nInterpretLevel = rNonThreadedData.nInterpretLevel;
+ nMacroInterpretLevel = rNonThreadedData.nMacroInterpretLevel;
+ nInterpreterTableOpLevel = rNonThreadedData.nInterpreterTableOpLevel;
+
+ // What about the recursion helper?
+ // Copy the lookup cache?
+}
+
+void ScDocumentThreadSpecific::MergeBackIntoNonThreadedData(ScDocumentThreadSpecific& rNonThreadedData)
+{
+ assert(nInterpretLevel == rNonThreadedData.nInterpretLevel);
+ assert(nMacroInterpretLevel == rNonThreadedData.nMacroInterpretLevel);
+ assert(nInterpreterTableOpLevel == rNonThreadedData.nInterpreterTableOpLevel);
+
+ // What about recursion helper and lookup cache?
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index a98263cc2d2a..2d04938d2632 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -4384,7 +4384,7 @@ bool ScFormulaCell::InterpretFormulaGroup()
virtual void doWork() override
{
- mpDocument->CalculateInColumnInThread(mrTopPos, mnLength, mnThisThread, mnThreadsTotal);
+ mpDocument->CalculateInColumnInThread(mrTopPos, mnLength, mnThisThread, mnThreadsTotal).MergeBackIntoNonThreadedData(mpDocument->maNonThreaded);
}
};