summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2017-08-16 13:01:38 +0300
committerDennis Francis <dennis.francis@collabora.co.uk>2017-11-21 13:49:51 +0530
commit1a22af493c9227a6a3823b3f0cdf7152728cc46d (patch)
treeb60b7d7e8c7514a0c4faa9b5b8f0b43287a80231
parent32328cc9db0b3dffe385140246aac3f9e817fb18 (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.hxx81
-rw-r--r--sc/source/core/data/documen2.cxx37
-rw-r--r--sc/source/core/data/document.cxx66
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: */