summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2017-09-22 18:55:37 +0300
committerDennis Francis <dennis.francis@collabora.co.uk>2017-11-21 13:49:49 +0530
commitdeca44db3c383be546a40f059130b1f046d36b16 (patch)
tree786fcb41e2e5db11b6bbe615922bae7c466524a1
parent7279481b869542ac094cddc56f76ae0712532b31 (diff)
Add "mutation guard" API for ScDocument
USe by adding a ScMutationGuard object to a section of code that shouldn't be run during threaded calculation of a formula group in any of the calculation threads. There are currently several "classes" of mutation as bits of ScMutationGuardFlags, althouh I am not sure whether that will be useful, so far I use just the one same (CORE) in all cases. Currently implemented using mutexes. Possibly a simple bool field in ScDocument would be enough, the multiple flags and mutexes might be over-complicating it? Maybe I misunderstood what I want. Add such mutation guards for some fields of ScDocument. Change-Id: If2a8223c49d36143f2984e0449798271f2b6440d
-rw-r--r--sc/inc/document.hxx27
-rw-r--r--sc/source/core/data/documen2.cxx3
-rw-r--r--sc/source/core/data/documen7.cxx3
-rw-r--r--sc/source/core/data/document.cxx30
-rw-r--r--sc/source/core/data/document10.cxx2
-rw-r--r--sc/source/core/data/formulacell.cxx3
-rw-r--r--sc/source/core/tool/interpr1.cxx1
7 files changed, 69 insertions, 0 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index e1ba0f33f30a..31f87443ecc4 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -41,8 +41,10 @@
#include <tools/gen.hxx>
#include <svl/zforlist.hxx>
+#include <cassert>
#include <memory>
#include <map>
+#include <mutex>
#include <set>
#include <vector>
@@ -271,6 +273,16 @@ 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!
+enum class ScMutationGuardFlags
+{
+ // Bit mask bits
+ CORE = 0x0001,
+ FORMULA = 0x0002,
+ RECURSIVE_INTERPRET = 0x0004,
+ // How many bits there are
+ N = 3
+};
+
class ScDocument
{
friend class ScValueIterator;
@@ -297,6 +309,7 @@ friend class sc::ColumnSpanSet;
friend class sc::EditTextIterator;
friend class sc::FormulaGroupAreaListener;
friend class sc::TableColumnBlockPositionSet;
+friend class ScMutationGuard;
typedef std::vector<ScTable*> TableContainer;
@@ -494,6 +507,8 @@ private:
bool mbTrackFormulasPending : 1;
bool mbFinalTrackFormulas : 1;
+ std::recursive_mutex maMutationGuard[static_cast<std::size_t>(ScMutationGuardFlags::N)];
+
public:
bool IsCellInChangeTrack(const ScAddress &cell,Color *pColCellBorder);
void GetCellChangeTrackNote(const ScAddress &cell, OUString &strTrackText, bool &pbLeftEdge);
@@ -2407,6 +2422,18 @@ private:
typedef std::unique_ptr<ScDocument, o3tl::default_delete<ScDocument>> ScDocumentUniquePtr;
+class ScMutationGuard
+{
+public:
+ ScMutationGuard(ScDocument* pDocument, ScMutationGuardFlags nFlags);
+ ~ScMutationGuard();
+
+private:
+ ScDocument* const mpDocument;
+ const ScMutationGuardFlags mnFlags;
+};
+
+
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index fb8e2557586f..ba434acae8b1 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -266,7 +266,10 @@ const sfx2::LinkManager* ScDocument::GetLinkManager() const
sc::DocumentLinkManager& ScDocument::GetDocLinkManager()
{
if (!mpDocLinkMgr)
+ {
+ ScMutationGuard aGuard(this, {ScMutationGuardFlags::CORE});
mpDocLinkMgr.reset(new sc::DocumentLinkManager(mpShell));
+ }
return *mpDocLinkMgr;
}
diff --git a/sc/source/core/data/documen7.cxx b/sc/source/core/data/documen7.cxx
index b8d577b6b9c8..b35d760137a1 100644
--- a/sc/source/core/data/documen7.cxx
+++ b/sc/source/core/data/documen7.cxx
@@ -361,6 +361,7 @@ void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
OSL_ENSURE( pCell, "PutInFormulaTree: pCell Null" );
RemoveFromFormulaTree( pCell );
// append
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
if ( pEOFormulaTree )
pEOFormulaTree->SetNext( pCell );
else
@@ -373,6 +374,7 @@ void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )
void ScDocument::RemoveFromFormulaTree( ScFormulaCell* pCell )
{
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
OSL_ENSURE( pCell, "RemoveFromFormulaTree: pCell Null" );
ScFormulaCell* pPrev = pCell->GetPrevious();
assert(pPrev != pCell); // pointing to itself?!?
@@ -429,6 +431,7 @@ void ScDocument::CalcFormulaTree( bool bOnlyForced, bool bProgressBar, bool bSet
if ( IsCalculatingFormulaTree() )
return ;
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
mpFormulaGroupCxt.reset();
bCalculatingFormulaTree = true;
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index a2f98bb17c7e..89716696d1d8 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2457,6 +2457,7 @@ ScDocument::NumFmtMergeHandler::~NumFmtMergeHandler()
void ScDocument::PrepareFormulaCalc()
{
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
mpFormulaGroupCxt.reset();
}
@@ -3538,6 +3539,7 @@ svl::SharedString ScDocument::GetSharedString( const ScAddress& rPos ) const
std::shared_ptr<sc::FormulaGroupContext>& ScDocument::GetFormulaGroupContext()
{
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
if (!mpFormulaGroupCxt)
mpFormulaGroupCxt.reset(new sc::FormulaGroupContext);
@@ -3896,6 +3898,7 @@ void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
}
}
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
mpFormulaGroupCxt.reset();
}
@@ -6300,6 +6303,7 @@ SfxUndoManager* ScDocument::GetUndoManager()
if (!mpUndoManager)
{
// to support enhanced text edit for draw objects, use an SdrUndoManager
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
mpUndoManager = new SdrUndoManager;
}
@@ -6720,4 +6724,30 @@ void ScDocument::SetAutoNameCache( ScAutoNameCache* pCache )
pAutoNameCache = pCache;
}
+ScMutationGuard::ScMutationGuard(ScDocument* pDocument, ScMutationGuardFlags nFlags) :
+ mpDocument(pDocument),
+ mnFlags(nFlags)
+{
+ for (auto b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
+ {
+ if (static_cast<std::size_t>(mnFlags) & (1 << b))
+ {
+ assert(mpDocument->maMutationGuard[b].try_lock());
+ }
+ }
+}
+
+ScMutationGuard::~ScMutationGuard()
+{
+#ifndef NDEBUG
+ for (auto b = 0; b < static_cast<std::size_t>(ScMutationGuardFlags::N); b++)
+ {
+ if (static_cast<std::size_t>(mnFlags) & (1 << b))
+ {
+ mpDocument->maMutationGuard[b].unlock();
+ }
+ }
+#endif
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 3eed195aae88..2c944e12e6ae 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -205,6 +205,7 @@ std::set<Color> ScDocument::GetDocColors()
void ScDocument::SetCalcConfig( const ScCalcConfig& rConfig )
{
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
maCalcConfig = rConfig;
}
@@ -336,6 +337,7 @@ void ScDocument::CompileHybridFormula()
void ScDocument::SharePooledResources( const ScDocument* pSrcDoc )
{
+ ScMutationGuard aGuard(this, ScMutationGuardFlags::CORE);
mxPoolHelper = pSrcDoc->mxPoolHelper;
mpCellStringPool = pSrcDoc->mpCellStringPool;
}
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index bda1c3cfa07d..835b813389c5 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -4254,6 +4254,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
sal_Int32 nThreadCount = rThreadPool.getWorkerCount();
SAL_INFO("sc.threaded", "Running " << nThreadCount << " threads");
+
+ ScMutationGuard aGuard(pDocument, ScMutationGuardFlags::CORE);
+
// Start nThreadCount new threads
std::vector<int> vResult(nThreadCount);
std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag();
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 81fa5634b8c1..157c8a2dcedd 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -6206,6 +6206,7 @@ void ScInterpreter::IterateParametersIfs( double(*ResultFunc)( const sc::ParamIf
void ScInterpreter::ScSumIfs()
{
+ // ScMutationGuard aShouldFail(pDok, ScMutationGuardFlags::CORE);
sal_uInt8 nParamCount = GetByte();
if (nParamCount < 3 || (nParamCount % 2 != 1))