diff options
author | Tor Lillqvist <tml@collabora.com> | 2017-09-29 11:04:17 +0300 |
---|---|---|
committer | Dennis Francis <dennis.francis@collabora.co.uk> | 2017-11-21 16:09:42 +0530 |
commit | 9732f2b1588e2686f5bdec416972c1686289b635 (patch) | |
tree | ce05fddf6e3c7d190d34c94bfc71202609f2fef7 /sc | |
parent | 973953bff0455c48b4ea43f6f4dd27778661eff3 (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.hxx | 18 | ||||
-rw-r--r-- | sc/source/core/data/documen2.cxx | 105 | ||||
-rw-r--r-- | sc/source/core/data/documen8.cxx | 11 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 105 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 2 |
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); } }; |