*** ChangeLog	23 Jan 2003 23:46:32 -0000	1.755
--- ChangeLog	24 Jan 2003 16:16:52 -0000
@@ -1,3 +1,42 @@
+2003-01-24  Michael Johnson  <michaelj@maine.rr.com>
+
+	* glib/glibmm/refptr.h: Change to be compatible with SigC::Object
+	reference counting behavior. Add some operators to make RefPtr
+	behave more like a pointer. In summary, make RefPtr a general
+	purpose smart pointer.
+	* glib/glibmm/objectbase.{cc,h}: Change the implementation of
+	reference counting to be compatible with changed RefPtr behavior,
+	by using the SigC::Object reference counting mechanism and
+	masking the underlying (and incompatible) GLib reference counting
+	implementation.
+	* glib/glibmm/object.cc: Minor change for compatibility with
+	Glib::ObjectBase changes.
+	* glib/glibmm/main.{cc,h}: Change the implementation of reference
+	counting in MainContext, MainLoop and Source to be compatible with
+	changed RefPtr behavior.
+	* glib/glibmm/quark.{cc,h}: Move quarks that are only used by
+	Glib::ObjectBase into objectbase.
+	* glib/glibmm/wrap.cc: Remove knowledge of Glib::ObjectBase internals
+	which are now private and use public methods instead.
+	* glib/src/iochannel.{ccg,hg}: Change the implementation of
+	reference counting in IOChannel to be compatible with changed
+	RefPtr behavior.
+	* gtk/gtkmm/menu_elems.cc: Go back to using the RefPtr constructor
+	in the construction list (avoid the extra copy) and don't bother
+	with the extra reference, it's not necessary anymore.
+	* gtk/src/container.ccg: Changes for compatibility with
+	Glib::ObjectBase changes.
+	* gtk/src/object.{ccg,hg}: Changes for compatibility with
+	Glib::ObjectBase changes.
+	* gtk/src/widget.ccg: Changes for compatibility with
+	Glib::ObjectBase changes.
+	* gtk/src/window.{ccg,hg}: Changes for compatibility with
+	Glib::ObjectBase changes.
+	* tools/m4/class_gobject.m4: Change implementation of generated
+	gobj_copy() to be compatible with changed Glib::ObjectBase behavior,
+	make generated destructors of Glib::Object subclasses protected so
+	that programmers cannot delete them.
+
 2003-01-24  Murray Cumming  <murrayc@usa.net>
 
 	* gtk/gtkmm/menu_elems.cc: Element::Element(MenuItem): Use the


*** glib/glibmm/main.cc	27 Oct 2002 14:31:32 -0000	1.18
--- glib/glibmm/main.cc	24 Jan 2003 16:16:57 -0000
@@ -29,6 +29,9 @@
 
 GTKMM_USING_STD(min)
 
+// See Scott Meyers "Effective C++" item 21 for reasons why objects
+// returned from functions should be const:
+// http://www.awprofessional.com/content/images/0201924889/items/item21.html
 
 namespace
 {
@@ -116,16 +119,19 @@ struct SourceCallbackData
 
   static void destroy_notify_callback(void* data);
 
-  Glib::Source* wrapper;
+  Glib::RefPtr<Glib::Source> wrapper;
   SourceConnectionNode* node;
+  bool anchored;
 };
 
 inline
 SourceCallbackData::SourceCallbackData(Glib::Source* wrapper_)
 :
-  wrapper (wrapper_),
-  node    (0)
-{}
+  node    (0),
+  anchored(true)
+{
+  wrapper = wrapper_;
+}
 
 void SourceCallbackData::set_node(SourceConnectionNode* node_)
 {
@@ -142,9 +148,9 @@ void SourceCallbackData::destroy_notify_
 
   if(self->node)
     SourceConnectionNode::destroy_notify_callback(self->node);
-
   if(self->wrapper)
-    Glib::Source::destroy_notify_callback(self->wrapper);
+    Glib::Source::destroy_notify_callback(self->wrapper); // tell the wrapper goodbye
+  self->wrapper = 0; // release the last reference to the wrapper
 
   delete self;
 }
@@ -154,7 +160,8 @@ void SourceCallbackData::destroy_notify_
  */
 SourceCallbackData* glibmm_source_get_callback_data(GSource* source)
 {
-  g_return_val_if_fail(source->callback_funcs->get != 0, 0);
+  if (!(source && source->callback_funcs && source->callback_funcs->get))
+    return 0;
 
   GSourceFunc func;
   void* user_data = 0;
@@ -328,7 +335,7 @@ SignalIO::SignalIO(GMainContext* context
 SigC::Connection SignalIO::connect(const SigC::Slot1<bool,IOCondition>& slot,
                                    int fd, IOCondition condition, int priority)
 {
-  const Glib::RefPtr<IOSource> source = IOSource::create(fd, condition);
+  const Glib::RefPtr<IOSource>& source = IOSource::create(fd, condition);
 
   if(priority != G_PRIORITY_DEFAULT)
     source->set_priority(priority);
@@ -344,7 +351,7 @@ SigC::Connection SignalIO::connect(const
                                    const Glib::RefPtr<IOChannel>& channel,
                                    IOCondition condition, int priority)
 {
-  const Glib::RefPtr<IOSource> source = IOSource::create(channel, condition);
+  const Glib::RefPtr<IOSource>& source = IOSource::create(channel, condition);
 
   if(priority != G_PRIORITY_DEFAULT)
     source->set_priority(priority);
@@ -365,15 +372,21 @@ SignalIO signal_io()
 /**** Glib::MainContext ****************************************************/
 
 // static
-Glib::RefPtr<MainContext> MainContext::create()
+RefPtr<MainContext> MainContext::create()
 {
-  return Glib::RefPtr<MainContext>(reinterpret_cast<MainContext*>(g_main_context_new()));
+  // Because the RefPtr constructor obtains a reference to the MainContext, we
+  // do not need the initial reference that the GMainContext is created with.
+  // So we call unreference() to do away with the duplicate reference.
+
+  const RefPtr<MainContext> result(static_cast<MainContext*>(g_main_context_new()));
+  result->unreference();
+  return result;
 }
 
 // static
-Glib::RefPtr<MainContext> MainContext::get_default()
+RefPtr<MainContext> MainContext::get_default()
 {
-  return Glib::wrap(g_main_context_default(), true);
+  return wrap(g_main_context_default(), true);
 }
 
 bool MainContext::iteration(bool may_block)
@@ -484,51 +497,65 @@ SignalIO MainContext::signal_io()
 
 void MainContext::reference() const
 {
-  g_main_context_ref(reinterpret_cast<GMainContext*>(const_cast<MainContext*>(this)));
+  g_main_context_ref(const_cast<MainContext*>(this));
 }
 
 void MainContext::unreference() const
 {
-  g_main_context_unref(reinterpret_cast<GMainContext*>(const_cast<MainContext*>(this)));
+  g_main_context_unref(const_cast<MainContext*>(this));
 }
 
 GMainContext* MainContext::gobj()
 {
-  return reinterpret_cast<GMainContext*>(this);
+  return this;
 }
 
 const GMainContext* MainContext::gobj() const
 {
-  return reinterpret_cast<const GMainContext*>(this);
+  return this;
 }
 
 GMainContext* MainContext::gobj_copy() const
 {
   reference();
-  return const_cast<GMainContext*>(gobj());
+  return const_cast<MainContext*>(this);
 }
 
-Glib::RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy)
+RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy)
 {
-  if(take_copy && gobject)
-    g_main_context_ref(gobject);
+  // Because the RefPtr constructor obtains a reference to the MainContext, we
+  // do not need the initial reference that the GMainContext is created with.
+  // So we call unreference() to do away with the duplicate reference.
 
-  return Glib::RefPtr<MainContext>(reinterpret_cast<MainContext*>(gobject));
+  const RefPtr<MainContext> result(static_cast<MainContext*>(gobject));
+  if (result && !take_copy)
+    result->unreference();
+  return result;
 }
 
 
 /**** Glib::MainLoop *******************************************************/
 
-Glib::RefPtr<MainLoop> MainLoop::create(bool is_running)
+RefPtr<MainLoop> MainLoop::create(bool is_running)
 {
-  return Glib::RefPtr<MainLoop>(
-      reinterpret_cast<MainLoop*>(g_main_loop_new(0, is_running)));
+  // Because the RefPtr constructor obtains a reference to the MainLoop, we
+  // do not need the initial reference that the GMainLoop is created with. So
+  // we call unreference() to do away with the duplicate reference.
+
+  const RefPtr<MainLoop> result(static_cast<MainLoop*>(g_main_loop_new(0, is_running)));
+  result->unreference();
+  return result;
 }
 
-Glib::RefPtr<MainLoop> MainLoop::create(const Glib::RefPtr<MainContext>& context, bool is_running)
+RefPtr<MainLoop> MainLoop::create(const RefPtr<MainContext>& context, bool is_running)
 {
-  return Glib::RefPtr<MainLoop>(
-      reinterpret_cast<MainLoop*>(g_main_loop_new(Glib::unwrap(context), is_running)));
+  // Because the RefPtr constructor obtains a reference to the MainLoop, we
+  // do not need the initial reference that the GMainLoop is created with. So
+  // we call unreference() to do away with the duplicate reference.
+
+  const RefPtr<MainLoop> result(static_cast<MainLoop*>(g_main_loop_new(unwrap(context), is_running)));
+  result->unreference();
+  return result;
 }
 
 void MainLoop::run()
@@ -546,43 +573,47 @@ bool MainLoop::is_running()
   return g_main_loop_is_running(gobj());
 }
 
-Glib::RefPtr<MainContext> MainLoop::get_context()
+RefPtr<MainContext> MainLoop::get_context()
 {
-  return Glib::wrap(g_main_loop_get_context(gobj()), true);
+  return wrap(g_main_loop_get_context(gobj()), true);
 }
 
 void MainLoop::reference() const
 {
-  g_main_loop_ref(reinterpret_cast<GMainLoop*>(const_cast<MainLoop*>(this)));
+  g_main_loop_ref(const_cast<MainLoop*>(this));
 }
 
 void MainLoop::unreference() const
 {
-  g_main_loop_unref(reinterpret_cast<GMainLoop*>(const_cast<MainLoop*>(this)));
+  g_main_loop_unref(const_cast<MainLoop*>(this));
 }
 
 GMainLoop* MainLoop::gobj()
 {
-  return reinterpret_cast<GMainLoop*>(this);
+  return this;
 }
 
 const GMainLoop* MainLoop::gobj() const
 {
-  return reinterpret_cast<const GMainLoop*>(this);
+  return this;
 }
 
 GMainLoop* MainLoop::gobj_copy() const
 {
   reference();
-  return const_cast<GMainLoop*>(gobj());
+  return const_cast<MainLoop*>(this);
 }
 
-Glib::RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy)
+RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy)
 {
-  if(take_copy && gobject)
-    g_main_loop_ref(gobject);
+  // Because the RefPtr constructor obtains a reference to the MainLoop, we
+  // do not need the initial reference that the GMainLoop is created with. So
+  // we call unreference() to do away with the duplicate reference.
 
-  return Glib::RefPtr<MainLoop>(reinterpret_cast<MainLoop*>(gobject));
+  const RefPtr<MainLoop> result(static_cast<MainLoop*>(gobject));
+  if (result && !take_copy)
+    result->unreference();
+  return result;
 }
 
 
@@ -601,9 +632,9 @@ const GSourceFuncs Source::vfunc_table_ 
   0, // closure_marshal
 };
 
-unsigned int Source::attach(const Glib::RefPtr<MainContext>& context)
+unsigned int Source::attach(const RefPtr<MainContext>& context)
 {
-  return g_source_attach(gobject_, Glib::unwrap(context));
+  return g_source_attach(gobject_, unwrap(context));
 }
 
 unsigned int Source::attach()
@@ -641,9 +672,9 @@ unsigned int Source::get_id() const
   return g_source_get_id(gobject_);
 }
 
-Glib::RefPtr<MainContext> Source::get_context()
+RefPtr<MainContext> Source::get_context()
 {
-  return Glib::wrap(g_source_get_context(gobject_), true);
+  return wrap(g_source_get_context(gobject_), true);
 }
 
 GSource* Source::gobj_copy() const
@@ -651,20 +682,36 @@ GSource* Source::gobj_copy() const
   return g_source_ref(gobject_);
 }
 
+// override
 void Source::reference() const
 {
-  g_source_ref(gobject_);
+  SourceCallbackData *const data = glibmm_source_get_callback_data(gobject_);
+  if (data && data->anchored == false) {
+    g_source_ref(gobject_);
+    data->anchored = true;
+  }
+  SigC::Object::reference();
 }
 
+// override
 void Source::unreference() const
 {
-  g_source_unref(gobject_);
+  SourceCallbackData *const data = glibmm_source_get_callback_data(gobject_);
+
+  SigC::Object::unreference();
+
+  if (data && data->anchored && const_cast<Source*>(this)->control()->count_ == 1)
+  {
+    data->anchored = false;
+    g_source_unref(gobject_);
+  }
 }
 
 Source::Source()
 :
   gobject_ (g_source_new(const_cast<GSourceFuncs*>(&vfunc_table_), sizeof(GSource)))
 {
+  set_manage();
   g_source_set_callback(
       gobject_, &glibmm_dummy_source_callback,
       new SourceCallbackData(this), // our persistant callback data object
@@ -675,6 +722,7 @@ Source::Source(GSource* cast_item, GSour
 :
   gobject_ (cast_item)
 {
+  set_manage();
   g_source_set_callback(
       gobject_, callback_func,
       new SourceCallbackData(this), // our persistant callback data object
@@ -683,20 +731,13 @@ Source::Source(GSource* cast_item, GSour
 
 Source::~Source()
 {
-  // The dtor should be invoked by destroy_notify_callback() only, which clears
-  // gobject_ before deleting.  However, we might also get to this point if
-  // a derived ctor threw an exception, and then we need to unref manually.
-
-  if(gobject_)
-  {
-    SourceCallbackData *const data = glibmm_source_get_callback_data(gobject_);
-    data->wrapper = 0;
-
-    GSource *const tmp_gobject = gobject_;
-    gobject_ = 0;
-
-    g_source_unref(tmp_gobject);
-  }
+  // We'll never get here with a non-zero gobject_ because
+  // destroy_notify_callback clears gobject_ before the last reference to this
+  // is released. This destructor will never be invoked as a result of a
+  // derived class constructor throwing an exception, because C++ only calls
+  // the destructors of fully constructed objects. See Scott Meyers "More
+  // Effective C++" item 10 for more information:
+  // http://www.awprofessional.com/content/images/020163371x/items/item10.html
 }
 
 SigC::Connection Source::connect_generic(const SigC::SlotBase& slot)
@@ -729,7 +770,7 @@ void Source::get_current_time(Glib::Time
 }
 
 inline // static
-Source* Source::get_wrapper(GSource* source)
+const RefPtr<Source> Source::get_wrapper(GSource* source)
 {
   SourceCallbackData *const data = glibmm_source_get_callback_data(source);
   return data->wrapper;
@@ -740,8 +781,7 @@ gboolean Source::prepare_vfunc(GSource* 
 {
   try
   {
-    Source *const self = get_wrapper(source);
-    return self->prepare(*timeout);
+    return get_wrapper(source)->prepare(*timeout);
   }
   catch(...)
   {
@@ -755,8 +795,7 @@ gboolean Source::check_vfunc(GSource* so
 {
   try
   {
-    Source *const self = get_wrapper(source);
-    return self->check();
+    return get_wrapper(source)->check();
   }
   catch(...)
   {
@@ -775,8 +814,7 @@ gboolean Source::dispatch_vfunc(GSource*
 
   try
   {
-    Source *const self = callback_data->wrapper;
-    return self->dispatch(callback_data->node->get_slot_node());
+    return callback_data->wrapper->dispatch(callback_data->node->get_slot_node());
   }
   catch(...)
   {
@@ -786,18 +824,10 @@ gboolean Source::dispatch_vfunc(GSource*
 }
 
 // static
-void Source::destroy_notify_callback(void* data)
+void Source::destroy_notify_callback(const RefPtr<Source>& data)
 {
   if(data)
-  {
-    Source *const self = static_cast<Source*>(data);
-
-    // gobject_ is already invalid at this point.
-    self->gobject_ = 0;
-
-    // No exception checking: if the dtor throws, you're out of luck anyway.
-    delete self;
-  }
+    data->gobject_ = 0; // gobject_ is already invalid at this point.
 }
 
 


*** glib/glibmm/main.h	1 Dec 2002 19:24:12 -0000	1.18
--- glib/glibmm/main.h	24 Jan 2003 16:16:57 -0000
@@ -33,6 +33,19 @@
 
 GTKMM_USING_STD(vector)
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+// Provide dummy declarations for GMainContext and GMainLoop so we
+// can subclass from them. We don't actually need to know what is
+// in them, so it's OK if we think they're empty.
+
+struct _GMainContext
+{
+};
+
+struct _GMainLoop
+{
+};
+#endif
 
 namespace Glib
 {
@@ -296,7 +309,7 @@ SignalIO signal_io();
 
 /** Main context.
  */
-class MainContext
+class MainContext : public GMainContext
 {
 public:
   typedef Glib::MainContext  CppObjectType;
@@ -363,7 +376,7 @@ private:
 Glib::RefPtr<MainContext> wrap(GMainContext* gobject, bool take_copy = false);
 
 
-class MainLoop
+class MainLoop : public GMainLoop
 {
 public:
   typedef Glib::MainLoop  CppObjectType;
@@ -399,7 +412,7 @@ private:
 Glib::RefPtr<MainLoop> wrap(GMainLoop* gobject, bool take_copy = false);
 
 
-class Source
+class Source : public SigC::Object
 {
 public:
   typedef Glib::Source  CppObjectType;
@@ -424,8 +437,8 @@ public:
   const GSource* gobj() const { return gobject_; }
   GSource*       gobj_copy() const;
 
-  void reference()   const;
-  void unreference() const;
+  virtual void reference()   const; // overrides SigC::Object::reference
+  virtual void unreference() const; // overrides SigC::Object::unreference
 
 protected:
   /** Construct an object that uses the virtual functions prepare(), check() and dispatch().
@@ -459,7 +472,7 @@ private:
 
 #ifndef DOXGEN_SHOULD_SKIP_THIS
 
-  static inline Source* get_wrapper(GSource* source);
+  static inline const RefPtr<Source> get_wrapper(GSource* source);
 
   static const GSourceFuncs vfunc_table_;
 
@@ -467,7 +480,7 @@ private:
   static gboolean check_vfunc(GSource* source);
   static gboolean dispatch_vfunc(GSource* source, GSourceFunc callback, void* user_data);
 public:
-  static void destroy_notify_callback(void* data);
+  static void destroy_notify_callback(const RefPtr<Source>& data);
 private:
 
 #endif /* DOXGEN_SHOULD_SKIP_THIS */


*** glib/glibmm/object.cc	4 Jan 2003 14:08:56 -0000	1.39
--- glib/glibmm/object.cc	24 Jan 2003 16:17:00 -0000
@@ -224,7 +224,6 @@ Object::Object(GObject* castitem)
 
 Object::~Object()
 {
-  cpp_destruction_in_progress_ = true;
 }
 
 /*


*** glib/glibmm/objectbase.cc	20 Dec 2002 21:39:39 -0000	1.11
--- glib/glibmm/objectbase.cc	24 Jan 2003 16:17:01 -0000
@@ -19,10 +19,147 @@
  */
 
 #include <glib-object.h>
-
-#include <glibmm/quark.h>
 #include <glibmm/objectbase.h>
+#include <glibmm/refptr.h>
 
+//----------------------------------------------------------------------
+// Notes on inheritance and management of underlying GTK+ objects.
+//
+// 1) Reference counting as lifetime management.
+//
+//    In the class hierarchy descended from Glib::ObjectBase, some of
+//    the classes always use reference counting to manage the lifetime of
+//    object instances. All such classes have protected constructors and
+//    can only be created by calling a static create() method of the
+//    class, which allocates an instance of the class on the heap with
+//    new and returns a smart pointer that serves as a reference to the
+//    instance. Some classes do not provide a create() method (they must
+//    be instantiated by derived classes or friends) or provide a method
+//    with a different name, but the basic principle still holds.
+//
+//    All classes in this category must be referenced through the use of
+//    smart pointers that maintain the reference count of each instance.
+//    When there are no more references to an instance (i.e. its reference
+//    count is reduced to zero) then the instance is deleted.
+//
+//    Other classes do not always use reference counting to manage the
+//    lifetime of object instances. They have public constructors. These
+//    classes may be allocated on the stack or as members of another
+//    class. Classes in this category normally are not referenced by smart
+//    pointers.
+//
+// 2) Wrapping of GLib objects.
+//
+//    Glib::ObjectBase is the base class for all classes that wrap a
+//    GLib object (a GObject). There is a one-to-one relationship
+//    between a C++ wrapper instance and its associated GObject. The
+//    wrapper instance holds a pointer to the GObject, and the GObject
+//    holds a pointer to the wrapper instance.
+//
+//    A GObject has a reference count of one when it is created, and the
+//    creator (in this case, the wrapper) is assumed to own this
+//    reference and thus the GObject.
+//
+//    The wrapper and the GObject both need to persist so long as there
+//    are external references (references held by a third entity) to
+//    either of them. The objects cannot mutually hold references to
+//    each other, because then they would keep each other alive when no
+//    more external references exist.
+//
+//    To accomplish this, one of the two objects holds a reference to
+//    the other at any given time. The object holding the reference is
+//    the anchor. With one exception, there will always be at least one
+//    external reference to the anchor. The exception is when a wrapper
+//    is newly constructed and has a reference to a GObject, but has not
+//    yet been referenced itself.
+//
+//    Normally, the wrapper is the anchor. The only time that the
+//    GObject is the anchor is when there are no external references to
+//    the wrapper (except for the case described above).
+//    
+//    If the wrapper is the anchor and the last external reference to it
+//    is released, then the GObject becomes the anchor. The GObject is
+//    given a reference to the wrapper and the wrapper's reference to
+//    the GObject is released. This happens in the wrapper's
+//    unreference() method. 
+//
+//    If the GObject is the anchor and an external reference to the
+//    wrapper is acquired, then the wrapper again becomes the anchor.
+//    The wrapper acquires a reference to the GObject and the reference
+//    to the wrapper is removed from the GObject. This happens in the
+//    wrapper's reference() method.
+//
+//    If the GObject is the anchor and its reference count goes to zero,
+//    then the GObject is destroyed and destroy_notify_callback_() is
+//    invoked.
+//
+//    The destroy_notify_callback_() acquires a temporary reference to
+//    the wrapper (which makes it the anchor) and calls the wrapper's
+//    destroy_notify_() virtual method. The destroy_notify_() method
+//    clears the wrapper's pointer to the GObject. Upon return from
+//    destroy_notify_() the temporary reference to the wrapper is
+//    released. Since it is the last reference to the wrapper, the
+//    wrapper is then deleted.
+//
+// 3) Inheritance hierarchy classifications.
+//
+//    There are only two classes that inherit directly from
+//    Glib::ObjectBase, which are Glib::Interface and Glib::Object.
+//
+//    Relatively few classes inherit directly from Glib::Interface. None
+//    of these can be instantiated directly. The use of reference 
+//    counting is indeterminate for these classes, because the nature
+//    of derived classes will dictate how the lifetime of an instance is
+//    determined.
+//
+//    A large number of classes inherit directly from Glib::Object. Of
+//    these, all but one use reference counting to manage the lifetime
+//    of object instances. The one exception is Gtk::Object.
+//
+// 4) Wrapping of GTK+ objects.
+//
+//    Gtk::Object is the base class for all classes that wrap a GTK+
+//    object (a GtkObject). GtkObject is a subclass of GObject that has
+//    a different set of rules for managing references. Gtk::Object is
+//    a subclass of Glib::Object that accounts for those rules.
+//
+//    The inheritance hierarchy of Gtk::Object includes all of the Gtk
+//    and Gnome widgets as well as a small number of utility classes
+//    including Gtk::Adjustment, Gtk::CellRenderer, Gtk::Tooltips and
+//    Gtk::TreeViewColumn.
+//
+//    Like a GObject, a GtkObject is created with an initial reference
+//    count of one. Unlike a GtkObject, this reference is not owned by
+//    the creating entity. It is considered a "floating" reference. To
+//    take ownership of a GtkObject, an entity must acquire a
+//    non-floating reference using g_object_ref() and then remove the
+//    floating reference by calling gtk_object_sink() on the GtkObject.
+//
+//    Normally, the Gtk::Object class does not use reference counting,
+//    nor do any classes that inherit from it. A Gtk::Object instance in
+//    this state is considered "unmanaged". An unmanaged Gtk::Object
+//    always has a non-floating reference to the GtkObject, which it
+//    acquires during initialization. An unmanaged Gtk::Object owns the
+//    GtkObject it wraps.
+//
+//    It is possible (though potentially perilous) to enable reference
+//    counting for a specific instance of a Gtk::Object by calling the
+//    set_manage() method directly or by using the Gtk::manage() function
+//    on the instance. This must only be done with a Gtk::Object instance
+//    that has been allocated with new. Once this is done, a Gtk::Object
+//    is considered "managed".
+//
+//    A managed Gtk::Object gives up its initial non-floating reference
+//    to the GtkObject. The GtkObject is then floating (if it was "sunk"
+//    by the Gtk::Object) or is owned by some other entity (usually a
+//    container widget) or is destroyed, if no more references to the
+//    GtkObject exist after the set_manage() call. A managed Gtk::Object
+//    gives up ownership of the GtkObject it wraps.
+//
+//    For detailed information on how Gtk::Object uses reference counting,
+//    see the Gtk::Object implementation.
+//
+//----------------------------------------------------------------------
 
 namespace
 {
@@ -41,33 +178,54 @@ namespace Glib
 
 /**** Glib::ObjectBase *****************************************************/
 
+GQuark ObjectBase::quark_ = 0;
+GQuark ObjectBase::quark_anchor_ = 0;
+GQuark ObjectBase::quark_disconnected_ = 0;
+
+//----------------------------------------------------------------------
+// construction, destruction
+//----------------------------------------------------------------------
+
 ObjectBase::ObjectBase()
 :
   gobject_                      (0),
   custom_type_name_             (anonymous_custom_type_name),
-  cpp_destruction_in_progress_  (false)
-{}
+  referenced_                   (true)
+{
+  set_manage(); // Arrange for delete to be called when no more references exist
+}
 
 ObjectBase::ObjectBase(const char* custom_type_name)
 :
   gobject_                      (0),
   custom_type_name_             (custom_type_name),
-  cpp_destruction_in_progress_  (false)
-{}
+  referenced_                   (true)
+{
+  set_manage(); // Arrange for delete to be called when no more references exist
+}
 
 ObjectBase::ObjectBase(const std::type_info& custom_type_info)
 :
   gobject_                      (0),
   custom_type_name_             (custom_type_info.name()),
-  cpp_destruction_in_progress_  (false)
-{}
+  referenced_                   (true)
+{
+  set_manage(); // Arrange for delete to be called when no more references exist
+}
 
 // initialize() actually initializes the wrapper.  Glib::ObjectBase is used
-// as virtual base class, which means the most-derived class' ctor invokes
+// as s virtual base class, which means the most-derived class' ctor invokes
 // the Glib::ObjectBase ctor -- thus it's useless for Glib::Object.
 //
 void ObjectBase::initialize(GObject* castitem)
 {
+  if(quark_ == 0)
+  {
+    quark_ = g_quark_from_static_string("glibmm__Glib::ObjectBase::quark_");
+    quark_anchor_ = g_quark_from_static_string("glibmm__Glib::ObjectBase::quark_anchor_");
+    quark_disconnected_ = g_quark_from_static_string("glibmm__Glib::ObjectBase::quark_disconnected_");
+  }
+
   if(gobject_)
   {
     // initialize() might be called twice when used with MI, e.g. by the ctors
@@ -77,181 +235,252 @@ void ObjectBase::initialize(GObject* cas
     g_assert(gobject_ == castitem);
 
     // TODO: Think about it.  Will this really be called twice?
-    g_printerr("ObjectBase::initialize() called twice for the same GObject\n");
+    g_printerr("Glib::ObjectBase::initialize() called twice for the same GObject\n");
 
     return; // Don't initialize the wrapper twice.
   }
 
-  //g_print("%s : %s\n", G_GNUC_PRETTY_FUNCTION, G_OBJECT_TYPE_NAME(castitem));
-
   gobject_ = castitem;
   _set_current_wrapper(castitem);
 }
 
 ObjectBase::~ObjectBase()
 {
-  // Normally, gobject_ should always be 0 at this point, because:
+  // Normally, gobject_ should always be zero at this point, because:
   //
-  // a) Gtk::Object handles memory management on its own and always resets
-  //    the gobject_ pointer in its destructor.
+  // a) Gtk::Object has different lifetime management behaviors and always
+  //    clears the gobject_ member in its destructor.
   //
-  // b) Glib::Object instances that aren't Gtk::Objects will always be
-  //    deleted by the destroy_notify_() virtual method.  Calling delete
-  //    on a Glib::Object is a programming error.
+  // b) Glib::ObjectBase instances that aren't Gtk::Object instances are
+  //    always deleted when the GObject is disposed and the gobject_ member
+  //    is cleared in destroy_notify_() before the Glib::ObjectBase is deleted.
+  //    Calling delete directly on a Glib::ObjectBase is a programming error.
   //
-  // The *only* situation where gobject_ is validly not 0 at this point
-  // happens if a derived class's ctor throws an exception.  In that case
-  // we have to call g_object_unref() on our own.
+  // The _only_ situation where gobject_ is validly not zero at this point
+  // is if a derived class's constructor throws an exception. However, in that
+  // case this destructor will never be called, because C++ does not call the
+  // destructor for an object that has not been completely constructed. See
+  // Scott Meyers "More Effective C++" item 10 for details:
+  // http://www.awprofessional.com/content/images/020163371x/items/item10.html
   //
-  if(GObject *const gobject = gobject_)
-  {
-#ifdef GTKMM_DEBUG_REFCOUNTING
-    g_warning("(Glib::ObjectBase::~ObjectBase): gobject_ = %p", (void*) gobject_);
-#endif
-
-    gobject_ = 0;
-
-#ifdef GTKMM_DEBUG_REFCOUNTING
-    g_warning("(Glib::ObjectBase::~ObjectBase): before g_object_steal_qdata()");
-#endif
+  // However, we can at least gracefully handle the case where someone calls
+  // delete on a Glib::ObjectBase instance. Their code may fail later when
+  // they attempt to access the deleted object, but we will have done the right
+  // thing here.
 
-    // Remove the pointer to the wrapper from the underlying instance.
-    // This does _not_ cause invocation of the destroy_notify callback.
-    g_object_steal_qdata(gobject, quark_);
-
-#ifdef GTKMM_DEBUG_REFCOUNTING
-    g_warning("(Glib::ObjectBase::~ObjectBase): calling g_object_unref()");
-#endif
+  if(GObject* const gobject = gobj())
+  {
+    // Disconnect the wrapper from the underlying instance. This does _not_
+    // cause invocation of destroy_notify_callback_
+    disconnect_wrapper_();
 
-    g_object_unref(gobject);
+    // Release our reference to the GObject, if we're holding one
+    if (referenced_) g_object_unref(gobject);
   }
 }
 
+//----------------------------------------------------------------------
+// public methods
+//----------------------------------------------------------------------
+
+// override
 void ObjectBase::reference() const
 {
-  // Completely replace the SigC::Object refcounting.
-  GTKMM_DEBUG_REFERENCE(this, gobject_);
-  g_object_ref(gobject_);
+  GTKMM_DEBUG_REFERENCE(this, gobj());
+
+  if (gobj_is_anchor())
+    gobj_set_anchor(false);
+  else
+    SigC::Object::reference();
 }
 
+// override
 void ObjectBase::unreference() const
 {
-  // Completely replace the SigC::Object refcounting.
-  GTKMM_DEBUG_UNREFERENCE(this, gobject_);
-  g_object_unref(gobject_);
+  GTKMM_DEBUG_UNREFERENCE(this, gobj());
+
+  if (gobj_can_anchor())
+    gobj_set_anchor(true);
+  else
+    SigC::Object::unreference();
 }
 
 GObject* ObjectBase::gobj_copy() const
 {
-  reference();
+  g_object_ref(gobject_);
   return gobject_;
 }
 
-void ObjectBase::_set_current_wrapper(GObject* object)
-{
-  // Store a pointer to this wrapper in the underlying instance, so that we
-  // never create a second wrapper for the same underlying instance.  Also,
-  // specify a callback that will tell us when it's time to delete this C++
-  // wrapper instance:
-
-  if(object)
-  {
-    if(!g_object_get_qdata(object, Glib::quark_))
-    {
-      g_object_set_qdata_full(object, Glib::quark_, this, &destroy_notify_callback_);
-    }
-    else
-    {
-      g_warning("This object, of type %s, already has a wrapper.\n"
-                "You should use wrap() instead of a constructor.",
-                G_OBJECT_TYPE_NAME(object));
-    }
-  }
-}
-
 // static
 ObjectBase* ObjectBase::_get_current_wrapper(GObject* object)
 {
   if(object)
-    return static_cast<ObjectBase*>(g_object_get_qdata(object, Glib::quark_));
+    return static_cast<ObjectBase*>(g_object_get_qdata(object, quark_));
   else
     return 0;
 }
 
 // static
-void ObjectBase::destroy_notify_callback_(void* data)
+bool ObjectBase::_wrapper_disconnected(GObject* object)
 {
-  //GTKMM_LIFECYCLE
+  // This function is used to prevent calling wrap() on a GObject whose wrapper
+  // instance has been (or is being) destroyed.
 
-  // This method is called (indirectly) from g_object_run_dispose().
-  // Get the C++ instance associated with the C instance:
-  ObjectBase* cppObject = static_cast<ObjectBase*>(data); //Previously set with g_object_set_qdata_full().
+  if(object)
+    return g_object_get_qdata(object, quark_disconnected_);
+  return false;
+}
+
+//----------------------------------------------------------------------
+// protected methods
+//----------------------------------------------------------------------
+
+bool ObjectBase::is_anonymous_custom_() const
+{
+  // Doing high-speed pointer comparison is OK here.
+  return (custom_type_name_ == anonymous_custom_type_name);
+}
+
+bool ObjectBase::is_derived_() const
+{
+  // gtkmmproc-generated classes initialize this to 0 by default.
+  return (custom_type_name_ != 0);
+}
+
+// virtual
+void ObjectBase::release_reference_()
+{
+  // This method is called by Gtk::Object::set_manage() when converting an
+  // unmanaged wrapper to a managed wrapper.
 
-#ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("ObjectBase::destroy_notify_callback_: cppObject=%10X, gobject_=%10X\n", cppObject, cppObject->gobject_);
-  g_warning("  gtypename=%s\n", cppObject->gobject_);
-#endif
+  referenced_ = false;
+  if (gobj())
+    g_object_unref(gobj());
+}
+
+// virtual
+void ObjectBase::disconnect_wrapper_()
+{
+  // This method is called by Gtk::Object::destroy_(), which in turn is called
+  // by Gtk::Object::~Object(), to dissociate the wrapper from the GtkObject
+  // prior to destroying it. This ensures that the wrapper is not referenced
+  // after it has been destroyed. 
 
-  if(cppObject) //This will be 0 if the C++ destructor has already run.
+  if(gobj())
   {
-    cppObject->destroy_notify_(); //Virtual - it does different things for GObject and GtkObject.
+    g_object_steal_qdata(gobj(), quark_); // Disconnect wrapper
+    g_object_set_qdata(gobj(), quark_disconnected_, (gpointer)true); // Prevent re-wrapping
+    gobject_ = 0; // Clear our pointer to the GObject
   }
 }
 
-void ObjectBase::destroy_notify_()
-{
-  // The C instance is about to be disposed, making it unusable.  Now is a
-  // good time to delete the C++ wrapper of the C instance.  There is no way
-  // to force the disposal of the GObject (though GtkObject  has
-  // gtk_object_destroy()), So this is the *only* place where we delete the
-  // C++ wrapper.
-  //
-  // This will only happen after the last unreference(), which will be done by
-  // the RefPtr<> destructor.  There should be no way to access the wrapper or
-  // the undobjecterlying instance after that, so it's OK to delete this.
+// It would be better if the following three methods did not need to know
+// the implementation of reference counting in SigC::ObjectBase, but we
+// can at least keep this knowledge as far up the class hierarchy as possible.
+// If SigC::ObjectBase changes to provide accessors for this information,
+// then we can change the implementations here.
 
-#ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Glib::ObjectBase::destroy_notify_: gobject_=%10X\n", gobject_);
-#endif
+bool ObjectBase::is_managed_() const
+{
+  return const_cast<ObjectBase*>(this)->control()->manage_;
+}
 
-  gobject_ = 0; // Make sure we don't unref it again in the dtor.
+void ObjectBase::set_manage(bool manage)
+{
+  if (manage)
+    set_manage();
+  else
+    control()->manage_ = 0;
+}
 
-  delete this;
+unsigned long ObjectBase::get_refcount_() const
+{
+  return const_cast<ObjectBase*>(this)->control()->count_;
 }
 
-bool ObjectBase::is_anonymous_custom_() const
+// virtual
+void ObjectBase::destroy_notify_()
 {
-  // Doing high-speed pointer comparison is OK here.
-  return (custom_type_name_ == anonymous_custom_type_name);
+  // The GObject is about to be disposed, making it unusable. We need to
+  // get rid of our pointer to the GObject. This method will _never_ be
+  // called from ~ObjectBase() because we clear the GObject's pointer to
+  // the wrapper before dereferencing it in ~ObjectBase().
+
+  gobject_ = 0; // Clear our pointer to the GObject
 }
 
-bool ObjectBase::is_derived_() const
+//----------------------------------------------------------------------
+// private methods
+//----------------------------------------------------------------------
+
+void ObjectBase::_set_current_wrapper(GObject* object)
 {
-  // gtkmmproc-generated classes initialize this to 0 by default.
-  return (custom_type_name_ != 0);
+  // Store a pointer to this wrapper in the GObject, so that we never
+  // create a second wrapper for the same GObject. Also specify a
+  // callback that will tell us if the GObject is destroyed.
+
+  if(object)
+  {
+    if(!g_object_get_qdata(object, quark_))
+      g_object_set_qdata_full(object, quark_, this, &destroy_notify_callback_);
+    else
+      g_warning("This object, of type %s, already has a wrapper.\n"
+                "You should use wrap() instead of a constructor.",
+                G_OBJECT_TYPE_NAME(object));
+  }
 }
 
-void ObjectBase::set_manage()
+// static
+void ObjectBase::destroy_notify_callback_(void* data)
 {
-  // This is a private method and SigC::manage() is a template function.
-  // Thus this will probably never run, unless you do something like:
+  // This method is called (indirectly) from g_object_run_dispose().
   //
-  // manage(static_cast<SigC::Object*>(refptr.operator->()));
+  // The data argument is a pointer to the wrapper associated with
+  // the GObject. This is set by the initialize() method through a call
+  // to _set_current_wrapper and is cleared to zero in the ObjectBase
+  // destructor.
+
+  if (data)
+  { // Inside this scope, the wrapper is always the anchor
+    RefPtr<ObjectBase> self(static_cast<ObjectBase*>(data));
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+      g_warning("Glib::ObjectBase::destroy_notify_callback_: cppObject=%10X, gobject_=%10X\n",
+        data, self->gobj());
+      g_warning("  gtypename=%s\n", G_OBJECT_TYPE_NAME(self->gobj()));
+    #endif
+
+    self->destroy_notify_(); // virtual method; can be overridden to add behaviors
 
-  g_error("Glib::ObjectBase::set_manage(): "
-          "only Gtk::Object instances can be managed");
+  } // The wrapper may be deleted when we leave this scope
 }
 
-bool _gobject_cppinstance_already_deleted(GObject* gobject)
+//----------------------------------------------------------------------
+// private methods related to anchoring
+//----------------------------------------------------------------------
+
+bool ObjectBase::gobj_is_anchor() const
 {
-  //This function is used to prevent calling wrap() on a GTK+ instance whose gtkmm instance has been deleted.
+  return gobj() && g_object_get_qdata(gobject_,quark_anchor_);
+}
 
-  if(gobject)
-    return (bool)g_object_get_qdata(gobject, Glib::quark_cpp_wrapper_deleted_); //true means that something is odd.
-  else
-    return false; //Nothing is particularly wrong.
+bool ObjectBase::gobj_can_anchor() const
+{
+  return gobj() && is_managed_() && get_refcount_() == 1 && !gobj_is_anchor();
 }
 
+void ObjectBase::gobj_set_anchor(bool anchor) const
+{
+  if (anchor)
+  {
+    g_object_set_qdata(gobject_, quark_anchor_, (gpointer)true);
+    if (referenced_ && gobj()->ref_count > 0) g_object_unref(gobject_);
+  }
+  else
+  {
+    g_object_steal_qdata(gobject_, quark_anchor_);
+    if (referenced_ && gobj()->ref_count > 0) g_object_ref(gobject_);
+  }
+}
 
 } // namespace Glib
-


*** glib/glibmm/objectbase.h	11 Oct 2002 18:05:43 -0000	1.9
--- glib/glibmm/objectbase.h	24 Jan 2003 16:17:04 -0000
@@ -25,6 +25,7 @@
 #include <typeinfo>
 #include <glibmmconfig.h>
 #include <glibmm/debug.h>
+#include <glibmm/quark.h>
 
 GTKMM_USING_STD(type_info)
 
@@ -71,14 +72,14 @@ protected:
   explicit ObjectBase(const char* custom_type_name);
   explicit ObjectBase(const std::type_info& custom_type_info);
 
-  virtual ~ObjectBase() = 0;
+  virtual ~ObjectBase() = 0; // Make it impossible to instantiate an ObjectBase directly
 
   // Called by Glib::Object and Glib::Interface constructors. See comments there.
   void initialize(GObject* castitem);
 
 public:
-  virtual void reference()   const; // overrides SigC::ObjectBase::reference()
-  virtual void unreference() const; // overrides SigC::ObjectBase::unreference()
+  virtual void reference()   const; // overrides SigC::Object::reference()
+  virtual void unreference() const; // overrides SigC::Object::unreference()
 
   inline GObject*       gobj()       { return gobject_; }
   inline const GObject* gobj() const { return gobject_; }
@@ -90,32 +91,53 @@ public:
   static ObjectBase* _get_current_wrapper(GObject* object);
 #endif
 
+  static bool _wrapper_disconnected(GObject* object);
+
 protected:
   GObject*            gobject_; // the GLib/GDK/GTK+ object instance
   const char*         custom_type_name_;
-  bool                cpp_destruction_in_progress_;
 
   bool is_anonymous_custom_() const;
   bool is_derived_() const;
 
-  static  void destroy_notify_callback_(void* data);
-  virtual void destroy_notify_();
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  virtual void release_reference_();
+  virtual void disconnect_wrapper_();
 
-  void _set_current_wrapper(GObject* object);
+  bool is_managed_() const;
+  void set_manage(bool manage);
+  unsigned long get_refcount_() const;
+  using SigC::Object::set_manage;
+#endif
+
+  virtual void destroy_notify_();
 
 private:
   // noncopyable
-  ObjectBase(const ObjectBase&);
-  ObjectBase& operator=(const ObjectBase&);
+  ObjectBase(const ObjectBase&); // not implemented
+  ObjectBase& operator=(const ObjectBase&); // not implemented
+
+  void _set_current_wrapper(GObject* object);
+  static void destroy_notify_callback_(void* data);
 
-  virtual void set_manage(); // calls g_error()
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  bool gobj_is_anchor() const;
+  bool gobj_can_anchor() const;
+  void gobj_set_anchor(bool anchor) const;
+#endif
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
   friend class Glib::GSigConnectionNode; // for GSigConnectionNode::notify()
 #endif
-};
 
-bool _gobject_cppinstance_already_deleted(GObject* gobject);
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  bool referenced_;
+  static GQuark quark_;
+  static GQuark quark_anchor_;
+  static GQuark quark_disconnected_;
+#endif
+
+};
 
 } // namespace Glib
 


*** glib/glibmm/quark.cc	11 Oct 2002 18:05:43 -0000	1.10
--- glib/glibmm/quark.cc	24 Jan 2003 16:17:06 -0000
@@ -59,8 +59,4 @@ Quark::Quark(const char* s)
 Quark::~Quark()
 {}
 
-
-GQuark quark_ = 0;
-GQuark quark_cpp_wrapper_deleted_ = 0;
-
 } /* namespace Glib */


*** glib/glibmm/quark.h	11 Oct 2002 18:05:43 -0000	1.13
--- glib/glibmm/quark.h	24 Jan 2003 16:17:07 -0000
@@ -75,14 +75,6 @@ inline bool operator==(const QueryQuark&
 inline bool operator!=(const QueryQuark& a, const QueryQuark& b)
   { return a.id() != b.id(); }
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-// TODO: Put this somewhere else.
-// (internal) The quark for C++ wrappers.
-extern GLIBMM_API GQuark quark_;
-extern GLIBMM_API GQuark quark_cpp_wrapper_deleted_;
-#endif
-
 } /* namespace Glib */
 
 #endif /* _GLIBMM_QUARK_H */
-


*** glib/glibmm/refptr.h	27 Dec 2002 12:19:33 -0000	1.32
--- glib/glibmm/refptr.h	24 Jan 2003 16:17:09 -0000
@@ -27,80 +27,102 @@ namespace Glib
 
 /** RefPtr<> is a reference-counting shared smartpointer.
  *
- * Some objects in gtkmm are obtained from a shared
- * store. Consequently you cannot instantiate them yourself. Instead they
- * return a RefPtr which behaves much like an ordinary pointer in that members
- * can be reached with the usual <code>object_ptr->member</code> notation.
- * Unlike most other smart pointers, RefPtr doesn't support dereferencing
- * through <code>*object_ptr</code>.
+ * Some objects in gtkmm are obtained from a shared store. Consequently
+ * you cannot instantiate them yourself. Instead you call a static creator 
+ * method, which returns a RefPtr<> that behaves much like an ordinary pointer
+ * in that members can be accessed with the usual <code>object_ptr->member</code>
+ * notation. While older versions of RefPtr<> did not support the dereferencing
+ * operator, this has been changed to enable operators of a referenced object
+ * to be invoked naturally e.g. <code>(*ptr) += some_value</code>.
  *
  * Reference counting means that a shared reference count is incremented each
- * time a RefPtr is copied, and decremented each time a RefPtr is destroyed,
- * for instance when it leaves its scope. When the reference count reaches
- * zero, the contained object is deleted, meaning  you don't need to remember
- * to delete the object.
+ * time a reference is created or copied, and decremented each time a reference
+ * is released, for instance when a RefPtr<> goes out of scope. When the
+ * reference count reaches zero, the reference counted object is deleted,
+ * meaning you don't need to remember to delete the object. An important
+ * consequence of this behavior is that objects to be reference counted must be
+ * allocated with new.
  *
- * RefPtr<> can store any class that has reference() and unreference() methods.
- * In gtkmm, that is anything derived from Glib::ObjectBase, such as
- * Gdk::Pixmap.
+ * RefPtr<> can be used with any class that has public reference() and
+ * unreference() methods. In gtkmm, that is anything derived from SigC::Object,
+ * such as Gdk::Pixmap.
+ *
+ * The RefPtr<> class does not increment or decrement the reference count
+ * directly, nor does it delete the object when the reference count reaches
+ * zero. It depends on the reference() and unreference() methods to do these
+ * things.
  *
  * See the "Memory Management" section in the "Programming with gtkmm"
  * book for further information.
  */
+
 template <class T_CppObject>
 class RefPtr
 {
 public:
   /** Default constructor
    *
-   * Afterwards is_null() will return true and use of -> will cause a segmentation fault.
+   * Creates a null reference; use of -> will cause a segmentation fault.
    */
   inline RefPtr();
-  
+
   /// Destructor - decrements reference count.
   inline ~RefPtr();
 
-  /// For use only by the ::create() methods.
+  /** Constructor from pointer
+   *
+   * Increments the reference count.
+   */
   explicit inline RefPtr(T_CppObject* pCppObject);
 
   /** Copy constructor
    *
-   * This increments the shared reference count.
+   * Increments the reference count.
    */
   inline RefPtr(const RefPtr<T_CppObject>& src);
 
-  /** Copy constructor (from different, but castable type).
+  /** Copy constructor (from RefPtr<> to a different, but castable T_CppObject).
    *
    * Increments the reference count.
    */
   template <class T_CastFrom>
   inline RefPtr(const RefPtr<T_CastFrom>& src);
 
-  /** Swap the contents of two RefPtr<>.
+  /** Swap the contents of two RefPtr<> instances.
+   *
    * This method swaps the internal pointers to T_CppObject.  This can be
    * done safely without involving a reference/unreference cycle and is
    * therefore highly efficient.
    */
   inline void swap(RefPtr<T_CppObject>& other);
 
-  /// Copy from another RefPtr:
+  /// Copy from another RefPtr<> to the same T_CppObject:
   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CppObject>& src);
 
-  // TODO: Get rid of this evilness.
-  /// For use only by the ::create() methods.
+  /** Copy directly from a pointer.
+   *
+   * Mimics usage of ordinary pointers:
+   * @code
+   *   ptr = new thing; // assign a new reference to the RefPtr<>
+   * @endcode
+   * As well as:
+   * @code
+   *   ptr = 0; // releases the object reference, sets the RefPtr<> to null
+   * @endcode
+   */
   inline RefPtr<T_CppObject>& operator=(T_CppObject* pCppObject); 
 
-  /** Copy from different, but castable type).
+  /** Copy from a RefPtr<> to a different, but castable T_CppObject).
    *
-   * Increments the reference count.
+   * Does nothing if the referenced objects are the same object.
+   * Decrements the reference count of the formerly referenced object.
+   * Increments the reference count of the newly referenced object.
    */
   template <class T_CastFrom>
   inline RefPtr<T_CppObject>& operator=(const RefPtr<T_CastFrom>& src);
 
-  /// Tests whether the RefPtr<> point to the same underlying instance.
+  /// Tests whether another RefPtr<> points to the same underlying instance.
   inline bool operator==(const RefPtr<T_CppObject>& src) const;
-  
-  /// See operator==().
   inline bool operator!=(const RefPtr<T_CppObject>& src) const;
 
   /** Dereferencing.
@@ -110,26 +132,43 @@ public:
    */
   inline T_CppObject* operator->() const;
 
+  /** Dereferencing.
+   *
+   * Use the operators of the underlying instance like so:
+   * <code>(*refptr) += some_value</code>.
+   */
+  inline T_CppObject& operator*() const;
+
   /** Test whether the RefPtr<> points to any underlying instance.
    *
    * Mimics usage of ordinary pointers:
    * @code
    *   if (ptr)
    *     do_something();
+   *   else if (!ptr)
+   *     do_something_else();
+   * @endcode
+   *
+   * Alternatively:
+   * @code
+   *   if (ptr == 0)
+   *     do_something();
+   *   else if (ptr != 0)
+   *     do_something_else();
    * @endcode
    */
   inline operator bool() const;
+  inline bool operator!() const;
 
   /// Test whether the RefPtr<> points to any underlying instance.
   inline bool is_null() const;  // whether there is no underlying instance
-
   
   /// Set underlying instance to 0, decrementing reference count of existing instance appropriately.
   inline void clear();
 
   /** Dynamic cast to derived class.
    *
-   * The RefPtr can't be cast with the usual notation so instead you can use
+   * The RefPtr<> can't be cast with the usual notation so instead you can use
    * @code
    *   ptr_derived = RefPtr<Derived>::cast_dynamic(ptr_base);
    * @endcode
@@ -163,6 +202,14 @@ T_CppObject* RefPtr<T_CppObject>::operat
   return pCppObject_;
 }
 
+// Might as well keep the dereferencing operators together.
+
+template <class T_CppObject> inline
+T_CppObject& RefPtr<T_CppObject>::operator*() const
+{
+  return *pCppObject_;
+}
+
 template <class T_CppObject> inline
 RefPtr<T_CppObject>::RefPtr()
 :
@@ -180,7 +227,10 @@ template <class T_CppObject> inline
 RefPtr<T_CppObject>::RefPtr(T_CppObject* pCppObject)
 :
   pCppObject_ (pCppObject)
-{}
+{
+  if (pCppObject_)
+    pCppObject_->reference();
+}
 
 template <class T_CppObject> inline
 RefPtr<T_CppObject>::RefPtr(const RefPtr<T_CppObject>& src)
@@ -251,17 +301,7 @@ RefPtr<T_CppObject>& RefPtr<T_CppObject>
 template <class T_CppObject> inline
 RefPtr<T_CppObject>& RefPtr<T_CppObject>::operator=(T_CppObject* pCppObject)
 {
-  RefPtr<T_CppObject> temp (pCppObject);
-
-  // This extra reference is necessary because operator=(T_CppObject*) used
-  // to behave differently than the ctor RefPtr(T_CppObject*), i.e. it takes
-  // a reference.  Unfortunately we can't fix it at this point.
-  //
-  // TODO: This assignment operator should be removed entirely at the next API break.
-
-  if(pCppObject)
-    pCppObject->reference();
-
+  RefPtr<T_CppObject> temp(pCppObject);
   this->swap(temp);
   return *this;
 }
@@ -295,6 +335,23 @@ RefPtr<T_CppObject>::operator bool() con
 }
 
 template <class T_CppObject> inline
+bool RefPtr<T_CppObject>::operator!() const
+{
+  return (pCppObject_ == 0);
+}
+
+// TODO: At the next API break, the clear() and is_null() methods should be
+// removed. As much as possible, RefPtr should behave like an ordinary pointer,
+// so that it is easier and more intuitive for developers to use it. There are
+// operators defined that make it possible to test for null or non-null and to
+// assign a null value to a RefPtr in the same way that pointers are tested and
+// assigned, so is_null() and clear() are unnecessary.
+// 
+// See Scott Meyers's articles on smart pointers at
+// http://www.aristeia.com/publications_frames.html for background on good
+// design of smart pointers.
+
+template <class T_CppObject> inline
 bool RefPtr<T_CppObject>::is_null() const
 {
   return (pCppObject_ == 0);
@@ -313,10 +370,6 @@ inline
 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_dynamic(const RefPtr<T_CastFrom>& src)
 {
   T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.operator->());
-
-  if(pCppObject)
-    pCppObject->reference();
-
   return RefPtr<T_CppObject>(pCppObject);
 }
 
@@ -326,10 +379,6 @@ inline
 RefPtr<T_CppObject> RefPtr<T_CppObject>::cast_static(const RefPtr<T_CastFrom>& src)
 {
   T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.operator->());
-
-  if(pCppObject)
-    pCppObject->reference();
-
   return RefPtr<T_CppObject>(pCppObject);
 }
 


*** glib/glibmm/wrap.cc	11 Oct 2002 18:05:44 -0000	1.24
--- glib/glibmm/wrap.cc	24 Jan 2003 16:17:11 -0000
@@ -32,6 +32,13 @@
 #include <glibmmconfig.h>
 GTKMM_USING_STD(vector)
 
+namespace Glib
+{
+  namespace Wrap
+  {
+    static GQuark quark_ = 0;
+  }
+}
 
 namespace
 {
@@ -50,8 +57,7 @@ Glib::ObjectBase* create_new_wrapper(GOb
 {
   g_return_val_if_fail(wrap_func_table != 0, 0);
 
-  bool gtkmm_wrapper_already_deleted = (bool)g_object_get_qdata((GObject*)object, Glib::quark_cpp_wrapper_deleted_);
-  if(gtkmm_wrapper_already_deleted)
+  if(Glib::ObjectBase::_wrapper_disconnected(object))
   {
     g_warning("Glib::create_new_wrapper: Attempted to create a 2nd C++ wrapper for a C instance whose C++ wrapper has been deleted.");
     return 0;
@@ -65,7 +71,7 @@ Glib::ObjectBase* create_new_wrapper(GOb
     // Look up the wrap table index stored in the type's static data.
     // If a wrap_new() has been registered for the type then call it.
     //
-    if(const gpointer idx = g_type_get_qdata(type, Glib::quark_))
+    if(const gpointer idx = g_type_get_qdata(type, Glib::Wrap::quark_))
     {
       const Glib::WrapNewFunction func = (*wrap_func_table)[GPOINTER_TO_UINT(idx)];
       return (*func)(object);
@@ -85,12 +91,6 @@ void wrap_register_init()
 {
   g_type_init();
 
-  if(!Glib::quark_)
-  {
-    Glib::quark_ = g_quark_from_static_string("glibmm__Glib::quark_");
-    Glib::quark_cpp_wrapper_deleted_ = g_quark_from_static_string("glibmm__Glib::quark_cpp_wrapper_deleted_");
-  }
-
   if(!wrap_func_table)
   {
     // Make the first element a dummy so we can detect unregistered types.
@@ -113,11 +113,14 @@ void wrap_register_cleanup()
 //
 void wrap_register(GType type, WrapNewFunction func)
 {
+  if(Glib::Wrap::quark_ == 0)
+    Glib::Wrap::quark_ = g_quark_from_static_string("glibmm__Glib::Wrap::quark_");
+
   const guint idx = wrap_func_table->size();
   wrap_func_table->push_back(func);
 
   // Store the table index in the type's static data.
-  g_type_set_qdata(type, Glib::quark_, GUINT_TO_POINTER(idx));
+  g_type_set_qdata(type, Glib::Wrap::quark_, GUINT_TO_POINTER(idx));
 }
 
 // This is a factory function that converts any type to
@@ -129,8 +132,7 @@ ObjectBase* wrap_auto(GObject* object, b
     return 0;
 
   // Look up current C++ wrapper instance:
-  ObjectBase* pCppObject =
-      static_cast<ObjectBase*>(g_object_get_qdata(object, Glib::quark_));
+  ObjectBase* pCppObject = ObjectBase::_get_current_wrapper(object);
 
   if(!pCppObject)
   {
@@ -147,7 +149,7 @@ ObjectBase* wrap_auto(GObject* object, b
   // take_copy=true is used where the GTK+ function doesn't do
   // an extra ref for us, and always for plain struct members.
   if(take_copy)
-    pCppObject->reference();
+    g_object_ref(object);
 
   return pCppObject;
 }
@@ -157,5 +159,4 @@ Glib::RefPtr<Object> wrap(GObject* objec
   return Glib::RefPtr<Object>(dynamic_cast<Object*>(wrap_auto(object, take_copy)));
 }
 
-} /* namespace Glib */
-
+} // namespace Glib


*** glib/src/iochannel.ccg	12 Nov 2002 19:45:05 -0000	1.3
--- glib/src/iochannel.ccg	24 Jan 2003 16:17:11 -0000
@@ -24,6 +24,9 @@
 #include <glibmm/main.h>
 #include <glib.h>
 
+// See Scott Meyers "Effective C++" item 21 for reasons why objects
+// returned from functions should be const:
+// http://www.awprofessional.com/content/images/0201924889/items/item21.html
 
 namespace
 {
@@ -34,19 +37,23 @@ namespace
 // C instance does.  Also Glib::wrap() usually returns always the same C++
 // wrapper object for a single C instance.
 //
-// Unfortunately it isn't possible to implement these features if we didn't
-// create the underlying GIOChannel.  That is, when wrapping existing
-// GIOChannel instances such as returned by e.g. g_io_channel_unix_new() or
-// g_io_channel_new_file().  Neither is there a way to hook up a wrapper
-// object in an existing GIOChannel, nor exists any destroy notification.
+// Unfortunately it isn't possible to implement these features if we're
+// wrapping a stock GIOChannel instance, such as returned by
+// g_io_channel_unix_new() or g_io_channel_new_file().  There is no way to
+// hook up a wrapper object to a stock GIOChannel, nor is there any destroy
+// notification.
 //
-// So that means:  If the IOChannel is implemented in C++ -- that is, our
-// GlibmmIOChannel backend is used -- we use the GIOChannel reference
-// counting mechanism.  If the IOChannel backend is unknown, then the
-// wrapper instance holds always exactly one reference to the GIOChannel.
-// The wrapper object itself is then managed via the SigC::Object refcounting
-// mechanism.  To do that a utility class ForeignIOChannel is introduced to
-// override reference() and unreference().
+// So that means:
+// - If the IOChannel is implemented in C++ so that an instance of our
+//   GlibmmIOChannel class is used as the GIOChannel, then we can hook into
+//   the "C instance" so that the wrapper's lifetime is tied to that of the
+//   GIOChannel. So long as there are references to either, both will continue
+//   to exist.
+// - If the GIOChannel is one of the stock channels, then the wrapper instance
+//   keeps a reference to the GIOChannel, but the wrapper's lifetime is
+//   managed solely by external C++ references. To make this more convenient,
+//   a utility class ForeignIOChannel is introduced with appropriate reference
+//   counting behaviors.
 
 class ForeignIOChannel : public Glib::IOChannel
 {
@@ -54,34 +61,43 @@ public:
   ForeignIOChannel(GIOChannel* gobject, bool take_copy)
     : Glib::IOChannel(gobject, take_copy) {}
 
+  ~ForeignIOChannel();
+
   virtual void reference()   const;
   virtual void unreference() const;
 };
 
+ForeignIOChannel::~ForeignIOChannel()
+{
+  if (gobject_) // We should have one of these
+    g_io_channel_unref(gobject_); // And we need to release our reference
+}
+
 void ForeignIOChannel::reference() const
 {
-  SigC::ObjectBase::reference();
+  SigC::Object::reference();
 }
 
 void ForeignIOChannel::unreference() const
 {
-  SigC::ObjectBase::unreference();
+  SigC::Object::unreference();
 }
 
 } // anonymous namespace
 
-
 namespace Glib
 {
 
-class GlibmmIOChannel
+/**** Glib::GlibmmIOChannel declaration ************************************/
+
+class GlibmmIOChannel : public GIOChannel
 {
+private:
+  GlibmmIOChannel(); // not implemented
+public:
+  GlibmmIOChannel(IOChannel *wrapper);
+  ~GlibmmIOChannel();
 public:
-  GIOChannel        base;
-  Glib::IOChannel*  wrapper;
-
-  static const GIOFuncs vfunc_table;
-
   static GIOStatus io_read(GIOChannel* channel, char* buf, gsize count,
                            gsize* bytes_read, GError** err);
 
@@ -96,23 +112,19 @@ public:
 
   static GIOStatus io_set_flags(GIOChannel* channel, GIOFlags flags, GError** err);
   static GIOFlags  io_get_flags(GIOChannel* channel);
-};
 
-// static
-const GIOFuncs GlibmmIOChannel::vfunc_table =
-{
-  &GlibmmIOChannel::io_read,
-  &GlibmmIOChannel::io_write,
-  &GlibmmIOChannel::io_seek,
-  &GlibmmIOChannel::io_close,
-  &GlibmmIOChannel::io_create_watch,
-  &GlibmmIOChannel::io_free,
-  &GlibmmIOChannel::io_set_flags,
-  &GlibmmIOChannel::io_get_flags,
+public:
+  static GlibmmIOChannel* get_instance(GIOChannel* channel);
+  bool is_anchored() const;
+  void set_anchored(bool anchored);
+  const RefPtr<IOChannel> get_wrapper() const;
+protected:
+  static const GIOFuncs vfunc_table_;
+  RefPtr<IOChannel> wrapper_;
+  bool anchored_;
 };
 
-
-/**** GLib::IOChannel ******************************************************/
+/**** Glib::IOChannel ******************************************************/
 
 /* Construct a custom C++-implemented IOChannel.  GlibmmIOChannel is an
  * extended GIOChannel struct which allows us to hook up a pointer to this
@@ -120,12 +132,9 @@ const GIOFuncs GlibmmIOChannel::vfunc_ta
  */
 IOChannel::IOChannel()
 :
-  gobject_ (static_cast<GIOChannel*>(g_malloc(sizeof(GlibmmIOChannel))))
+  gobject_(new GlibmmIOChannel(this))
 {
-  g_io_channel_init(gobject_);
-  gobject_->funcs = const_cast<GIOFuncs*>(&GlibmmIOChannel::vfunc_table);
-
-  reinterpret_cast<GlibmmIOChannel*>(gobject_)->wrapper = this;
+  set_manage();
 }
 
 /* Construct an IOChannel wrapper for an already created GIOChannel.
@@ -134,11 +143,13 @@ IOChannel::IOChannel()
  */
 IOChannel::IOChannel(GIOChannel* gobject, bool take_copy)
 :
-  gobject_ (gobject)
+  gobject_(gobject)
 {
+  set_manage();
+
   // This ctor should never be called for GlibmmIOChannel instances.
   g_assert(gobject != 0);
-  g_assert(gobject->funcs != &GlibmmIOChannel::vfunc_table);
+  g_assert(GlibmmIOChannel::get_instance(gobject) == 0);
 
   if(take_copy)
     g_io_channel_ref(gobject_);
@@ -146,29 +157,23 @@ IOChannel::IOChannel(GIOChannel* gobject
 
 IOChannel::~IOChannel()
 {
-  if(gobject_)
-  {
-    // Check whether this IOChannel is implemented in C++, i.e. whether it
-    // uses our GlibmmIOChannel forwarding backend.  Normally, this will never
-    // be true because the wrapper should only be deleted in the io_free()
-    // callback, which clears gobject_ before deleting.  But in case the ctor
-    // of a derived class threw an exception the GIOChannel must be destroyed
-    // prematurely.
-    //
-    if(gobject_->funcs == &GlibmmIOChannel::vfunc_table)
-    {
-      // Disconnect the wrapper object so that it won't be deleted twice.
-      reinterpret_cast<GlibmmIOChannel*>(gobject_)->wrapper = 0;
-    }
-
-    GIOChannel *const tmp_gobject = gobject_;
-    gobject_ = 0;
-
-    g_io_channel_unref(tmp_gobject);
-  }
+  // This destructor will never be invoked as a result of a derived class
+  // constructor throwing an exception, because C++ only calls the destructors
+  // of fully constructed objects. See Scott Meyers "More Effective C++" item
+  // 10 for more information:
+  // http://www.awprofessional.com/content/images/020163371x/items/item10.html
+  //
+  // Therefore, this destructor will only be invoked as a result of all
+  // references to this object being released. This means that we don't need
+  // to clean up the gobject_ pointer because either it points to a deleted
+  // GlibmmIOChannel or it points to a GIOChannel that was dereferenced by the
+  // ForeignIOChannel destructor.
+  //
+  // As a consequence of this, the GlibmmIOChannel destructor does not need
+  // to clear the gobject_ pointer in the wrapper, which is good.
 }
 
-Glib::RefPtr<IOChannel> IOChannel::create_from_file(const std::string& filename, const std::string& mode)
+RefPtr<IOChannel> IOChannel::create_from_file(const std::string& filename, const std::string& mode)
 {
   GError* error = 0;
   GIOChannel *const channel = g_io_channel_new_file(filename.c_str(), mode.c_str(), &error);
@@ -176,24 +181,24 @@ Glib::RefPtr<IOChannel> IOChannel::creat
   if(error)
     Glib::Error::throw_exception(error);
 
-  return Glib::wrap(channel, false);
+  return wrap(channel, false);
 }
 
-Glib::RefPtr<IOChannel> IOChannel::create_from_fd(int fd)
+RefPtr<IOChannel> IOChannel::create_from_fd(int fd)
 {
-  return Glib::wrap(g_io_channel_unix_new(fd), false);
+  return wrap(g_io_channel_unix_new(fd), false);
 }
 
 #ifdef G_OS_WIN32
 
-Glib::RefPtr<IOChannel> IOChannel::create_from_win32_fd(int fd)
+RefPtr<IOChannel> IOChannel::create_from_win32_fd(int fd)
 {
-  return Glib::wrap(g_io_channel_win32_new_fd(fd), false);
+  return wrap(g_io_channel_win32_new_fd(fd), false);
 }
 
-Glib::RefPtr<IOChannel> IOChannel::create_from_win32_socket(int socket)
+RefPtr<IOChannel> IOChannel::create_from_win32_socket(int socket)
 {
-  return Glib::wrap(g_io_channel_win32_new_socket(socket), false);
+  return wrap(g_io_channel_win32_new_socket(socket), false);
 }
 
 #endif /* G_OS_WIN32 */
@@ -296,12 +301,9 @@ std::string IOChannel::get_line_term() c
   return (term) ? std::string(term, len) : std::string();
 }
 
-Glib::RefPtr<IOSource> IOChannel::create_watch(IOCondition condition)
+RefPtr<IOSource> IOChannel::create_watch(IOCondition condition)
 {
-  // The corresponding unreference() takes place in the dtor
-  // of the Glib::RefPtr<IOChannel> object below.
-  reference();
-  return IOSource::create(Glib::RefPtr<IOChannel>(this), condition);
+  return IOSource::create(RefPtr<IOChannel>(this), condition);
 }
 
 IOStatus IOChannel::read_vfunc(char*, gsize, gsize&)
@@ -328,10 +330,10 @@ IOStatus IOChannel::close_vfunc()
   return IO_STATUS_ERROR;
 }
 
-Glib::RefPtr<Glib::Source> IOChannel::create_watch_vfunc(IOCondition)
+RefPtr<Glib::Source> IOChannel::create_watch_vfunc(IOCondition)
 {
   g_assert_not_reached();
-  return Glib::RefPtr<Glib::Source>();
+  return RefPtr<Glib::Source>();
 }
 
 IOStatus IOChannel::set_flags_vfunc(IOFlags)
@@ -348,45 +350,115 @@ IOFlags IOChannel::get_flags_vfunc()
 
 void IOChannel::reference() const
 {
-  g_io_channel_ref(gobject_);
+  GlibmmIOChannel* channel = GlibmmIOChannel::get_instance(gobject_);
+  if (channel && channel->is_anchored() == false)
+  {
+    g_io_channel_ref(gobject_); // pick up our reference to the GIOChannel
+    channel->set_anchored(true);
+  }
+
+  SigC::Object::reference();
 }
 
 void IOChannel::unreference() const
 {
-  g_io_channel_unref(gobject_);
+  GlibmmIOChannel* channel = GlibmmIOChannel::get_instance(gobject_);
+
+  SigC::Object::unreference();
+  
+  if (channel && channel->is_anchored() && get_refcount_() == 1)
+  {
+    channel->set_anchored(false);
+    g_io_channel_unref(gobject_); // drop our reference to the GIOChannel
+  }
+}
+
+unsigned long IOChannel::get_refcount_() const
+{
+  return const_cast<IOChannel*>(this)->control()->count_;
 }
 
-Glib::RefPtr<IOChannel> wrap(GIOChannel* gobject, bool take_copy)
+RefPtr<IOChannel> wrap(GIOChannel* channel, bool take_copy)
 {
   IOChannel* cpp_object = 0;
 
-  if(gobject)
+  if(channel)
   {
-    if(gobject->funcs == &GlibmmIOChannel::vfunc_table)
+    if(GlibmmIOChannel* object = GlibmmIOChannel::get_instance(channel))
     {
-      cpp_object = reinterpret_cast<GlibmmIOChannel*>(gobject)->wrapper;
-
-      if(take_copy && cpp_object)
-        cpp_object->reference();
+      if(take_copy)
+        g_io_channel_ref(object);
+      return object->get_wrapper();
     }
     else
-    {
-      cpp_object = SigC::manage(new ForeignIOChannel(gobject, take_copy));
-      cpp_object->reference(); // the SigC::Object refcount is initially 0
-    }
+      cpp_object = new ForeignIOChannel(channel, take_copy);
   }
 
-  return Glib::RefPtr<IOChannel>(cpp_object);
+  return RefPtr<IOChannel>(cpp_object);
 }
 
 
 /**** Glib::GlibmmIOChannel ************************************************/
 
 // static
+const GIOFuncs GlibmmIOChannel::vfunc_table_ =
+{
+  io_read,
+  io_write,
+  io_seek,
+  io_close,
+  io_create_watch,
+  io_free,
+  io_set_flags,
+  io_get_flags,
+};
+
+GlibmmIOChannel::GlibmmIOChannel(IOChannel *wrapper)
+:
+  anchored_(true)
+{
+  g_io_channel_init(this);
+  funcs = const_cast<GIOFuncs*>(&vfunc_table_);
+  wrapper_ = wrapper;
+}
+
+GlibmmIOChannel::~GlibmmIOChannel()
+{
+  // We need to explicitly release our reference to the IOChannel,
+  // because it is the last one and we want the unreference to
+  // happen before this GIOChannel is destroyed.
+
+  wrapper_ = 0;
+}
+
+// static
+GlibmmIOChannel* GlibmmIOChannel::get_instance(GIOChannel* channel)
+{
+  if (channel && channel->funcs == &vfunc_table_)
+    return static_cast<GlibmmIOChannel*>(channel);
+  return 0;
+}
+
+bool GlibmmIOChannel::is_anchored() const
+{
+  return anchored_;
+}
+
+void GlibmmIOChannel::set_anchored(bool anchored)
+{
+  anchored_ = anchored;
+}
+
+const RefPtr<IOChannel> GlibmmIOChannel::get_wrapper() const
+{
+  return wrapper_;
+}
+
+// static
 GIOStatus GlibmmIOChannel::io_read(GIOChannel* channel, char* buf, gsize count,
                                    gsize* bytes_read, GError** err)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
@@ -408,7 +480,7 @@ GIOStatus GlibmmIOChannel::io_read(GIOCh
 GIOStatus GlibmmIOChannel::io_write(GIOChannel* channel, const char* buf, gsize count,
                                     gsize* bytes_written, GError** err)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
@@ -429,7 +501,7 @@ GIOStatus GlibmmIOChannel::io_write(GIOC
 // static
 GIOStatus GlibmmIOChannel::io_seek(GIOChannel* channel, gint64 offset, GSeekType type, GError** err)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
@@ -450,7 +522,7 @@ GIOStatus GlibmmIOChannel::io_seek(GIOCh
 // static
 GIOStatus GlibmmIOChannel::io_close(GIOChannel* channel, GError** err)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
@@ -471,11 +543,11 @@ GIOStatus GlibmmIOChannel::io_close(GIOC
 // static
 GSource* GlibmmIOChannel::io_create_watch(GIOChannel* channel, GIOCondition condition)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
-    const Glib::RefPtr<Source> source = wrapper->create_watch_vfunc((IOCondition) condition);
+    const Glib::RefPtr<Source>& source = wrapper->create_watch_vfunc((IOCondition) condition);
     return (source) ? source->gobj_copy() : 0;
   }
   catch(...)
@@ -489,19 +561,13 @@ GSource* GlibmmIOChannel::io_create_watc
 // static
 void GlibmmIOChannel::io_free(GIOChannel* channel)
 {
-  if(IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper)
-  {
-    wrapper->gobject_ = 0;
-    delete wrapper;
-  }
-
-  g_free(channel);
+  delete get_instance(channel);
 }
 
 // static
 GIOStatus GlibmmIOChannel::io_set_flags(GIOChannel* channel, GIOFlags flags, GError** err)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
@@ -522,7 +588,7 @@ GIOStatus GlibmmIOChannel::io_set_flags(
 // static
 GIOFlags GlibmmIOChannel::io_get_flags(GIOChannel* channel)
 {
-  IOChannel *const wrapper = reinterpret_cast<GlibmmIOChannel*>(channel)->wrapper;
+  const RefPtr<IOChannel>& wrapper = get_instance(channel)->wrapper_;
 
   try
   {
@@ -537,4 +603,3 @@ GIOFlags GlibmmIOChannel::io_get_flags(G
 }
 
 } // namespace Glib
-


*** glib/src/iochannel.hg	14 Dec 2002 12:57:08 -0000	1.5
--- glib/src/iochannel.hg	24 Jan 2003 16:17:15 -0000
@@ -431,6 +431,7 @@ protected:
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
   IOChannel(GIOChannel* gobject, bool take_copy);
+  unsigned long get_refcount_() const;
 #endif
 
   virtual IOStatus read_vfunc(char* buf, gsize count, gsize& bytes_read);
@@ -449,4 +450,3 @@ protected:
 Glib::RefPtr<IOChannel> wrap(GIOChannel* gobject, bool take_copy = false);
 
 } // namespace Glib
-


*** gtk/gtkmm/menu_elems.cc	23 Jan 2003 23:46:34 -0000	1.16
--- gtk/gtkmm/menu_elems.cc	24 Jan 2003 16:17:16 -0000
@@ -40,10 +40,8 @@ Element::Element()
 {}
 
 Element::Element(MenuItem& child)
-{
-  child_ = Glib::RefPtr<MenuItem>(&child);
-  child_->reference(); //It's normally used with a create(), which starts with a refcount of 1.  
-}
+: child_(&child)
+{}
 
 Element::~Element()
 {}


*** gtk/src/container.ccg	20 Dec 2002 21:39:40 -0000	1.31
--- gtk/src/container.ccg	24 Jan 2003 16:17:18 -0000
@@ -53,15 +53,11 @@ namespace Gtk
 void Container_Class::remove_callback_custom(GtkContainer* self, GtkWidget* p0)
 {
   //GTKMM_LIFECYCLE
-  //Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted - just call the original C callback.
-  bool gtkmm_child_already_deleted = Glib::_gobject_cppinstance_already_deleted((GObject*)p0);
 
-  if(!gtkmm_child_already_deleted)
-  {
-    //Call the regular, generated callback:
-    Container_Class::remove_callback(self, p0);
-  }
-  else
+  //Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted.
+  //Just call the original C callback.
+
+  if(Widget::_wrapper_disconnected(G_OBJECT(p0)))
   {
     BaseClassType *const base = static_cast<BaseClassType*>(
         g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
@@ -70,6 +66,11 @@ void Container_Class::remove_callback_cu
     //Call the original underlying C function:
     if(base && base->remove)
       (*base->remove)(self, p0);
+  }
+  else
+  {
+    //Call the regular, generated callback:
+    Container_Class::remove_callback(self, p0);
   }
 }
 


*** gtk/src/object.ccg	20 Dec 2002 21:39:40 -0000	1.36
--- gtk/src/object.ccg	24 Jan 2003 16:17:20 -0000
@@ -24,46 +24,69 @@
 namespace Gtk
 {
 
+//----------------------------------------------------------------------
+// construction
+//----------------------------------------------------------------------
+
 Object::Object(const Glib::ConstructParams& construct_params)
 :
-  Glib::Object(construct_params)
+  Glib::Object(construct_params),
+  was_floating_(false),
+  in_destructor_(false)
 {
-   gobject_disposed_ = false;
-
   _init_unmanage(); //We don't like the GTK+ default memory management - we want to be in control._)
 }
 
 Object::Object(GtkObject* castitem)
 :
-  Glib::Object((GObject*) castitem)
+  Glib::Object((GObject*) castitem),
+  was_floating_(false),
+  in_destructor_(false)
 {
-  gobject_disposed_ = false;
-
-   _init_unmanage(); //We don't like the GTK+ default memory management - we want to be in control.
+  _init_unmanage(); //We don't like the GTK+ default memory management - we want to be in control.
 }
 
 void Object::_init_unmanage(bool /* is_toplevel = false */)
 {
   //GTKMM_LIFECYCLE
-  referenced_ = true; //Not managed.
 
-  //g_warning("Object::_init_unmanage(): %s\n", G_OBJECT_TYPE_NAME(gobject_));
+  Glib::Object::set_manage(false);
 
-  if(gobject_)
+  if(gobj())
   {
-    //Glib::Object::Object has already stored a pointer to this C++ instance in the underlying C instance,
-    //and connected a callback which will, in turn, call our destroy_notify_(),
-    //so will will know if GTK+ disposes of the underlying instance.
-
-    // Most GTK+ objects are floating, by default. This means that the container widget controls their lifetime.
-    // We'll change this:
-    if(GTK_OBJECT_FLOATING (gobject_)) //Top-level Windows and Dialogs can not be manag()ed, so there is no need to do this.
+    // Glib::Object::Object has already stored a pointer to this wrapper in the
+    // underlying GtkObject and connected a callback which will in turn call our
+    // destroy_notify_(), so we will know if GTK+ disposes of the GtkObject.
+    //
+    // Most GTK+ widgets are floating by default. This means that there is an
+    // un-owned "floating" reference to the widget. If the widget is added to a
+    // container, then the container obtains a non-floating reference to the widget
+    // and then removes the floating reference by calling gtk_object_sink().
+    // Subsequently the container owns the widget and controls its lifetime.
+    //
+    // If the floating reference has already been removed, gtk_object_sink() does
+    // nothing.
+    //
+    // We'll change this initial state by taking a non-floating reference here and
+    // sinking the GtkObject if it is floating. This can later be changed by calling
+    // set_manage() on the wrapper, which enables reference counting on the wrapper
+    // and changes our non-floating reference back to a floating reference.
+    //
+    // If the widget is added to a container after we sink it here, then the
+    // container will have an additional non-floating reference.
+
+    #ifdef GTKMM_DEBUG_REFCOUNTING
+    g_warning("Object::_init_unmanage(): %s\n", G_OBJECT_TYPE_NAME(gobject_));
+    #endif
+
+    if(was_floating_ = GTK_OBJECT_FLOATING(gobj()))
     {
-      //g_warning("Object::_init_unmanage(), object was floating: %s\n", G_OBJECT_TYPE_NAME(gobject_));
+      #ifdef GTKMM_DEBUG_REFCOUNTING
+      g_warning("Object::_init_unmanage(), object was floating: %s\n", G_OBJECT_TYPE_NAME(gobj()));
+      #endif
 
-      GTKMM_DEBUG_REFERENCE(this, gobject_);
-      g_object_ref(gobject_);  //Increase ref by 1 so that it doesn't get deleted when we sink() it (sink()ing does an unref)
-      gtk_object_sink((GtkObject*)gobject_); //Stops it from being floating - we will make this optional ( see Gtk::manage() ),
+      g_object_ref(gobj()); // Take ownership of the GtkObject
+      gtk_object_sink(gobj()); // Remove the floating reference
 
       #ifdef GTKMM_DEBUG_REFCOUNTING
       g_warning("gtkmm after sink: C++ instance: %10X, C instance: %10X, refcount=%d\n", (Glib::ObjectBase*)this, gobject_, G_OBJECT(gobject_)->ref_count);
@@ -72,243 +95,216 @@ void Object::_init_unmanage(bool /* is_t
     }
     else
     {
-       //This widget is already not floating. It's probably already been added to a GTK+ container, and has just had Glib::wrap() called on it.
-       //It's not floating because containers call gtk_object_sink() on child widgets to take control of them.
-       //We just ref() it so that we can unref it later.
-       g_object_ref(gobject_);
-       //This has the added side-effect that, because the refcount is now >1, the refcount check in set_manage() prevents us from refloating a widget that's been sunk when added to a container.
+      // This widget is already not floating. This means one of two things:
+      //
+      // 1) It's already owned by another entity (probably a GTK+ container). It's not
+      //    floating because the owner called gtk_object_sink() on it to take control
+      //    of it. The owner has a non-floating reference to the widget.
+      //
+      // 2) It's a GtkWindow (i.e. a top-level window or dialog). In this case, GTK+
+      //    owns a non-floating reference to the widget.
+      //
+      // In either case, we obtain our own reference, which we release in destroy_().
+      // This ensures that the widget stays alive until we're done with it.
 
-       //Alternatively, it might be a top-level window (e.g. a Dialog). We would then be doing one too-many refs(),
-       //We do an extra unref() in Window::_destroy_c_instance() to take care of that.
+      g_object_ref(gobj());
     }
-  }
-}
-
-void Object::_destroy_c_instance()
-{
-  #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Object::_destroy_c_instance() this=%10X, gobject_=%10X\n", this, gobject_);
-    if(gobject_)
-      g_warning("gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-  #endif
-
-  cpp_destruction_in_progress_ = true;
-
-  // remove our hook.
-  GtkObject* object = gobj();
-  if (object)
-  {
-    g_assert(GTK_IS_OBJECT(object));
 
-    disconnect_cpp_wrapper();
-    //Unfortunately this means that our dispose callback will not be called, because the qdata has been removed.
-    //So we'll connect the callback again, just so that gobject_disposed_ gets set for use later in this same method.
-    //See below:
-
-    //This probably isn't a problem now:
-    //If we are killing the C++ instance before the C instance, then this might lead to strange behaviour.
-    //If this is a problem, then you'll have to use a managed() object, which will die only upon GTK+'s request.
-
-    //We can't do anything with the gobject_ if it's already been disposed.
-    //This prevents us from unref-ing it again, or destroying it again after GTK+ has told us that it has been disposed.
-    if (!gobject_disposed_)
-    {
-      if(referenced_)
-      {
-        //It's not manage()ed so we just unref to destroy it
-        #ifdef GTKMM_DEBUG_REFCOUNTING
-        g_warning("final unref: gtypename: %s, refcount: %d\n", G_OBJECT_TYPE_NAME(object), ((GObject*)object)->ref_count);
-        #endif
-
-        //Because we called disconnect_cpp_wrapper() our dispose callback will not be called, because the qdata has been removed.
-        //So we'll connect a callback again, just so that gobject_disposed_ gets set for use later in this same method.
-        gulong connection_id_destroy = g_signal_connect (object, "destroy", G_CALLBACK (&callback_destroy_), this);
-
-        GTKMM_DEBUG_UNREFERENCE(this, object);
-        g_object_unref(object);
-
-        if(!gobject_disposed_) //or if(g_signal_handler_is_connected(object, connection_id_destroy))
-          g_signal_handler_disconnect(object, connection_id_destroy);
-
-        //destroy_notify() should have been called after the final g_object_unref() or gtk_object_destroy(), so gobject_disposed_ should now be true.
-
-        //If the C instance still isn't dead then insist, by calling gtk_object_destroy().
-        //This is necessary because even a manage()d widget is refed when added to a container.
-        // <danielk> That's simply not true.  But references might be taken elsewhere,
-        // and gtk_object_destroy() just tells everyone "drop your refs, please!".
-        if (!gobject_disposed_)
-        {
-          #ifdef GTKMM_DEBUG_REFCOUNTING
-          g_warning("Gtk::Object::_destroy_c_instance(): Calling gtk_object_destroy(): gobject_=%10X, gtypename=%s\n", object, G_OBJECT_TYPE_NAME(object));
-          #endif
-
-          g_assert(GTK_IS_OBJECT(object));
-          gtk_object_destroy(object); //Container widgets can respond to this.
-        }
-      }
-      else
-      {
-        //It's manag()ed, but the coder decided to delete it before deleting its parent.
-        //That should be OK because the Container can respond to that.
-        #ifdef GTKMM_DEBUG_REFCOUNTING
-        g_warning("Gtk::Object::_destroy_c_instance(): Calling gtk_object_destroy(): gobject_=%10X\n", gobject_);
-        #endif
-
-        if (!gobject_disposed_)
-        {
-          g_assert(GTK_IS_OBJECT(object));
-          gtk_object_destroy(object);
-        }
-      }
-    }
-
-    //Glib::Object::~Object() will not g_object_unref() it too. because gobject_ is now 0.
+    // At this point, we own a non-floating reference to the widget. If set_manage() is
+    // called later, it will convert our reference to a floating reference or release it,
+    // depending on whether we sunk the widget or not.
   }
 }
 
+//----------------------------------------------------------------------
+// destruction
+//----------------------------------------------------------------------
+
 Object::~Object()
 {
-  #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Object::~Object() gobject_=%10X\n", gobject_);
-  #endif
-
-  //This has probably been called already from Gtk::Object::_destroy(), which is called from derived destructors.
-  _destroy_c_instance();
+  destroy_();
 }
 
-void Object::disconnect_cpp_wrapper()
-{
-  //GTKMM_LIFECYCLE:
-
-  #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Object::disconnect_cpp_wrapper() this=%10X, gobject_=%10X\n", this, gobject_);
-    if(gobject_)
-      g_warning("gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-  #endif
-
-  if(gobj())
-  {
-    //Prevent gtk vfuncs and default signal handlers from calling our instance methods:
-    g_object_steal_qdata((GObject*)gobj(), Glib::quark_); //It will no longer be possible to get the C++ instance from the C instance.
-
-    //Allow us to prevent generation of a new C++ wrapper during destruction:
-    g_object_set_qdata((GObject*)gobj(), Glib::quark_cpp_wrapper_deleted_, (gpointer)true);
-
-    //Prevent C++ instance from using GTK+ object:
-    gobject_ = 0;
-
-    //TODO: Disconnect any signals, using gtk methods.
-    //We'll have to keep a record of all the connections.
-  }
-}
-
-void Object::destroy_notify_()
+void Object::destroy_()
 {
-  //Overriden.
   //GTKMM_LIFECYCLE
 
+  // This method is called from the destructors of all classes derived from
+  // Gtk::Object. We do the work of destroying the GtkObject here rather than
+  // in Gtk::Object::~Object() so that signal handlers and callbacks of derived
+  // classes can be called while the GtkObject is being disposed. This is only
+  // an issue for unmanaged wrappers, because managed wrappers are not deleted
+  // until after the GtkObject has been disposed.
+  //
+  // At this point, one of two conditions will hold:
+  //
+  // 1) The gobject_ member will be zero, which means that either it was
+  //    disposed by GTK+ and the wrapper was deleted because it was managed,
+  //    or that the member has already been cleared in a derived class's
+  //    destructor. In either case, we have nothing to do.
+  // 2) The gobject_ member will be non-zero, which means that the GtkObject
+  //    has not been disposed yet. In this case, we destroy it here. This can
+  //    happen if a managed wrapper is prematurely deleted by a programmer
+  //    (which would be a potential disaster and ideally should never happen)
+  //    or if an unmanaged wrapper is destroyed normally.
+
+  // This probably isn't a problem now:
+  // If we are killing the wrapper before the GtkObject, then this might lead
+  // to strange behaviour. If this is a problem, then you'll have to use a managed
+  // object, which will coordinate the lifetimes of the wrapper and the GtkObject.
+
   #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Object::destroy_notify_: this=%10X, gobject_=%10X\n", this, gobject_);
-  if(gobject_)
-    g_warning("  gtypename=%s\n", G_OBJECT_TYPE_NAME(gobject_));
+  g_warning("Gtk::Object::destroy_() this=%10X, gobject_=%10X\n", this, gobj());
+  if(gobj())
+    g_warning("gtypename: %s\n", G_OBJECT_TYPE_NAME(gobj()));
   #endif
 
-  //Remember that it's been disposed (which only happens once):
-  //This also stops us from destroying it again in the destructor when it calls destroy_().
-  gobject_disposed_ = true;
+  in_destructor_ = true;
 
-  if(!cpp_destruction_in_progress_) //This function might have been called as a side-effect of destroy() when it called gtk_object_destroy().
+  GtkObject* const object = gobj();
+  if (object)
   {
-    if (!referenced_) //If it's manage()ed.
+    g_assert(GTK_IS_OBJECT(object));
+
+    // If this wrapper is unmanaged, then we hold a non-floating reference to
+    // the GtkObject and we release our reference here. The destroy_notify
+    // callback will be called if the GtkObject gets disposed, which is OK for
+    // an unmanaged wrapper because it won't recursively delete the wrapper.
+    //
+    // Because a Gtk::Window is always unmanaged, we will always do this
+    // unref(), which counters the ref() that we did in _init_unmanage(). The
+    // GtkWindow should still be alive after the unref() because GTK+ holds a
+    // non-floating reference to it. We destroy the GtkWindow further on by
+    // calling gtk_object_destroy(), which causes GTK+ to release its reference.
+
+    if (is_managed_() == false)
     {
       #ifdef GTKMM_DEBUG_REFCOUNTING
-      g_warning("Gtk::Object::destroy_notify_: before delete this.\n");
+      g_warning("final unref: gtypename: %s, refcount: %d\n", G_OBJECT_TYPE_NAME(object),
+        G_OBJECT(object)->ref_count);
       #endif
-      delete this; //Free the C++ instance.
+
+      g_object_unref(object);
     }
-    else  //It's not managed, but the C gobject_ just died before the C++ instance..
+
+    // If the GtkObject still isn't dead then it is either floating (which
+    // should not happen) or is being referenced elsewhere. We force the other
+    // references to be released by calling gtk_object_destroy().
+    //
+    // We un-manage the wrapper first so that the destroy_notify callback
+    // will not recursively delete the wrapper.
+
+    if (gobj())
     {
       #ifdef GTKMM_DEBUG_REFCOUNTING
-      g_warning("Gtk::Object::destroy_notify_: setting gobject_ to 0\n");
+      g_warning("Gtk::Object::_destroy(): Calling gtk_object_destroy(): gobject_=%10X, gtypename=%s\n",
+        object, G_OBJECT_TYPE_NAME(object));
       #endif
-      gobject_ = 0;
+
+      Glib::Object::set_manage(false); // Ensure wrapper does not get deleted again
+      gtk_object_destroy(object); // Container widgets will respond to this
+      disconnect_wrapper_(); // In case some other entity didn't release its ref
     }
+
+    // Glib::Object::~Object() will not g_object_unref() it too, because gobject_ is now 0.
   }
+}
 
+bool Object::is_in_destructor_() const
+{
+  return in_destructor_;
 }
 
-void Object::destroy_()
+//----------------------------------------------------------------------
+// public methods
+//----------------------------------------------------------------------
+
+// override
+void Object::reference() const
 {
-  //Called from destructors.
-  //GTKMM_LIFECYCLE
+  GObject* const object = gobject_;
 
-  #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Object::destroy_(): gobject_: %10X\n", gobject_);
-  if(gobject_)
-   g_warning("  gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-  #endif
+  // We shadow every wrapper reference in the GtkObject, because we might
+  // not have a permanent reference to the GtkObject and we want to ensure
+  // that it will stay alive so long as there are references to the wrapper.
+  //
+  // We shadow references even if the wrapper is unmanaged, because if the
+  // wrapper is referenced and then set_manage() is called, we will need
+  // the shadow references to be in place already.
+  //
+  // We check the GtkObject ref_count before shadowing the reference. It's
+  // possible for the wrapper to be referenced during disposal of the
+  // GtkObject, in which case we should not be ref()ing or unref()ing it.
 
-  if ( !cpp_destruction_in_progress_ ) //see comment below.
-  {
-    //Prevent destroy_notify_() from running as a possible side-effect of gtk_object_destroy.
-    //We can't predict whether destroy_notify_() will really be run, so we'll disconnect the C++ instance here.
-    cpp_destruction_in_progress_ = true;
+  if (object && object->ref_count > 0)
+    g_object_ref(object);
+  Glib::Object::reference();
+}
 
-    //destroy the C instance:
-    _destroy_c_instance();
-  }
+// override
+void Object::unreference() const
+{
+  GObject* const object = gobject_;
 
-  //The C++ destructor will be reached later. This function was called by a destructor.
+  // See commentary above in reference() regarding shadow references. We
+  // release the shadow reference here, if we still have a GtkObject by
+  // this time. We get the value of gobject_ before we unreference() the
+  // wrapper, because the wrapper could be deleted.
+
+  Glib::Object::unreference();
+  if (object && object->ref_count > 0)
+    g_object_unref(object);
 }
 
 void Object::set_manage() 
 {
   //GTKMM_LIFECYCLE
-  //This object will not be unref()ed by gtkmm, though it could be destroyed if the coder deletes the C++ instance early.
-  //This method is overriden in Gtk::Window because they can not be manage()ed.
-
-  if (!referenced_) return; //It's already managed.
 
-  // tell libsigc that the object is disposable
-  SigC::ObjectBase::set_manage();
+  // A managed Gtk::Object wrapper is associated with an initially floating
+  // GtkObject. Prior to entering set_manage() we have a non-floating
+  // reference to the GtkObject that we obtained in _init_unmanage().
+  //
+  // If we own the GtkObject, then we give up ownership by converting our
+  // reference to a floating reference. If we don't own the GtkObject, then
+  // we just release our reference. Either way, we must not call
+  // g_object_unref() later to release the reference.
+  //
+  // While it's possible that we could float a widget that was added to a
+  // container after we sunk it, in practice that is unlikely to happen
+  // because gtkmm internals call set_manage() on a wrapper immediately after
+  // creating it if at all. Even if it does happen, since a container will
+  // usually call gtk_object_destroy() on its children when the container is
+  // disposed, no resource leak should result.
+  //
+  // After this, the GtkObject will stay alive until it is disposed by GTK+
+  // and it will keep the wrapper alive as well. When the GtkObject is
+  // disposed, the wrapper is automatically deleted.
 
-  // remove our reference
-  if (gobject_->ref_count >= 1) //This should only happen just after creation. We don't use "==1" because GtkButton starts with a refcount of 2 when using a mnemonic.
+  if (is_managed_() == false)
   {
-    //g_warning("Object::set_manage(), making object floating: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-
-    // Cowardly refuse to remove last reference make floating instead. //TODO: What does that comment mean?
-    GTK_OBJECT_SET_FLAGS(gobj(), GTK_FLOATING);
+    Glib::Object::set_manage(); // Enable reference-counting for the C++ wrapper
+    release_reference_(); // Release our initial reference to the GtkObject
   }
-  else
-  {
-    //g_warning("Object::set_manage(), not sinking, just unrefing: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-
-    //DEF_GTKMM_DEBUG_UNREF(this, gobj())
-    //g_object_unref(gobj());
-  }
-
-  //g_warning("Object::set_manage(): end: %s", G_OBJECT_TYPE_NAME(gobject_));
-  //g_warning("  refcount=%d", G_OBJECT(gobj())->ref_count);
-
-  referenced_ = false;
 }
 
-void Object::callback_destroy_(GObject*, void* data) //static
-{
-  //This is only used for a short time, then disconnected.
+//----------------------------------------------------------------------
+// private methods
+//----------------------------------------------------------------------
 
-  Object* cppObject = static_cast<Object*>(data);
-  if(cppObject) //This will be 0 if the C++ destructor has already run.
+// override
+void Object::release_reference_()
+{
+  if (gobj())
   {
-    cppObject->gobject_disposed_ = true;
-  }
-}
+    g_object_ref(gobj()); // get an extra reference
 
-bool Object::is_managed_() const
-{
-  return !referenced_;
+    Glib::Object::release_reference_(); // give up our initial reference
+
+    if (was_floating_) // If we sunk the widget
+      GTK_OBJECT_SET_FLAGS(gobj(), GTK_FLOATING); // Then float it again
+    else // If the widget was already sunk
+      g_object_unref(gobj()); // Then just give up our extra reference
+  }
 }
 
 } // namespace Gtk
-


*** gtk/src/object.hg	21 Oct 2002 13:18:57 -0000	1.35
--- gtk/src/object.hg	24 Jan 2003 16:17:25 -0000
@@ -46,29 +46,28 @@ public:
   //void set_user_data(gpointer data);
   //gpointer get_user_data();
 
-  virtual void set_manage();
+  virtual void reference() const; // overrides Glib::Object::reference()
+  virtual void unreference() const; // overrides Glib::Object::unreference()
+  virtual void set_manage(); // hides Glib::Object::set_manage
 
   _WRAP_PROPERTY("user-data", void*)
 
-  bool is_managed_() const;
-
 protected:
-
   void destroy_();
+  bool is_in_destructor_() const;
 
   // If you need it, give me an example. murrayc. -- Me too. daniel.
   //_WRAP_SIGNAL(void destroy(), "destroy")
   _IGNORE_SIGNAL(destroy)
 
-  void _init_unmanage(bool is_toplevel = false);
-  virtual void destroy_notify_(); //override.
-  void disconnect_cpp_wrapper();
-  void _destroy_c_instance();
-  static void callback_destroy_(GObject* gobject, void* data); //only connected for a short time.
+private:
+  bool was_floating_;
+  bool in_destructor_;
 
-  // set if flags used by derived classes.
-  bool referenced_; // = not managed.
-  bool gobject_disposed_;
+  void _init_unmanage(bool is_toplevel = false);
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  virtual void release_reference_(); // overrides Glib::Object::release_reference_()
+#endif
 };
 
 } // namespace Gtk


*** gtk/src/widget.ccg	23 Dec 2002 04:27:15 -0000	1.39
--- gtk/src/widget.ccg	24 Jan 2003 16:17:26 -0000
@@ -199,59 +199,61 @@ void Widget::drag_set_as_icon(const Glib
 void Widget_Class::hierarchy_changed_callback_custom(GtkWidget* self, GtkWidget* p0)
 {
   //GTKMM_LIFECYCLE
-  //Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted - just call the original C callback.
-  bool gtkmm_child_already_deleted = Glib::_gobject_cppinstance_already_deleted((GObject*)p0);
 
-  if(!gtkmm_child_already_deleted)
-  {
-    //Call the regular, generated callback:
-    Widget_Class::hierarchy_changed_callback(self, p0);
-  }
-  else
+  // Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted.
+  // Just call the original C callback.
+
+  if(Widget::_wrapper_disconnected(G_OBJECT(p0)))
   {
     BaseClassType *const base = static_cast<BaseClassType*>(
         g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
     );
 
-    //Call the original underlying C function:
+    // Call the original underlying C function:
     if(base && base->hierarchy_changed)
       (*base->hierarchy_changed)(self, p0);
   }
+  else
+  {
+    // Call the regular, generated callback:
+    Widget_Class::hierarchy_changed_callback(self, p0);
+  }
 }
 
 void Widget_Class::parent_set_callback_custom(GtkWidget* self, GtkWidget* p0)
 {
   //GTKMM_LIFECYCLE
-  //Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted - just call the original C callback.
-  bool gtkmm_p0_already_deleted = Glib::_gobject_cppinstance_already_deleted((GObject*)p0);
 
-  if(!gtkmm_p0_already_deleted)
-  {
-    //Call the regular, generated callback:
-    Widget_Class::parent_set_callback(self, p0);
-  }
-  else
+  // Don't call wrap() on a GTK+ instance whose gtkmm instance has been deleted.
+  // Just call the original C callback.
+
+  if(Widget::_wrapper_disconnected(G_OBJECT(p0)))
   {
     BaseClassType *const base = static_cast<BaseClassType*>(
         g_type_class_peek_parent(G_OBJECT_GET_CLASS(self)) // Get the parent class of the object class (The original underlying C class).
     );
 
-    //Call the original underlying C function:
+    // Call the original underlying C function:
     if(base && base->parent_set)
       (*base->parent_set)(self, p0);
   }
+  else
+  {
+    // Call the regular, generated callback:
+    Widget_Class::parent_set_callback(self, p0);
+  }
 }
 
 void Widget_Class::dispose_vfunc_callback(GObject* self)
 {
-  Widget *const obj = dynamic_cast<Widget*>(
-      Glib::ObjectBase::_get_current_wrapper(self));
+  Widget *const obj = dynamic_cast<Widget*>(Widget::_get_current_wrapper(self));
 
   // This function might be invoked recursively because we're triggering
-  // several signal emissions, particularly signal_hide().  Therefore we
-  // have to test for cpp_destruction_in_progress_ at this point.
+  // emission of signal_hide(). Therefore we have to test for wrapper destruction
+  // in progress at this point. If the wrapper is being destroyed, we want to
+  // let the dispose happen normally.
 
-  if(obj && !obj->cpp_destruction_in_progress_)
+  if(obj && !obj->is_in_destructor_())
   {
     GtkWidget *const pWidget = obj->gobj();
     g_return_if_fail(pWidget == GTK_WIDGET(self));
@@ -260,10 +262,21 @@ void Widget_Class::dispose_vfunc_callbac
     // the nasty self-destroying behaviour of GTK+.  This applies to:
     //
     // - GtkWindow, if it received "delete_event"
-    // - GtkDialog, which destroys on "response" by default
     // - any widget inside a GtkContainer on gtk_container_destroy()
+    //
+    // GtkDialog explicitly does _not_ destroy the widget when
+    // gtk_dialog_response() is invoked. See the GTK+ docs.
+    //
+    // The "self-destroying behavior" of GTK+ would not be a problem
+    // except that the GObject class dispose method destroys the
+    // signal handlers that have connected to the object, even though
+    // it can't be sure that the object is going to be destroyed.
+    // GObject then redundantly destroys the signal handlers when the
+    // last reference is released. GObject should probably only do
+    // the latter. If that ever happens, we can do away with this
+    // kludge.
 
-    if(obj->referenced_)
+    if(obj->is_managed_() == false)
     {
       // GTKMM_LIFECYCLE
       // Remove the widget from its parent container so that it
@@ -272,8 +285,8 @@ void Widget_Class::dispose_vfunc_callbac
       {
         // Normally, we would have to ref the child widget because
         // gtk_container_remove() unrefs it.  But since we only remove
-        // non-managed objects here, the container just releases the
-        // reference it has acquired before in gtk_container_add().
+        // non-managed objects here, the reference held by the wrapper
+        // keeps the widget alive.
 
         gtk_container_remove(GTK_CONTAINER(pWidget->parent), pWidget);
       }


*** gtk/src/window.ccg	20 Dec 2002 21:39:40 -0000	1.30
--- gtk/src/window.ccg	24 Jan 2003 16:17:27 -0000
@@ -63,67 +63,5 @@ void Window::set_manage()
   g_warning("gtkmm: Attempt to call Gtk::manage() on a Gtk::Window, but a Gtk::Window has no parent container to manage its lifetime.\n");
 }
 
-void Window::destroy_()
-{
-  //Called from destructors.
-  //overridden so that the correct _destroy_c_instance() ends up being called by the destructor.
-
-  //GTKMM_LIFECYCLE
-
-  #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Window::destroy_(): gobject_: %10X\n", gobject_);
-  if(gobject_)
-   g_warning("  gtypename: %s\n", G_OBJECT_TYPE_NAME(gobject_));
-  #endif
-
-  if ( !cpp_destruction_in_progress_ ) //see comment below.
-  {
-    //Prevent destroy_notify_() from running as a possible side-effect of gtk_object_destroy.
-    //We can't predict whether destroy_notify_() will really be run, so we'll disconnect the C++ instance here.
-    cpp_destruction_in_progress_ = true;
-
-    //destroy the C instance:
-    _destroy_c_instance();
-  }
-
-  //The C++ destructor will be reached later. This function was called by a destructor.
-}
-
-void Window::_destroy_c_instance()
-{
-  //We override this,
-  //because though top-level windows can only be destroyed with gtk_widget_destroy, according to Owen Taylor. murrayc.
-  #ifdef GTKMM_DEBUG_REFCOUNTING
-  g_warning("Gtk::Window::_destroy_c_instance() gobject_=%10X\n", gobject_);
-  #endif
-
-  cpp_destruction_in_progress_ = true;
-
-  // remove our hook.
-  GtkObject* object = (GtkObject*)gobj();
-  if (object)
-  {
-    disconnect_cpp_wrapper();
-    //If we are killing the C++ instance before the C instance, then this might lead to strange behaviour.
-    //If this is a problem, then you'll have to use a managed() object, which will die only upon GTK+'s request.
-
-    //We can't do anything with the gobject_ if it's already been disposed.
-    //This prevents us from unref-ing it again, or destroying it again after GTK+ has told us that it has been disposed.
-    if (!gobject_disposed_)
-    {
-        //Windows can not be unrefed. They are "self-owning".
-        #ifdef GTKMM_DEBUG_REFCOUNTING
-        g_warning("Gtk::Window::_destroy_c_instance(): Calling gtk_object_destroy(): gobject_=%10X\n", object);
-        #endif
-        g_object_unref(object); //We ref()ed it one too many times to simplify our _init_unmanage() code.
-
-        if(!gobject_disposed_) //Just in case that unref() really destroyed it, in which case our dispose callack would have just been called.
-          gtk_object_destroy(object);
-      }
-
-    //Glib::Object::~Object() will not g_object_unref() it too. because gobject_ is now 0.
-  }
-}
-
 } /* namespace Gtk */
 


*** gtk/src/window.hg	20 Jan 2003 11:52:31 -0000	1.56
--- gtk/src/window.hg	24 Jan 2003 16:17:28 -0000
@@ -281,12 +281,6 @@ public:
   ///Overriden to warn that it doesn't make sense to use Gtk::manage() on this class because it has no parent container.
   virtual void set_manage();
 
-protected:
-
-  //See comments in the implementations:
-  void destroy_();
-  void _destroy_c_instance();
-
 private:
 
   //We'll create an accel_group if it's requested, and remember it.


*** tools/m4/class_gobject.m4	30 Jun 2002 15:01:26 -0000	1.20
--- tools/m4/class_gobject.m4	24 Jan 2003 16:17:30 -0000
@@ -132,8 +132,7 @@ Glib::ObjectBase* __CPPNAME__`'_Class::w
 
 __CNAME__* __CPPNAME__::gobj_copy()
 {
-  reference();
-  return gobj();
+  return reinterpret_cast<__CNAME__*>(__CPPPARENT__::gobj_copy());
 }
 
 __CPPNAME__::__CPPNAME__`'(const Glib::ConstructParams& construct_params)
@@ -186,9 +185,10 @@ protected:
 
 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
 
-public:
+protected:
   virtual ~__CPPNAME__`'();
 
+public:
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
   static GType get_type()      G_GNUC_CONST;
   static GType get_base_type() G_GNUC_CONST;


