Collect all empty broadcasters and remove them in one go later.

This is to avoid repeated calls to set_empty() on the broadcaster array
which causes array reallocation on each call. Instead, we can store the
segments of broadcasters to be deleted later, and call set_empty() on
those segments to reduce the number of calls to set_empty().

The meat of this is not implemented yet, as EndListeningContext is still
empty.

Change-Id: I914bc2881acee3902c4fec0f6c21aaf4d2489df8
This commit is contained in:
Kohei Yoshida 2013-05-13 16:13:46 -04:00
parent 180c2fe743
commit 410154e76c
13 changed files with 188 additions and 1 deletions

View file

@ -139,6 +139,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/global \
sc/source/core/data/global2 \
sc/source/core/data/globalx \
sc/source/core/data/listenercontext \
sc/source/core/data/markarr \
sc/source/core/data/markdata \
sc/source/core/data/mtvelements \

View file

@ -48,6 +48,7 @@ namespace editeng { class SvxBorderLine; }
namespace sc {
struct FormulaGroupContext;
class EndListeningContext;
}
class Fraction;
@ -439,6 +440,7 @@ public:
void StartListening( SvtListener& rLst, SCROW nRow );
void EndListening( SvtListener& rLst, SCROW nRow );
void EndListening( sc::EndListeningContext& rCxt, SCROW nRow, SvtListener& rListener );
void MoveListeners( SvtBroadcaster& rSource, SCROW nDestRow );
void StartAllListeners();
void StartNeededListeners(); // only for cells where NeedsListening()==true

View file

@ -49,6 +49,7 @@
namespace editeng { class SvxBorderLine; }
namespace sc {
struct FormulaGroupContext;
class EndListeningContext;
}
class SvxFontItem;
@ -1754,6 +1755,8 @@ public:
void EndListeningCell( const ScAddress& rAddress,
SvtListener* pListener );
void EndListeningCell( sc::EndListeningContext& rCxt, const ScAddress& rPos, SvtListener& rListener );
void EndListeningFormulaCells( std::vector<ScFormulaCell*>& rCells );
void PutInFormulaTree( ScFormulaCell* pCell );

View file

@ -28,6 +28,12 @@
#include <set>
namespace sc {
class EndListeningContext;
}
class ScTokenArray;
struct ScSimilarFormulaDelta;
@ -309,6 +315,7 @@ public:
void StartListeningTo( ScDocument* pDoc );
void EndListeningTo(
ScDocument* pDoc, ScTokenArray* pArr = NULL, ScAddress aPos = ScAddress() );
void EndListeningTo( sc::EndListeningContext& rCxt );
};
#endif

View file

