diff options
author | Tor Lillqvist <tml@collabora.com> | 2017-08-16 13:01:38 +0300 |
---|---|---|
committer | Dennis Francis <dennis.francis@collabora.co.uk> | 2017-11-21 13:49:51 +0530 |
commit | 1a22af493c9227a6a3823b3f0cdf7152728cc46d (patch) | |
tree | b60b7d7e8c7514a0c4faa9b5b8f0b43287a80231 | |
parent | 32328cc9db0b3dffe385140246aac3f9e817fb18 (diff) |
Move some of the fields in ScDocument into a thread-local struct
This is part of the work to enable having several ScInterpreters
working on the same object in parallel. Perhaps a more thorugh
re-factoring would be better, maybe these fields should not be part of
ScDocument at all, but part of ScInterpreter?
Without this change the parallelism unit test occasionally fails.
Change-Id: I70500b4d2b513e134d22b4b98c84a3ec00dad291
-rw-r--r-- | sc/inc/document.hxx | 81 | ||||
-rw-r--r-- | sc/source/core/data/documen2.cxx | 37 | ||||
-rw-r--r-- | sc/source/core/data/document.cxx | 66 |
3 files changed, 120 insertions, 64 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 2078d5df3929..4f798d2ef6ce 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -273,6 +273,27 @@ 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! +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 + + ScRecursionHelper* pRecursionHelper; // information for recursive and iterative cell formulas + + ScLookupCacheMapImpl* pLookupCacheMapImpl; // cache for lookups like VLOOKUP and MATCH + + ScDocumentThreadSpecific() : + nInterpretLevel(0), + nMacroInterpretLevel(0), + nInterpreterTableOpLevel(0), + pRecursionHelper(nullptr), + pLookupCacheMapImpl(nullptr) + { + } + +}; + enum class ScMutationGuardFlags { // Bit mask bits @@ -391,12 +412,8 @@ private: std::unique_ptr<ScClipOptions> mpClipOptions; // clipboard options ScConsolidateParam* pConsolidateDlgData; - ScRecursionHelper* pRecursionHelper; // information for recursive and iterative cell formulas - ScAutoNameCache* pAutoNameCache; // for automatic name lookup during CompileXML - ScLookupCacheMapImpl* pLookupCacheMapImpl; // cache for lookups like VLOOKUP and MATCH - SfxItemSet* pPreviewFont; // convert to std::unique_ptr or whatever ScStyleSheet* pPreviewCellStyle; ScMarkData maPreviewSelection; @@ -430,9 +447,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 - sal_uInt16 nInterpreterTableOpLevel; // >0 if in interpreter TableOp + static thread_local std::map<const ScDocument *, ScDocumentThreadSpecific> maThreadSpecific; sal_uInt16 nSrcVer; // file version (load/save) sal_uInt16 nFormulaTrackCount; HardRecalcState eHardRecalcState; // off, temporary, eternal @@ -2150,49 +2165,21 @@ public: void SetForcedFormulas( bool bVal ) { bHasForcedFormulas = bVal; } sal_uLong GetFormulaCodeInTree() const { return nFormulaCodeInTree; } - bool IsInInterpreter() const { return nInterpretLevel != 0; } - void IncInterpretLevel() - { - if ( nInterpretLevel < USHRT_MAX ) - nInterpretLevel++; - } - void DecInterpretLevel() - { - if ( nInterpretLevel ) - nInterpretLevel--; - } - sal_uInt16 GetMacroInterpretLevel() { return nMacroInterpretLevel; } - void IncMacroInterpretLevel() - { - if ( nMacroInterpretLevel < USHRT_MAX ) - nMacroInterpretLevel++; - } - void DecMacroInterpretLevel() - { - if ( nMacroInterpretLevel ) - nMacroInterpretLevel--; - } - 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 + bool IsInInterpreter() const; + void IncInterpretLevel(); + void DecInterpretLevel(); + sal_uInt16 GetMacroInterpretLevel(); + void IncMacroInterpretLevel(); + void DecMacroInterpretLevel(); + bool IsInInterpreterTableOp() const; + void IncInterpreterTableOpLevel(); + void DecInterpreterTableOpLevel(); + + // add a formula to be remembered for TableOp broadcasts void AddTableOpFormulaCell( ScFormulaCell* ); void InvalidateLastTableOpParams() { aLastTableOpParams.bValid = false; } - ScRecursionHelper& GetRecursionHelper() - { - if (!pRecursionHelper) - pRecursionHelper = CreateRecursionHelperInstance(); - return *pRecursionHelper; - } + ScRecursionHelper& GetRecursionHelper(); bool IsInDtorClear() const { return bInDtorClear; } void SetExpandRefs( bool bVal ); bool IsExpandRefs() const { return bExpandRefs; } diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 7399dd976aff..3c3266225c1b 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -165,9 +165,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : pDocOptions( nullptr ), pExtDocOptions( nullptr ), pConsolidateDlgData( nullptr ), - pRecursionHelper( nullptr ), pAutoNameCache( nullptr ), - pLookupCacheMapImpl( nullptr ), pPreviewFont( nullptr ), pPreviewCellStyle( nullptr ), nUnoObjectId( 0 ), @@ -176,9 +174,6 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : mbThreadedGroupCalcInProgress( false ), nFormulaCodeInTree(0), nXMLImportedFormulaCount( 0 ), - nInterpretLevel(0), - nMacroInterpretLevel(0), - nInterpreterTableOpLevel(0), nSrcVer( SC_CURRENT_VERSION ), nFormulaTrackCount(0), eHardRecalcState(HardRecalcState::OFF), @@ -400,7 +395,12 @@ ScDocument::~ScDocument() ScAddInAsync::RemoveDocument( this ); ScAddInListener::RemoveDocument( this ); DELETEZ( pChartListenerCollection); // before pBASM because of potential Listener! - DELETEZ( pLookupCacheMapImpl); // before pBASM because of listeners + + if (maThreadSpecific.find(this) != maThreadSpecific.end()) + { + DELETEZ( maThreadSpecific[this].pLookupCacheMapImpl ); // before pBASM because of listeners + } + // destroy BroadcastAreas first to avoid un-needed Single-EndListenings of Formula-Cells delete pBASM; // BroadcastAreaSlotMachine pBASM = nullptr; @@ -449,13 +449,16 @@ ScDocument::~ScDocument() mxPoolHelper.clear(); delete pScriptTypeData; - delete pRecursionHelper; + if (maThreadSpecific.find(this) != maThreadSpecific.end()) + delete maThreadSpecific[this].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 ) @@ -1231,10 +1234,10 @@ ScRecursionHelper* ScDocument::CreateRecursionHelperInstance() ScLookupCache & ScDocument::GetLookupCache( const ScRange & rRange ) { ScLookupCache* pCache = nullptr; - if (!pLookupCacheMapImpl) - pLookupCacheMapImpl = new ScLookupCacheMapImpl; - auto it( pLookupCacheMapImpl->aCacheMap.find( rRange)); - if (it == pLookupCacheMapImpl->aCacheMap.end()) + if (!maThreadSpecific[this].pLookupCacheMapImpl) + maThreadSpecific[this].pLookupCacheMapImpl = new ScLookupCacheMapImpl; + auto it( maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.find( rRange)); + if (it == maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.end()) { pCache = new ScLookupCache( this, rRange); AddLookupCache( *pCache); @@ -1246,7 +1249,7 @@ ScLookupCache & ScDocument::GetLookupCache( const ScRange & rRange ) void ScDocument::AddLookupCache( ScLookupCache & rCache ) { - if (!pLookupCacheMapImpl->aCacheMap.insert( ::std::pair< const ScRange, + if (!maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.insert( ::std::pair< const ScRange, ScLookupCache*>( rCache.getRange(), &rCache)).second) { OSL_FAIL( "ScDocument::AddLookupCache: couldn't add to hash map"); @@ -1257,24 +1260,24 @@ void ScDocument::AddLookupCache( ScLookupCache & rCache ) void ScDocument::RemoveLookupCache( ScLookupCache & rCache ) { - auto it( pLookupCacheMapImpl->aCacheMap.find( + auto it( maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.find( rCache.getRange())); - if (it == pLookupCacheMapImpl->aCacheMap.end()) + if (it == maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.end()) { OSL_FAIL( "ScDocument::RemoveLookupCache: range not found in hash map"); } else { ScLookupCache* pCache = (*it).second; - pLookupCacheMapImpl->aCacheMap.erase( it); + maThreadSpecific[this].pLookupCacheMapImpl->aCacheMap.erase( it); EndListeningArea( pCache->getRange(), false, &rCache); } } void ScDocument::ClearLookupCaches() { - if( pLookupCacheMapImpl ) - pLookupCacheMapImpl->clear(); + if( maThreadSpecific[this].pLookupCacheMapImpl ) + maThreadSpecific[this].pLookupCacheMapImpl->clear(); } bool ScDocument::IsCellInChangeTrack(const ScAddress &cell,Color *pColCellBorder) diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index d1e42ea9c0b3..ce5e9b6c4627 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -6769,4 +6769,70 @@ ScMutationGuard::~ScMutationGuard() #endif } +thread_local std::map<const ScDocument *, ScDocumentThreadSpecific> ScDocument::maThreadSpecific; + +bool ScDocument::IsInInterpreter() const +{ + if (maThreadSpecific.find(this) != maThreadSpecific.end()) + return maThreadSpecific[this].nInterpretLevel != 0; + return false; +} + +void ScDocument::IncInterpretLevel() +{ + if (maThreadSpecific[this].nInterpretLevel < USHRT_MAX) + maThreadSpecific[this].nInterpretLevel++; +} + +void ScDocument::DecInterpretLevel() +{ + if (maThreadSpecific[this].nInterpretLevel) + maThreadSpecific[this].nInterpretLevel--; +} + +sal_uInt16 ScDocument::GetMacroInterpretLevel() +{ + if (maThreadSpecific.find(this) != maThreadSpecific.end()) + return maThreadSpecific[this].nMacroInterpretLevel; + return 0; +} + +void ScDocument::IncMacroInterpretLevel() +{ + if (maThreadSpecific[this].nMacroInterpretLevel < USHRT_MAX) + maThreadSpecific[this].nMacroInterpretLevel++; +} + +void ScDocument::DecMacroInterpretLevel() +{ + if (maThreadSpecific[this].nMacroInterpretLevel) + maThreadSpecific[this].nMacroInterpretLevel--; +} + +bool ScDocument::IsInInterpreterTableOp() const +{ + if (maThreadSpecific.find(this) != maThreadSpecific.end()) + return maThreadSpecific[this].nInterpreterTableOpLevel != 0; + return false; +} + +void ScDocument::IncInterpreterTableOpLevel() +{ + if (maThreadSpecific[this].nInterpreterTableOpLevel < USHRT_MAX) + maThreadSpecific[this].nInterpreterTableOpLevel++; +} + +void ScDocument::DecInterpreterTableOpLevel() +{ + if (maThreadSpecific[this].nInterpreterTableOpLevel) + maThreadSpecific[this].nInterpreterTableOpLevel--; +} + +ScRecursionHelper& ScDocument::GetRecursionHelper() +{ + if (!maThreadSpecific[this].pRecursionHelper) + maThreadSpecific[this].pRecursionHelper = CreateRecursionHelperInstance(); + return *maThreadSpecific[this].pRecursionHelper; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |