? patch
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/libsigc++2/ChangeLog,v
retrieving revision 1.177
diff -u -p -r1.177 ChangeLog
--- ChangeLog	11 Feb 2005 19:45:20 -0000	1.177
+++ ChangeLog	17 Feb 2005 16:43:00 -0000
@@ -1,3 +1,10 @@
+2005-02-17  Neal E. Coombes  <nealc@trdlnk.com>
+	
+	* sigc++/signal_base.cc: Fix performance leak in signal_impl::notify
+	by keeping track of the relevant iterator.  Performance change from
+	O(n) to O(1) in likely the majority of calls to notify.
+	See bug #167714.
+
 2005-02-11  Martin Schulze  <mschulze@cvs.gnome.org>
 
 	* docs/manual/Makefile.am: Set the correct group in post-html.
Index: sigc++/signal_base.cc
===================================================================
RCS file: /cvs/gnome/libsigc++2/sigc++/signal_base.cc,v
retrieving revision 1.5
diff -u -p -r1.5 signal_base.cc
--- sigc++/signal_base.cc	18 Jan 2005 16:59:15 -0000	1.5
+++ sigc++/signal_base.cc	17 Feb 2005 16:43:01 -0000
@@ -58,16 +58,26 @@ signal_impl::iterator_type signal_impl::
 {
   return slots_.erase(i);
 }
-    
+
+struct self_and_iter
+{
+  signal_impl *self;
+  signal_impl::iterator_type iter;
+  self_and_iter(signal_impl *impl, signal_impl::iterator_type i)
+    : self(impl), iter(i) {}
+};
+
 signal_impl::iterator_type signal_impl::insert(signal_impl::iterator_type i, const slot_base& slot_)
 {
   iterator_type temp = slots_.insert(i, slot_);
-  temp->set_parent(this, &notify);
+  self_and_iter *si = new self_and_iter(this, temp);
+  temp->set_parent(si, &notify);
   return temp;
 }
 
 void signal_impl::sweep()
 {
+  deferred_ = false;
   iterator_type i = slots_.begin();
   while (i != slots_.end())
     if ((*i).empty())
@@ -78,12 +88,17 @@ void signal_impl::sweep()
 
 void* signal_impl::notify(void* d)
 {
-  signal_impl* self = reinterpret_cast<signal_impl*>(d);
-  if (self->exec_count_ == 0)
-    self->sweep();
+  self_and_iter *si = static_cast<self_and_iter *>(d);
+  signal_impl* self = si->self;
+  signal_impl::iterator_type i = si->iter;
+  if (self->exec_count_ == 0) {
+    assert((*i).empty());
+    self->erase(i);
+  }
   else                       // This is occuring during signal emission.
     self->deferred_ = true;  // => sweep() will be called from ~signal_exec().
-  return 0;                  // This is safer because we don't have to care about our iterators in emit().
+  delete si;                  // This is safer because we don't have to care about our iterators in emit().
+  return 0;
 }
 
 } /* namespace internal */