@ -0,0 +1,34 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef SC_LISTENERCONTEXT_HXX
#define SC_LISTENERCONTEXT_HXX
#include "address.hxx"
class ScDocument;
namespace sc {
class EndListeningContext
{
ScDocument& mrDoc;
public:
EndListeningContext(ScDocument& rDoc);
ScDocument& getDoc();
void addEmptyBroadcasterPosition(SCCOL nCol, SCROW nRow, SCTAB nTab);
void purgeEmptyBroadcasters();
};
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -91,6 +91,8 @@ struct SC_DLLPUBLIC ScSingleRefData // Single reference (one address) int
/// In external references nTab is -1
inline bool ValidExternal() const;
ScAddress toAbs( const ScAddress& rPos ) const;
void SmartRelAbs( const ScAddress& rPos );
void CalcRelFromAbs( const ScAddress& rPos );
void CalcAbsIfRel( const ScAddress& rPos );

View file

@ -49,6 +49,7 @@ namespace com { namespace sun { namespace star {
namespace sc {
struct FormulaGroupContext;
class EndListeningContext;
}
class SfxItemSet;
@ -932,6 +933,7 @@ private:
void StartListening( const ScAddress& rAddress, SvtListener* pListener );
void EndListening( const ScAddress& rAddress, SvtListener* pListener );
void EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener );
void StartAllListeners();
void StartNeededListeners(); // only for cells where NeedsListening()==TRUE
void SetRelNameDirty();

View file

@ -58,6 +58,7 @@
#include "tokenarray.hxx"
#include "globalnames.hxx"
#include "formulagroup.hxx"
#include "listenercontext.hxx"
#include <math.h>
@ -1902,6 +1903,18 @@ void ScColumn::EndListening( SvtListener& rLst, SCROW nRow )
maBroadcasters.set_empty(nRow, nRow);
}
void ScColumn::EndListening( sc::EndListeningContext& rCxt, SCROW nRow, SvtListener& rListener )
{
SvtBroadcaster* pBC = GetBroadcaster(nRow);
if (!pBC)
return;
rListener.EndListening(*pBC);
if (!pBC->HasListeners())
// There is no more listeners for this cell. Add it to the purge list for later purging.
rCxt.addEmptyBroadcasterPosition(nCol, nRow, nTab);
}
void ScColumn::CompileDBFormula()
{
if ( !maItems.empty() )

View file

@ -36,6 +36,7 @@
#include "colorscale.hxx"
#include "sheetevents.hxx"
#include "tokenarray.hxx"
#include "listenercontext.hxx"
#include <tools/shl.hxx>
@ -200,14 +201,26 @@ void ScDocument::EndListeningCell( const ScAddress& rAddress,
maTabs[nTab]->EndListening( rAddress, pListener );
}
void ScDocument::EndListeningCell(
sc::EndListeningContext& rCxt, const ScAddress& rPos, SvtListener& rListener )
{
if (!TableExists(rPos.Tab()))
return;
maTabs[rPos.Tab()]->EndListening(rCxt, rPos.Col(), rPos.Row(), rListener);
}
void ScDocument::EndListeningFormulaCells( std::vector<ScFormulaCell*>& rCells )
{
if (rCells.empty())
return;
sc::EndListeningContext aCxt(*this);
std::vector<ScFormulaCell*>::iterator it = rCells.begin(), itEnd = rCells.end();
for (; it != itEnd; ++it)
(*it)->EndListeningTo(this);
(*it)->EndListeningTo(aCxt);
aCxt.purgeEmptyBroadcasters();
}
void ScDocument::PutInFormulaTree( ScFormulaCell* pCell )

View file

@ -44,6 +44,7 @@
#include "svl/intitem.hxx"
#include "rtl/strbuf.hxx"
#include "formulagroup.hxx"
#include "listenercontext.hxx"
#include <boost/bind.hpp>
@ -3329,4 +3330,62 @@ void ScFormulaCell::EndListeningTo( ScDocument* pDoc, ScTokenArray* pArr,
}
}
void ScFormulaCell::EndListeningTo( sc::EndListeningContext& rCxt )
{
if (rCxt.getDoc().IsClipOrUndo() || IsInChangeTrack())
return;
ScDocument& rDoc = rCxt.getDoc();
rDoc.SetDetectiveDirty(true); // It has changed something
if (pCode->IsRecalcModeAlways())
{
rDoc.EndListeningArea(BCA_LISTEN_ALWAYS, this);
return;
}
pCode->Reset();
ScToken* t;
while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceRPN()) ) != NULL )
{
StackVar eType = t->GetType();
ScSingleRefData& rRef1 = t->GetSingleRef();
ScSingleRefData& rRef2 = (eType == svDoubleRef ? t->GetDoubleRef().Ref2 : rRef1);
switch (eType)
{
case svSingleRef:
{
ScAddress aCell = rRef1.toAbs(aPos);
if (aCell.IsValid())
rDoc.EndListeningCell(rCxt, aCell, *this);
}
break;
case svDoubleRef:
{
ScAddress aCell1 = rRef1.toAbs(aPos);
ScAddress aCell2 = rRef2.toAbs(aPos);
if (aCell1.IsValid() && aCell2.IsValid())
{
if (t->GetOpCode() == ocColRowNameAuto)
{ // automagically
if ( rRef1.IsColRel() )
{ // ColName
aCell2.SetRow(MAXROW);
}
else
{ // RowName
aCell2.SetCol(MAXCOL);
}
}
rDoc.EndListeningArea(ScRange(aCell1, aCell2), this);
}
}
break;
default:
; // nothing
}
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "listenercontext.hxx"
#include "document.hxx"
namespace sc {
EndListeningContext::EndListeningContext(ScDocument& rDoc) : mrDoc(rDoc) {}
ScDocument& EndListeningContext::getDoc()
{
return mrDoc;
}
void EndListeningContext::addEmptyBroadcasterPosition(SCCOL nCol, SCROW nRow, SCTAB nTab)
{
}
void EndListeningContext::purgeEmptyBroadcasters()
{
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -1097,6 +1097,14 @@ void ScTable::EndListening( const ScAddress& rAddress, SvtListener* pListener )
aCol[rAddress.Col()].EndListening( *pListener, rAddress.Row() );
}
void ScTable::EndListening( sc::EndListeningContext& rCxt, SCCOL nCol, SCROW nRow, SvtListener& rListener )
{
if (!ValidCol(nCol))
return;
aCol[nCol].EndListening(rCxt, nRow, rListener);
}
void ScTable::SetPageStyle( const OUString& rName )
{
if ( aPageStyle != rName )

View file

@ -27,6 +27,17 @@ void ScSingleRefData::CalcRelFromAbs( const ScAddress& rPos )
nRelTab = nTab - rPos.Tab();
}
ScAddress ScSingleRefData::toAbs( const ScAddress& rPos ) const
{
SCCOL nRetCol = Flags.bColRel ? nRelCol + rPos.Col() : nCol;
SCROW nRetRow = Flags.bRowRel ? nRelRow + rPos.Row() : nRow;
SCTAB nRetTab = Flags.bTabRel ? nRelTab + rPos.Tab() : nTab;
if (!ValidCol(nRetCol) || !ValidRow(nRetRow) || !ValidTab(nRetTab))
return ScAddress(ScAddress::INITIALIZE_INVALID);
return ScAddress(nRetCol, nRetRow, nRetTab);
}
void ScSingleRefData::SmartRelAbs( const ScAddress& rPos )
{