summaryrefslogtreecommitdiff
path: root/sc/source/core
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2017-08-22 14:26:29 +0300
committerDennis Francis <dennis.francis@collabora.co.uk>2017-11-21 13:49:49 +0530
commit115206ed8a797ed82de63fa33d82bb3679d01d63 (patch)
tree0f4e2387b7744bcb980214564bfbcf1a56a2120b /sc/source/core
parentea7df4d8f94e25206114bfed503c683a8e7e79e0 (diff)
Move formula tree manipulation out of multi-threaded parts of code
Change-Id: I2f7e6fb747b6a74172a81f9db9bc210ef6a27342
Diffstat (limited to 'sc/source/core')
-rw-r--r--sc/source/core/data/column2.cxx23
-rw-r--r--sc/source/core/data/documen8.cxx9
-rw-r--r--sc/source/core/data/formulacell.cxx133
-rw-r--r--sc/source/core/data/table1.cxx7
4 files changed, 130 insertions, 42 deletions
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 8e852f856c7a..760bd805a761 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2930,6 +2930,29 @@ void ScColumn::CalculateInThread( SCROW nRow, size_t nLen, unsigned nThisThread,
}
}
+void ScColumn::HandleStuffAfterParallelCalculation( SCROW nRow, size_t nLen )
+{
+ sc::CellStoreType::position_type aPos = maCells.position(nRow);
+ sc::CellStoreType::iterator it = aPos.first;
+ if (it->type != sc::element_type_formula)
+ // This is not a formula block.
+ return;
+
+ size_t nBlockLen = it->size - aPos.second;
+ if (nBlockLen < nLen)
+ // Length is longer than the length of formula cells. Not good.
+ return;
+
+ sc::formula_block::iterator itCell = sc::formula_block::begin(*it->data);
+ std::advance(itCell, aPos.second);
+
+ for (size_t i = 0; i < nLen; ++i, ++itCell)
+ {
+ ScFormulaCell& rCell = **itCell;
+ rCell.HandleStuffAfterParallelCalculation();
+ }
+}
+
void ScColumn::SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat )
{
ApplyAttr(nRow, SfxUInt32Item(ATTR_VALUE_FORMAT, nNumberFormat));
diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index ea5c34b55bc9..7e31c2f6ab35 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -436,6 +436,15 @@ void ScDocument::CalculateInColumnInThread( const ScAddress& rTopPos, size_t nLe
pTab->CalculateInColumnInThread(rTopPos.Col(), rTopPos.Row(), nLen, nThisThread, nThreadsTotal);
}
+void ScDocument::HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen )
+{
+ ScTable* pTab = FetchTable(rTopPos.Tab());
+ if (!pTab)
+ return;
+
+ pTab->HandleStuffAfterParallelCalculation(rTopPos.Col(), rTopPos.Row(), nLen);
+}
+
void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo,
bool bNumFormatChanged )
{
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 835b813389c5..d6996fa35036 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1724,7 +1724,24 @@ void ScFormulaCell::Interpret()
#endif
}
-void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bUpdateProgress )
+namespace {
+class StackCleaner
+{
+ ScDocument* pDoc;
+ ScInterpreter* pInt;
+ public:
+ StackCleaner( ScDocument* pD, ScInterpreter* pI )
+ : pDoc(pD), pInt(pI)
+ {}
+ ~StackCleaner()
+ {
+ delete pInt;
+ pDoc->DecInterpretLevel();
+ }
+};
+}
+
+void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bSingleThreaded )
{
RecursionCounter aRecursionCounter( pDocument->GetRecursionHelper(), this);
nSeenInIteration = pDocument->GetRecursionHelper().GetIteration();
@@ -1751,20 +1768,6 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bUp
if( pCode->GetCodeLen() && pDocument )
{
- class StackCleaner
- {
- ScDocument* pDoc;
- ScInterpreter* pInt;
- public:
- StackCleaner( ScDocument* pD, ScInterpreter* pI )
- : pDoc(pD), pInt(pI)
- {}
- ~StackCleaner()
- {
- delete pInt;
- pDoc->DecInterpretLevel();
- }
- };
pDocument->IncInterpretLevel();
ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, aPos, *pCode );
StackCleaner aStackCleaner( pDocument, pInterpreter);
@@ -2085,7 +2088,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bUp
// a changed result must still reset the stream flag
pDocument->SetStreamValid(aPos.Tab(), false, true);
}
- if ( !pCode->IsRecalcModeAlways() )
+ if ( bSingleThreaded && !pCode->IsRecalcModeAlways() )
pDocument->RemoveFromFormulaTree( this );
// FORCED cells also immediately tested for validity (start macro possibly)
@@ -2104,7 +2107,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bUp
}
// Reschedule slows the whole thing down considerably, thus only execute on percent change
- if (bUpdateProgress)
+ if (bSingleThreaded)
{
ScProgress *pProgress = ScProgress::GetInterpretProgress();
if (pProgress && pProgress->Enabled())
@@ -2112,13 +2115,59 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bUp
pProgress->SetStateCountDownOnPercent(
pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE );
}
+
+ switch (pInterpreter->GetVolatileType())
+ {
+ case ScInterpreter::VOLATILE:
+ // Volatile via built-in volatile functions. No actions needed.
+ break;
+ case ScInterpreter::VOLATILE_MACRO:
+ // The formula contains a volatile macro.
+ pCode->SetExclusiveRecalcModeAlways();
+ pDocument->PutInFormulaTree(this);
+ StartListeningTo(pDocument);
+ break;
+ case ScInterpreter::NOT_VOLATILE:
+ if (pCode->IsRecalcModeAlways())
+ {
+ // The formula was previously volatile, but no more.
+ EndListeningTo(pDocument);
+ pCode->SetExclusiveRecalcModeNormal();
+ }
+ else
+ {
+ // non-volatile formula. End listening to the area in case
+ // it's listening due to macro module change.
+ pDocument->EndListeningArea(BCA_LISTEN_ALWAYS, false, this);
+ }
+ pDocument->RemoveFromFormulaTree(this);
+ break;
+ default:
+ ;
+ }
}
+ }
+ else
+ {
+ // Cells with compiler errors should not be marked dirty forever
+ OSL_ENSURE( pCode->GetCodeError() != FormulaError::NONE, "no RPN code and no errors ?!?!" );
+ ResetDirty();
+ }
+}
+
+void ScFormulaCell::HandleStuffAfterParallelCalculation()
+{
+ if( pCode->GetCodeLen() && pDocument )
+ {
+ if ( !pCode->IsRecalcModeAlways() )
+ pDocument->RemoveFromFormulaTree( this );
+
+ pDocument->IncInterpretLevel();
+ ScInterpreter* pInterpreter = new ScInterpreter( this, pDocument, aPos, *pCode );
+ StackCleaner aStackCleaner( pDocument, pInterpreter);
switch (pInterpreter->GetVolatileType())
{
- case ScInterpreter::VOLATILE:
- // Volatile via built-in volatile functions. No actions needed.
- break;
case ScInterpreter::VOLATILE_MACRO:
// The formula contains a volatile macro.
pCode->SetExclusiveRecalcModeAlways();
@@ -2144,12 +2193,6 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam, bool bUp
;
}
}
- else
- {
- // Cells with compiler errors should not be marked dirty forever
- OSL_ENSURE( pCode->GetCodeError() != FormulaError::NONE, "no RPN code and no errors ?!?!" );
- ResetDirty();
- }
}
void ScFormulaCell::SetCompile( bool bVal )
@@ -4255,27 +4298,33 @@ bool ScFormulaCell::InterpretFormulaGroup()
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();
- for (int i = 0; i < nThreadCount; ++i)
- {
- rThreadPool.pushTask(new Executor(aTag, i, nThreadCount, pDocument, mxGroup->mpTopCell->aPos, mxGroup->mnLength, vResult));
- }
- SAL_INFO("sc.threaded", "Joining threads");
- rThreadPool.waitUntilDone(aTag);
- SAL_INFO("sc.threaded", "Done");
- for (int i = 0; i < nThreadCount; ++i)
{
- if (!vResult[i])
+ ScMutationGuard aGuard(pDocument, ScMutationGuardFlags::CORE);
+
+ // Start nThreadCount new threads
+ std::vector<int> vResult(nThreadCount);
+ std::shared_ptr<comphelper::ThreadTaskTag> aTag = comphelper::ThreadPool::createThreadTaskTag();
+ for (int i = 0; i < nThreadCount; ++i)
{
- SAL_INFO("sc.threaded", "Thread " << i << " failed");
- result = false;
+ rThreadPool.pushTask(new Executor(aTag, i, nThreadCount, pDocument, mxGroup->mpTopCell->aPos, mxGroup->mnLength, vResult));
+ }
+
+ SAL_INFO("sc.threaded", "Joining threads");
+ rThreadPool.waitUntilDone(aTag);
+ SAL_INFO("sc.threaded", "Done");
+
+ for (int i = 0; i < nThreadCount; ++i)
+ {
+ if (!vResult[i])
+ {
+ SAL_INFO("sc.threaded", "Thread " << i << " failed");
+ result = false;
+ }
}
}
+ pDocument->HandleStuffAfterParallelCalculation(mxGroup->mpTopCell->aPos, mxGroup->mnLength);
+
return result;
}
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index fdafbbc6c1f8..961b2f443568 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2346,6 +2346,13 @@ void ScTable::CalculateInColumnInThread( SCCOL nCol, SCROW nRow, size_t nLen, un
aCol[nCol].CalculateInThread( nRow, nLen, nThisThread, nThreadsTotal );
}
+void ScTable::HandleStuffAfterParallelCalculation( SCCOL nCol, SCROW nRow, size_t nLen)
+{
+ assert(ValidCol(nCol));
+
+ aCol[nCol].HandleStuffAfterParallelCalculation( nRow, nLen );
+}
+
#if DUMP_COLUMN_STORAGE
void ScTable::DumpColumnStorage( SCCOL nCol ) const
{