[Libreoffice-commits] core.git: include/svl svl/source
Jan Holesovsky
kendy at collabora.com
Sat Dec 21 08:29:53 PST 2013
include/svl/broadcast.hxx | 7 ++++-
svl/source/notify/broadcast.cxx | 49 +++++++++++++++++++++++++++-------------
2 files changed, 40 insertions(+), 16 deletions(-)
New commits:
commit c8b624329caed68550fcb1fe197c8fa8107d079b
Author: Jan Holesovsky <kendy at collabora.com>
Date: Sat Dec 21 17:26:01 2013 +0100
Don't call EndListening() on already destructed listeners.
Change-Id: I9bda35f2246de9d37077dda33c710b89ee008e5a
diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx
index d122e02..72ac303 100644
--- a/include/svl/broadcast.hxx
+++ b/include/svl/broadcast.hxx
@@ -70,10 +70,15 @@ public:
* themselves from the broadcaster - the broadcaster will not broadcast
* anything after the PrepareForDesctruction() call anyway.
*/
- void PrepareForDestruction() { mbAboutToDie = true; }
+ void PrepareForDestruction();
private:
ListenersType maListeners;
+
+ /// When the broadcaster is about to die, collect listeners that asked for removal.
+ ListenersType maDestructedListeners;
+
+ /// Indicate that this broadcaster will be destructed (we indicate this on all ScColumn's broadcasters during the ScTable destruction, eg.)
bool mbAboutToDie:1;
bool mbDisposing:1;
bool mbNormalized:1;
diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx
index 3575c7f..50d68a9 100644
--- a/svl/source/notify/broadcast.cxx
+++ b/svl/source/notify/broadcast.cxx
@@ -35,18 +35,6 @@ public:
}
};
-class EndListeningHandler : std::unary_function<SvtListener*, void>
-{
- SvtBroadcaster& mrBC;
-public:
- EndListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {}
-
- void operator() ( SvtListener* p )
- {
- p->EndListening(mrBC);
- }
-};
-
class NotifyHandler : std::unary_function<SvtListener*, void>
{
SvtBroadcaster& mrBC;
@@ -81,9 +69,15 @@ void SvtBroadcaster::Add( SvtListener* p )
void SvtBroadcaster::Remove( SvtListener* p )
{
- if (mbAboutToDie || mbDisposing)
+ if (mbDisposing)
return;
+ if (mbAboutToDie)
+ {
+ maDestructedListeners.push_back(p);
+ return;
+ }
+
Normalize();
std::pair<ListenersType::iterator,ListenersType::iterator> r =
std::equal_range(maListeners.begin(), maListeners.end(), p);
@@ -107,8 +101,27 @@ SvtBroadcaster::~SvtBroadcaster()
mbDisposing = true;
Broadcast( SfxSimpleHint(SFX_HINT_DYING) );
- // unregister all listeners.
- std::for_each(maListeners.begin(), maListeners.end(), EndListeningHandler(*this));
+ // normalize the list of listeners than already asked for destruction
+ std::sort(maDestructedListeners.begin(), maDestructedListeners.end());
+ ListenersType::iterator itUniqueEnd = std::unique(maDestructedListeners.begin(), maDestructedListeners.end());
+ maDestructedListeners.erase(itUniqueEnd, maDestructedListeners.end());
+
+ // and the list of registered listeners too
+ 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::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)->EndListening(*this);
+ }
}
void SvtBroadcaster::Broadcast( const SfxHint &rHint )
@@ -133,4 +146,10 @@ bool SvtBroadcaster::HasListeners() const
return !maListeners.empty();
}
+void SvtBroadcaster::PrepareForDestruction()
+{
+ mbAboutToDie = true;
+ maDestructedListeners.reserve(maListeners.size());
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list