diff options
author | Jan Holesovsky <kendy@collabora.com> | 2013-12-21 20:51:29 +0100 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2013-12-21 20:55:44 +0100 |
commit | df9883411a5423793ad411ac05d7a28c355209aa (patch) | |
tree | d78ff591cb6128a35228b119eda939953bf1091e | |
parent | d358c377718f981d615b5ba2c6c5137dd150d2f0 (diff) |
Make the broadcasting work even when about to destruct.
Change-Id: Idba9302e1ec5234d3d472cda047c09ba52afd328
-rw-r--r-- | include/svl/broadcast.hxx | 1 | ||||
-rw-r--r-- | svl/source/notify/broadcast.cxx | 93 |
2 files changed, 48 insertions, 46 deletions
diff --git a/include/svl/broadcast.hxx b/include/svl/broadcast.hxx index 72ac3036cd28..a77ebdbc2819 100644 --- a/include/svl/broadcast.hxx +++ b/include/svl/broadcast.hxx @@ -82,6 +82,7 @@ private: bool mbAboutToDie:1; bool mbDisposing:1; bool mbNormalized:1; + bool mbDestNormalized:1; }; diff --git a/svl/source/notify/broadcast.cxx b/svl/source/notify/broadcast.cxx index 50d68a98d066..8d3905a2480b 100644 --- a/svl/source/notify/broadcast.cxx +++ b/svl/source/notify/broadcast.cxx @@ -21,44 +21,23 @@ #include <svl/listener.hxx> #include <svl/smplhint.hxx> -namespace { - -class StartListeningHandler : std::unary_function<SvtListener*, void> +void SvtBroadcaster::Normalize() { - SvtBroadcaster& mrBC; -public: - StartListeningHandler( SvtBroadcaster& rBC ) : mrBC(rBC) {} - - void operator() ( SvtListener* p ) + if (!mbNormalized) { - p->StartListening(mrBC); + std::sort(maListeners.begin(), maListeners.end()); + ListenersType::iterator itUniqueEnd = std::unique(maListeners.begin(), maListeners.end()); + maListeners.erase(itUniqueEnd, maListeners.end()); + mbNormalized = true; } -}; - -class NotifyHandler : std::unary_function<SvtListener*, void> -{ - SvtBroadcaster& mrBC; - const SfxHint& mrHint; -public: - NotifyHandler( SvtBroadcaster& rBC, const SfxHint& rHint ) : mrBC(rBC), mrHint(rHint) {} - void operator() ( SvtListener* p ) + if (!mbDestNormalized) { - p->Notify(mrBC, mrHint); + std::sort(maDestructedListeners.begin(), maDestructedListeners.end()); + ListenersType::iterator itUniqueEnd = std::unique(maDestructedListeners.begin(), maDestructedListeners.end()); + maDestructedListeners.erase(itUniqueEnd, maDestructedListeners.end()); + mbDestNormalized = true; } -}; - -} - -void SvtBroadcaster::Normalize() -{ - if (mbNormalized) - return; - - std::sort(maListeners.begin(), maListeners.end()); - ListenersType::iterator itUniqueEnd = std::unique(maListeners.begin(), maListeners.end()); - maListeners.erase(itUniqueEnd, maListeners.end()); - mbNormalized = true; } void SvtBroadcaster::Add( SvtListener* p ) @@ -75,6 +54,7 @@ void SvtBroadcaster::Remove( SvtListener* p ) if (mbAboutToDie) { maDestructedListeners.push_back(p); + mbDestNormalized = false; return; } @@ -88,12 +68,33 @@ void SvtBroadcaster::Remove( SvtListener* p ) ListenersGone(); } -SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbDisposing(false), mbNormalized(false) {} +SvtBroadcaster::SvtBroadcaster() : mbAboutToDie(false), mbDisposing(false), mbNormalized(false), mbDestNormalized(false) {} SvtBroadcaster::SvtBroadcaster( const SvtBroadcaster &rBC ) : - maListeners(rBC.maListeners), mbAboutToDie(false), mbDisposing(false), mbNormalized(rBC.mbNormalized) + maListeners(rBC.maListeners), maDestructedListeners(rBC.maDestructedListeners), + mbAboutToDie(rBC.mbAboutToDie), mbDisposing(false), + mbNormalized(rBC.mbNormalized), mbDestNormalized(rBC.mbDestNormalized) { - std::for_each(maListeners.begin(), maListeners.end(), StartListeningHandler(*this)); + if (mbAboutToDie) + Normalize(); + + ListenersType::iterator dest(maDestructedListeners.begin()); + for (ListenersType::iterator it(maListeners.begin()); it < maListeners.end(); ++it) + { + bool bStart = true; + + if (mbAboutToDie) + { + // skip the destructed ones + while (dest != maDestructedListeners.end() && (*dest < *it)) + ++dest; + + bStart = (dest == maDestructedListeners.end() || *dest != *it); + } + + if (bStart) + (*it)->StartListening(*this); + } } SvtBroadcaster::~SvtBroadcaster() @@ -101,12 +102,6 @@ SvtBroadcaster::~SvtBroadcaster() mbDisposing = true; Broadcast( SfxSimpleHint(SFX_HINT_DYING) ); - // 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 @@ -126,12 +121,18 @@ 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)); + + 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)->Notify(*this, rHint); + } } void SvtBroadcaster::ListenersGone() {} |