[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