include/formula/token.hxx | 1 + sc/inc/formularesult.hxx | 3 +++ sc/source/core/data/formulacell.cxx | 2 ++ sc/source/core/tool/formularesult.cxx | 25 +++++++++++++++++++++++++ 4 files changed, 31 insertions(+)
New commits: commit 9d29649e07a3b2c5c2b3dda1dc15c0ca1ed51ae3 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sun Apr 14 21:09:59 2024 +0100 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Mon Apr 15 14:08:06 2024 +0200 Related: tdf#160056 FormulaResult may ref an initial interpreter FormulaToken If a token from the original tokens, supplied to a parallel group calculation while RefCounting was disabled for those tokens, ends up as a FormulaResult token, then fix up the ref count when parallel calculation ends Change-Id: I2587c25d216ab170725017b67b97d203a578160b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166080 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/include/formula/token.hxx b/include/formula/token.hxx index 68461a48db1d..89043877a4fd 100644 --- a/include/formula/token.hxx +++ b/include/formula/token.hxx @@ -186,6 +186,7 @@ public: } void SetRefCntPolicy(RefCntPolicy ePolicy) { eRefCntPolicy = ePolicy; } + RefCntPolicy GetRefCntPolicy() const { return eRefCntPolicy; } oslInterlockedCount GetRef() const { return mnRefCnt; } OpCode GetOpCode() const { return eOp; } diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index 581d9a4bba3d..44aab47acd44 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -62,6 +62,7 @@ class ScFormulaResult const formula::FormulaToken* mpToken; // if not, result token obtained from interpreter }; bool mbToken :1; // whether content of union is a token + bool mbNoneRefCnt :1; // if token was added when using RefCntPolicy::None bool mbEmpty :1; // empty cell result bool mbEmptyDisplayedAsString :1; // only if mbEmpty // If set it implies that the result is a simple double (in mfValue) and no error @@ -208,6 +209,8 @@ public: /** Get the ScMatrixFormulaCellToken* if token is of that type, else NULL. Shouldn't be used externally except by ScFormulaCell::SetMatColsRows(). */ ScMatrixFormulaCellToken* GetMatrixFormulaCellTokenNonConst(); + + void HandleStuffAfterParallelCalculation(); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index e57514b0345a..529ea73a7e6e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2336,6 +2336,8 @@ void ScFormulaCell::InterpretTail( ScInterpreterContext& rContext, ScInterpretTa void ScFormulaCell::HandleStuffAfterParallelCalculation(ScInterpreter* pInterpreter) { + aResult.HandleStuffAfterParallelCalculation(); + if( !pCode->GetCodeLen() ) return; diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index b421354550a3..08ef363ff68f 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -26,6 +26,7 @@ FormulaResultValue::FormulaResultValue( FormulaError nErr ) : mfValue(0.0), meTy ScFormulaResult::ScFormulaResult() : mpToken(nullptr), mbToken(true), + mbNoneRefCnt(false), mbEmpty(false), mbEmptyDisplayedAsString(false), mbValueCached(false), @@ -58,10 +59,12 @@ ScFormulaResult::ScFormulaResult( const ScFormulaResult & r ) : } else mfValue = r.mfValue; + mbNoneRefCnt = mbToken && mpToken && mpToken->GetRefCntPolicy() == formula::RefCntPolicy::None; } ScFormulaResult::ScFormulaResult( const formula::FormulaToken* p ) : mbToken(false), + mbNoneRefCnt(false), mbEmpty(false), mbEmptyDisplayedAsString(false), mbValueCached(false), @@ -129,6 +132,7 @@ void ScFormulaResult::ResolveToken( const formula::FormulaToken * p ) mbToken = true; } } + mbNoneRefCnt = mbToken && mpToken && mpToken->GetRefCntPolicy() == formula::RefCntPolicy::None; } ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r ) @@ -151,6 +155,7 @@ void ScFormulaResult::Assign( const ScFormulaResult & r ) if (mbToken && mpToken) mpToken->DecRef(); mbToken = false; + mbNoneRefCnt = false; mbEmpty = true; mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString; meMultiline = r.meMultiline; @@ -236,6 +241,7 @@ void ScFormulaResult::SetDouble( double f ) mpToken->DecRef(); mfValue = f; mbToken = false; + mbNoneRefCnt = false; meMultiline = MULTILINE_FALSE; mbValueCached = true; } @@ -563,12 +569,14 @@ void ScFormulaResult::SetHybridDouble( double f ) mpToken->DecRef(); mpToken = new ScHybridCellToken( f, aString, aFormula, false); mpToken->IncRef(); + mbNoneRefCnt = false; } } else { mfValue = f; mbToken = false; + mbNoneRefCnt = false; meMultiline = MULTILINE_FALSE; mbValueCached = true; } @@ -585,6 +593,7 @@ void ScFormulaResult::SetHybridString( const svl::SharedString& rStr ) mpToken = new ScHybridCellToken( f, rStr, aFormula, false); mpToken->IncRef(); mbToken = true; + mbNoneRefCnt = false; } void ScFormulaResult::SetHybridEmptyDisplayedAsString() @@ -602,6 +611,7 @@ void ScFormulaResult::SetHybridEmptyDisplayedAsString() mpToken = new ScHybridCellToken( f, aStr, aFormula, true); mpToken->IncRef(); mbToken = true; + mbNoneRefCnt = false; } void ScFormulaResult::SetHybridFormula( const OUString & rFormula ) @@ -615,6 +625,7 @@ void ScFormulaResult::SetHybridFormula( const OUString & rFormula ) mpToken = new ScHybridCellToken( f, aStr, rFormula, false); mpToken->IncRef(); mbToken = true; + mbNoneRefCnt = false; } void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL ) @@ -625,6 +636,7 @@ void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRe mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL); mpToken->IncRef(); mbToken = true; + mbNoneRefCnt = false; } const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const @@ -638,4 +650,17 @@ ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst() return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken()); } +// If a token from the original tokens, supplied to a parallel group calculation +// while RefCounting was disabled for those tokens, ends up as a FormulaResult +// token, then fix up the ref count now +void ScFormulaResult::HandleStuffAfterParallelCalculation() +{ + if (mbNoneRefCnt) + { + assert(mbToken && mpToken && mpToken->GetRefCntPolicy() != formula::RefCntPolicy::None); + mpToken->IncRef(); + mbNoneRefCnt = false; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */