diff options
author | Tor Lillqvist <tml@collabora.com> | 2017-08-22 14:26:29 +0300 |
---|---|---|
committer | Dennis Francis <dennis.francis@collabora.co.uk> | 2017-11-21 16:09:40 +0530 |
commit | 12d70f4a89f5586f1b617c052b9573f706030d17 (patch) | |
tree | 5a6409d061677074155adcd7bd585dfed0b2f938 /sc | |
parent | 6d94519008580975608f852f4adee50ec099a6ad (diff) |
Move formula tree manipulation out of multi-threaded parts of code
Change-Id: I2f7e6fb747b6a74172a81f9db9bc210ef6a27342
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 1 | ||||
-rw-r--r-- | sc/inc/document.hxx | 1 | ||||
-rw-r--r-- | sc/inc/formulacell.hxx | 4 | ||||
-rw-r--r-- | sc/inc/table.hxx | 1 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 23 | ||||
-rw-r--r-- | sc/source/core/data/documen8.cxx | 9 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 133 | ||||
-rw-r--r-- | sc/source/core/data/table1.cxx | 7 |
8 files changed, 136 insertions, 43 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index e6ddccb1c5eb..67bc6c348c5e 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -583,6 +583,7 @@ public: void SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen ); void CalculateInThread( SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); + void HandleStuffAfterParallelCalculation( SCROW nRow, size_t nLen ); void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index a51a5f3f18d5..add4a3338200 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -2024,6 +2024,7 @@ public: 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); + void HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen ); /** * Transfer a series of contiguous cell values from specified position to diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 3eed0ea45246..d7fe046c7c0e 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -150,7 +150,9 @@ public: SCITP_FROM_ITERATION, SCITP_CLOSE_ITERATION_CIRCLE }; - void InterpretTail( ScInterpretTailParameter, bool bUpdateProgress ); + void InterpretTail( ScInterpretTailParameter, bool bSingleThreaded ); + + void HandleStuffAfterParallelCalculation(); enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef }; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index c7fa43e64e96..9b04a4d019a4 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -998,6 +998,7 @@ public: void SetFormulaResults( SCCOL nCol, SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen ); void CalculateInColumnInThread( SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); + void HandleStuffAfterParallelCalculation( SCCOL nCol, SCROW nRow, size_t nLen); /** * Either start all formula cells as listeners unconditionally, or start 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 { |