[glibmm] Glib::Binding: Keep a binding alive even without a RefPtr



commit dc92d02f4d50851a1af59e5fbe2a753dcfd2e9df
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Sun Dec 15 15:43:37 2019 +0100

    Glib::Binding: Keep a binding alive even without a RefPtr
    
    A binding between properties can remain even after all RefPtr<Binding>s
    are gone. This is similar to how Gtk::Widget::set_controller() works
    in gtkmm4.
    
    Fixes #62, see !21

 glib/src/binding.ccg         | 20 --------------------
 glib/src/binding.hg          | 18 ++++++------------
 tests/glibmm_binding/main.cc | 13 +++++++++----
 3 files changed, 15 insertions(+), 36 deletions(-)
---
diff --git a/glib/src/binding.ccg b/glib/src/binding.ccg
index dfad8a66..0c07a07c 100644
--- a/glib/src/binding.ccg
+++ b/glib/src/binding.ccg
@@ -125,24 +125,4 @@ Binding::unbind()
     g_binding_unbind(gobj());
 }
 
-// Override unreference() from ObjectBase.
-//
-// Why is this necessary? Because GBinding is an unusual kind of GObject.
-// It calls g_object_unref() itself, if either the source object or the
-// target object is finalized, almost like g_binding_unbind().
-// But the GBinding object shall be destroyed when and only when the last
-// reference from a Glib::RefPtr is dropped.
-void
-Binding::unreference() const
-{
-  GBinding* const binding = const_cast<GBinding*>(gobj());
-
-  // If the last Glib::RefPtr is being deleted, and the binding has not been unbound,
-  // then drop the extra reference that was added by bind_property_value().
-  if (gobject_->ref_count == 2 && g_binding_get_source(binding))
-    g_object_unref(binding);
-
-  Object::unreference();
-}
-
 } // namespace Glib
diff --git a/glib/src/binding.hg b/glib/src/binding.hg
index c6849e17..98bc3fc6 100644
--- a/glib/src/binding.hg
+++ b/glib/src/binding.hg
@@ -29,7 +29,7 @@ namespace Glib
 
 /** Bind two object properties.
  *
- * Glib::Binding is the representation of a binding between a property on a
+ * %Glib::Binding is the representation of a binding between a property on a
  * Glib::ObjectBase instance (or source) and another property on another Glib::ObjectBase
  * instance (or target). Whenever the source property changes, the same
  * value is applied to the target property; for instance, the following binding:
@@ -90,10 +90,11 @@ namespace Glib
  * various ways of blocking a signal emission, like Glib::SignalProxyNormal::emission_stop()
  * or g_signal_handler_block().
  *
- * A binding will be severed, and the resources it allocates freed, whenever
- * either one of the Glib::ObjectBase instances it refers to is deleted,
- * when unbind() is called, or when the Glib::Binding instance loses
- * its last reference.
+ * The binding between the two properties is broken whenever either one of the
+ * Glib::ObjectBase instances it refers to is deleted or when unbind() is called.
+ * If a RefPtr<Binding> remains after the binding has been broken, get_source()
+ * and get_target() return a <tt>nullptr</tt>. It's not necessary to keep a
+ * RefPtr<Binding> in order to keep the binding alive.
  *
  * @newin{2,44}
  */
@@ -407,13 +408,6 @@ public:
   _WRAP_PROPERTY("target", Glib::RefPtr<Glib::ObjectBase>, newin "2,44")
   _WRAP_PROPERTY("target-property", Glib::ustring, newin "2,44")
 
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-  /** Decrement the reference count for this object.
-   * You should never need to do this manually - use the object via a RefPtr instead.
-   */
-  void unreference() const override;
-#endif /* DOXYGEN_SHOULD_SKIP_THIS */
-
 private:
   // The functor TransformProp can be implicitly converted to a SlotTransform
   // and used in a call to bind_property_value().
diff --git a/tests/glibmm_binding/main.cc b/tests/glibmm_binding/main.cc
index 9b727e51..4d0bacc7 100644
--- a/tests/glibmm_binding/main.cc
+++ b/tests/glibmm_binding/main.cc
@@ -80,11 +80,12 @@ test()
     // Ensure no change when invalid source results in false return
     source.property_string() = "six six six";
     g_assert_cmpint(target.property_int(), ==, 47);
-  }
 
-  // Ensure the binding was released when its RefPtr went out of scope
-  source.property_string() = "89";
-  g_assert_cmpint(target.property_int(), ==, 47);
+    // Ensure the binding is broken when unbind() is called
+    binding->unbind();
+    source.property_string() = "89";
+    g_assert_cmpint(target.property_int(), ==, 47);
+  }
 
   {
     auto binding = Glib::Binding::bind_property(
@@ -94,6 +95,10 @@ test()
     // With SYNC_CREATE, value of source must sync to target on bind
     g_assert_cmpint(target.property_int(), ==, 89);
   }
+
+  // Ensure the binding was not broken when its RefPtr went out of scope
+  source.property_string() = "90";
+  g_assert_cmpint(target.property_int(), ==, 90);
 }
 
 } // namespace


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