[Libreoffice-commits] core.git: svl/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Tue Oct 2 10:30:13 UTC 2018
svl/source/notify/broadcast.cxx | 72 ++++++++++++++++++++++------------------
1 file changed, 40 insertions(+), 32 deletions(-)
New commits:
commit 4a290888580474f9542f185091bb2a6fcf4e9a53
Author: Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Mon Oct 1 14:31:00 2018 +0200
Commit: Noel Grandin <noel.grandin at collabora.co.uk>
CommitDate: Tue Oct 2 12:29:51 2018 +0200
SvtBroadcaster unify the normal and PrepareForDestruction paths
since this approach is better in that it avoids O(n^2) behaviour
of lots of listeners deleting from a std::vector, lets just
always use this approach.
Change-Id: I9204996ee8c9379ac71dfc168a6c1fc653e63a8e
Reviewed-on: https://gerrit.libreoffice.org/61204
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 626a48a332e9..7e67de0bcdf1 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -40,9 +40,8 @@ void SvtBroadcaster::Normalize() const
void SvtBroadcaster::Add( SvtListener* p )
{
- assert(!mbDisposing && "called inside my own destructor?");
- assert(!mbAboutToDie && "called after PrepareForDestruction()?");
- if (mbDisposing || mbAboutToDie)
+ assert(!mbAboutToDie && "called inside my own destructor / after PrepareForDestruction()?");
+ if (mbAboutToDie)
return;
// only reset mbNormalized if we are going to become unsorted
if (!maListeners.empty() && maListeners.back() > p)
@@ -52,13 +51,12 @@ void SvtBroadcaster::Add( SvtListener* p )
void SvtBroadcaster::Remove( SvtListener* p )
{
- if (mbDisposing)
- return;
-
if (mbAboutToDie)
{
+ // only reset mbDestNormalized if we are going to become unsorted
+ if (!maDestructedListeners.empty() && maDestructedListeners.back() > p)
+ mbDestNormalized = false;
maDestructedListeners.push_back(p);
- mbDestNormalized = false;
return;
}
@@ -75,14 +73,13 @@ void SvtBroadcaster::Remove( SvtListener* p )
ListenersGone();
}
-SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbDisposing(false), mbNormalized(true), mbDestNormalized(true) {}
+SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbNormalized(true), mbDestNormalized(true) {}
SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
- mbAboutToDie(false), mbDisposing(false),
+ mbAboutToDie(false),
mbNormalized(true), mbDestNormalized(true)
{
- assert(!rBC.mbAboutToDie && "copying an object marked with PrepareForDestruction()?");
- assert(!rBC.mbDisposing && "copying an object that is in it's destructor?");
+ assert(!rBC.mbAboutToDie && "copying an object marked with PrepareForDestruction() / that is in it's destructor?");
rBC.Normalize(); // so that insert into ourself is in-order, and therefore we do not need to Normalize()
maListeners.reserve(rBC.maListeners.size());
@@ -92,41 +89,52 @@ SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) :
SvtBroadcaster::~SvtBroadcaster()
{
- mbDisposing = true;
- Broadcast( SfxHint(SfxHintId::Dying) );
+ PrepareForDestruction();
+
+ Normalize();
+
+ {
+ SfxHint aHint(SfxHintId::Dying);
+ ListenersType::const_iterator dest(maDestructedListeners.begin());
+ for (ListenersType::iterator it(maListeners.begin()); it != maListeners.end(); ++it)
+ {
+ // skip the destructed ones
+ while (dest != maDestructedListeners.end() && (*dest < *it))
+ ++dest;
+
+ if (dest == maDestructedListeners.end() || *dest != *it)
+ (*it)->Notify(aHint);
+ }
+ }
Normalize();
// now when both lists are sorted, we can linearly unregister all
// listeners, with the exception of those that already asked to be removed
// during their own destruction
- ListenersType::const_iterator dest(maDestructedListeners.begin());
- for (ListenersType::iterator it(maListeners.begin()); it != maListeners.end(); ++it)
{
- // skip the destructed ones
- while (dest != maDestructedListeners.end() && (*dest < *it))
- ++dest;
-
- if (dest == maDestructedListeners.end() || *dest != *it)
- (*it)->BroadcasterDying(*this);
+ ListenersType::const_iterator dest(maDestructedListeners.begin());
+ for (ListenersType::iterator it(maListeners.begin()); it != maListeners.end(); ++it)
+ {
+ // skip the destructed ones
+ while (dest != maDestructedListeners.end() && (*dest < *it))
+ ++dest;
+
+ if (dest == maDestructedListeners.end() || *dest != *it)
+ (*it)->BroadcasterDying(*this);
+ }
}
}
void SvtBroadcaster::Broadcast( const SfxHint &rHint )
{
- Normalize();
+ assert(!mbAboutToDie && "broadcasting after PrepareForDestruction() / from inside my own destructor?");
+ if (mbAboutToDie)
+ return;
- ListenersType::const_iterator dest(maDestructedListeners.begin());
ListenersType aListeners(maListeners); // this copy is important to avoid erasing entries while iterating
- for (ListenersType::iterator it(aListeners.begin()); it != aListeners.end(); ++it)
- {
- // skip the destructed ones
- while (dest != maDestructedListeners.end() && (*dest < *it))
- ++dest;
-
- if (dest == maDestructedListeners.end() || *dest != *it)
- (*it)->Notify(rHint);
- }
+ for (SvtListener * p : aListeners)
+ p->Notify(rHint);
}
void SvtBroadcaster::ListenersGone() {}
More information about the Libreoffice-commits
mailing list