[Libreoffice-commits] core.git: include/svl sc/inc sc/source svl/source
Jan Holesovsky
kendy at collabora.com
Fri Dec 20 17:07:55 PST 2013
include/svl/broadcast.hxx | 13 +++++++++++++
sc/inc/column.hxx | 1 +
sc/source/core/data/column2.cxx | 15 +++++++++++++++
sc/source/core/data/table1.cxx | 3 +++
svl/source/notify/broadcast.cxx | 9 ++++++---
5 files changed, 38 insertions(+), 3 deletions(-)
New commits:
commit efb30219a1113ee08bf26160a08b4f721a514fdf
Author: Jan Holesovsky <kendy at collabora.com>
Date: Sat Dec 21 01:41:18 2013 +0100
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
diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx
index 6a6bc03..d122e02 100644
--- a/include/svl/broadcast.hxx
+++ b/include/svl/broadcast.hxx
@@ -60,8 +60,21 @@ public:
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:
ListenersType maListeners;
+ bool mbAboutToDie:1;
bool mbDisposing:1;
bool mbNormalized:1;
};
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 55b3847..b7f48db 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -491,6 +491,7 @@ public:
SvtBroadcaster* GetBroadcaster( SCROW nRow );
const SvtBroadcaster* GetBroadcaster( SCROW nRow ) const;
void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, SCROW nRow2 );
+ void PrepareBroadcastersForDestruction();
bool HasBroadcaster() const;
void Broadcast( SCROW nRow );
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 307d42b..2092406b 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1962,6 +1962,21 @@ void ScColumn::DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCROW nRo
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
{
sc::BroadcasterStoreType::const_iterator it = maBroadcasters.begin(), itEnd = maBroadcasters.end();
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 4eed3b0..37417ac 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -341,6 +341,9 @@ ScTable::~ScTable()
delete mpRangeName;
delete pDBDataNoName;
DestroySortCollator();
+
+ for (SCCOL k=0; k<=MAXCOL; k++)
+ aCol[k].PrepareBroadcastersForDestruction();
}
void ScTable::GetName( OUString& rName ) const
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 24b5790..3575c7f 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -81,7 +81,7 @@ void SvtBroadcaster::Add( SvtListener* p )
void SvtBroadcaster::Remove( SvtListener* p )
{
- if (mbDisposing)
+ if (mbAboutToDie || mbDisposing)
return;
Normalize();
@@ -94,10 +94,10 @@ void SvtBroadcaster::Remove( SvtListener* p )
ListenersGone();
}
-SvtBroadcaster::SvtBroadcaster() : mbDisposing(false), mbNormalized(false) {}
+SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbDisposing(false), mbNormalized(false) {}
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));
}
@@ -113,6 +113,9 @@ SvtBroadcaster::~SvtBroadcaster()
void SvtBroadcaster::Broadcast( const SfxHint &rHint )
{
+ if (mbAboutToDie)
+ return;
+
Normalize();
ListenersType listeners(maListeners);
std::for_each(listeners.begin(), listeners.end(), NotifyHandler(*this, rHint));
More information about the Libreoffice-commits
mailing list