Kaydet (Commit) efb30219 authored tarafından Jan Holesovsky's avatar Jan Holesovsky

Speedup destruction of sheets with too many listeners & broadcasters.

Listeners and broadcasters are M:N relationship.  If you want to
destruct them, you easily end up in O(M*N) situation; where for every
listener, you iterate all broadcasters, to remove that one listener.

To avoid that, announce to the broadcasters that they are going to die, and the
listeners do not have to bother with removing themselves from the broadcaster.
The broadcaster will not broadcast anything after the PrepareForDesctruction()
call anyway.

Change-Id: I68d78b23e73bcbb944de9139448b2c20dfa14f62
üst 0d5d01a4
...@@ -60,8 +60,21 @@ public: ...@@ -60,8 +60,21 @@ public:
bool HasListeners() const; bool HasListeners() const;
/**
* Listeners and broadcasters are M:N relationship. If you want to
* destruct them, you easily end up in O(M*N) situation; where for every
* listener, you iterate all broadcasters, to remove that one listener.
*
* To avoid that, use this call to announce to the broadcaster it is going
* to die, and the listeners do not have to bother with removing
* themselves from the broadcaster - the broadcaster will not broadcast
* anything after the PrepareForDesctruction() call anyway.
*/
void PrepareForDestruction() { mbAboutToDie = true; }
private: private:
ListenersType maListeners; ListenersType maListeners;
bool mbAboutToDie:1;
bool mbDisposing:1; bool mbDisposing:1;
bool mbNormalized:1; bool mbNormalized:1;
}; };
......
...@@ -491,6 +491,7 @@ public: ...@@ -491,6 +491,7 @@ public:
SvtBroadcaster* GetBroadcaster( SCROW nRow ); SvtBroadcaster* GetBroadcaster( SCROW nRow );
const SvtBroadcaster* GetBroadcaster( SCROW nRow ) const; const SvtBroadcaster* GetBroadcaster( SCROW nRow ) const;
void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 ); void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 );
void PrepareBroadcastersForDestruction();
bool HasBroadcaster() const; bool HasBroadcaster() const;
void Broadcast( SCROW nRow ); void Broadcast( SCROW nRow );
......
...@@ -1962,6 +1962,21 @@ void ScColumn::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRo ...@@ -1962,6 +1962,21 @@ void ScColumn::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRo
maBroadcasters.set_empty(rBlockPos.miBroadcasterPos, nRow1, nRow2); maBroadcasters.set_empty(rBlockPos.miBroadcasterPos, nRow1, nRow2);
} }
void ScColumn::PrepareBroadcastersForDestruction()
{
sc::BroadcasterStoreType::iterator itPos = maBroadcasters.begin(), itPosEnd = maBroadcasters.end();
for (; itPos != itPosEnd; ++itPos)
{
if (itPos->type == sc::element_type_broadcaster)
{
sc::broadcaster_block::iterator it = sc::broadcaster_block::begin(*itPos->data);
sc::broadcaster_block::iterator itEnd = sc::broadcaster_block::end(*itPos->data);
for (; it != itEnd; ++it)
(*it)->PrepareForDestruction();
}
}
}
bool ScColumn::HasBroadcaster() const bool ScColumn::HasBroadcaster() const
{ {
sc::BroadcasterStoreType::const_iterator it = maBroadcasters.begin(), itEnd = maBroadcasters.end(); sc::BroadcasterStoreType::const_iterator it = maBroadcasters.begin(), itEnd = maBroadcasters.end();
......
...@@ -341,6 +341,9 @@ ScTable::~ScTable() ...@@ -341,6 +341,9 @@ ScTable::~ScTable()
delete mpRangeName; delete mpRangeName;
delete pDBDataNoName; delete pDBDataNoName;
DestroySortCollator(); DestroySortCollator();
for (SCCOL k=0; k<=MAXCOL; k++)
aCol[k].PrepareBroadcastersForDestruction();
} }
void ScTable::GetName( OUString& rName ) const void ScTable::GetName( OUString& rName ) const
......
...@@ -81,7 +81,7 @@ void SvtBroadcaster::Add( SvtListener* p ) ...@@ -81,7 +81,7 @@ void SvtBroadcaster::Add( SvtListener* p )
void SvtBroadcaster::Remove( SvtListener* p ) void SvtBroadcaster::Remove( SvtListener* p )
{ {
if (mbDisposing) if (mbAboutToDie || mbDisposing)
return; return;
Normalize(); Normalize();
...@@ -94,10 +94,10 @@ void SvtBroadcaster::Remove( SvtListener* p ) ...@@ -94,10 +94,10 @@ void SvtBroadcaster::Remove( SvtListener* p )
ListenersGone(); ListenersGone();
} }
SvtBroadcaster::SvtBroadcaster() : mbDisposing(false), mbNormalized(false) {} SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbDisposing(false), mbNormalized(false) {}
SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) : SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
maListeners(rBC.maListeners), mbDisposing(false), mbNormalized(rBC.mbNormalized) maListeners(rBC.maListeners), mbAboutToDie(false), mbDisposing(false), mbNormalized(rBC.mbNormalized)
{ {
std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this)); std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this));
} }
...@@ -113,6 +113,9 @@ SvtBroadcaster::~SvtBroadcaster() ...@@ -113,6 +113,9 @@ SvtBroadcaster::~SvtBroadcaster()
void SvtBroadcaster::Broadcast( const SfxHint &rHint ) void SvtBroadcaster::Broadcast( const SfxHint &rHint )
{ {
if (mbAboutToDie)
return;
Normalize(); Normalize();
ListenersType listeners(maListeners); ListenersType listeners(maListeners);
std::for_each(listeners.begin(), listeners.end(), NotifyHandler(*this, rHint)); std::for_each(listeners.begin(), listeners.end(), NotifyHandler(*this, rHint));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment