[libsigcplusplus/variadic_mem_fun3: 105/148] signal_base: clear signal_impl in its own destructor.



commit 7373b6fbfdbc2072f5bbc85f3eebe28747ce1367
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Mar 3 13:46:09 2016 +0100

    signal_base: clear signal_impl in its own destructor.
    
    This deals with some TODO comments.
    This patch is based on a suggestion from Kjell Ahlstedt:
    See https://bugzilla.gnome.org/show_bug.cgi?id=167714#c14

 sigc++/signal_base.cc |   29 ++++++++++++++---------------
 sigc++/signal_base.h  |    1 +
 2 files changed, 15 insertions(+), 15 deletions(-)
---
diff --git a/sigc++/signal_base.cc b/sigc++/signal_base.cc
index bbb1955..1bf12c4 100644
--- a/sigc++/signal_base.cc
+++ b/sigc++/signal_base.cc
@@ -37,6 +37,19 @@ signal_impl::signal_impl()
 : ref_count_(0), exec_count_(0), deferred_(false)
 {}
 
+signal_impl::~signal_impl()
+{
+  // unreference() must not call ~signal_impl() while clear() is executing.
+  ++ref_count_;
+
+  // Disconnect all slots before *this is deleted.
+  clear();
+
+  // Now ref_count_ can be cleared again (not really necessary), but don't do it
+  // with a call to unreference(). That would invoke ~signal_impl() recursively.
+  --ref_count_;
+}
+
 // only MSVC needs this to guarantee that all new/delete are executed from the DLL module
 #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY
 void* signal_impl::operator new(size_t size_)
@@ -191,11 +204,6 @@ signal_base::~signal_base()
 {
   if (impl_)
   {
-    // Disconnect all slots before impl_ is deleted.
-    // TODO: Move the signal_impl::clear() call to ~signal_impl() when ABI can be broken.
-    if (impl_->ref_count_ == 1)
-      impl_->clear();
-
     impl_->unreference();
   }
 }
@@ -259,13 +267,9 @@ signal_base& signal_base::operator=(const signal_base& src)
 
   if (impl_)
   {
-    // Disconnect all slots before impl_ is deleted.
-    // TODO: Move the signal_impl::clear() call to ~signal_impl() when ABI can be broken.
-    if (impl_->ref_count_ == 1)
-      impl_->clear();
-
     impl_->unreference();
   }
+
   impl_ = src.impl();
   impl_->reference();
   return *this;
@@ -277,11 +281,6 @@ signal_base& signal_base::operator=(signal_base&& src)
 
   if (impl_)
   {
-    // Disconnect all slots before impl_ is deleted.
-    // TODO: Move the signal_impl::clear() call to ~signal_impl() when ABI can be broken.
-    if (impl_->ref_count_ == 1)
-      impl_->clear();
-
     impl_->unreference();
   }
 
diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h
index 94037ca..d19a341 100644
--- a/sigc++/signal_base.h
+++ b/sigc++/signal_base.h
@@ -50,6 +50,7 @@ struct SIGC_API signal_impl : public notifiable
   typedef slot_list::const_iterator const_iterator_type;
 
   signal_impl();
+  ~signal_impl();
 
   signal_impl(const signal_impl& src) = delete;
   signal_impl& operator=(const signal_impl& src) = delete;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]