[glibmm/wip/dboles/Binding-Issue#62: 2/2] Binding: Add set_manage() to not require a RefPtr
- From: Daniel Boles <dboles src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glibmm/wip/dboles/Binding-Issue#62: 2/2] Binding: Add set_manage() to not require a RefPtr
- Date: Fri, 15 Nov 2019 11:41:29 +0000 (UTC)
commit 5ff73c83bb19a37e42756acbde3ef05983b21b0e
Author: Daniel Boles <dboles src gmail com>
Date: Fri Nov 15 11:37:31 2019 +0000
Binding: Add set_manage() to not require a RefPtr
Allow users to call Glib::manage(RefPtr<Binding>) in order to defeat our
pre-existing and still default behaviour that a user must keep a RefPtr
to the Binding in order to keep it alive, instead letting it revert to
the C-style behaviour of staying alive as long as either object does.
We use Glib::manage() to avoid the possible pitfall of a user calling
->set_manage() on the result of bind_property*(), which might be empty.
https://gitlab.gnome.org/GNOME/glibmm/issues/62
glib/src/binding.ccg | 24 +++++++++++++++++-------
glib/src/binding.hg | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 7 deletions(-)
---
diff --git a/glib/src/binding.ccg b/glib/src/binding.ccg
index dfad8a66..ce8a6891 100644
--- a/glib/src/binding.ccg
+++ b/glib/src/binding.ccg
@@ -112,7 +112,8 @@ Binding::bind_property_value(const PropertyProxy_Base& source_property,
// Take an extra ref. GBinding uses one ref itself, and drops it if
// either the source object or the target object is finalized.
- // The GBinding object must not be destroyed while there are RefPtrs around.
+ // The GBinding object must not be destroyed while there are RefPtrs around,
+ // unless set_manage() was called.
g_object_ref(binding);
return Glib::make_refptr_for_instance<Binding>(new Binding(binding));
}
@@ -131,18 +132,27 @@ Binding::unbind()
// 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.
+// reference from a Glib::RefPtr is dropped. unless set_manage() was called.
void
Binding::unreference() const
{
- GBinding* const binding = const_cast<GBinding*>(gobj());
+ if (!m_manage)
+ {
+ 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);
+ // 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();
}
+void
+Binding::set_manage()
+{
+ m_manage = true;
+}
+
} // namespace Glib
diff --git a/glib/src/binding.hg b/glib/src/binding.hg
index b9baf4fc..898932f9 100644
--- a/glib/src/binding.hg
+++ b/glib/src/binding.hg
@@ -146,6 +146,12 @@ public:
* Glib::Binding for as long as you want to bind, but that alone does not
* necessarily mean the binding between properties itself is still active.
*
+ * If it is not convenient to maintain a Glib::RefPtr to keep a Glib::Binding
+ * active, you can pass the Glib::Binding to Glib::manage() to specify that it
+ * should have its lifetime managed by the source/target objects and unbind()
+ * only. In that case, it will stay active as long as the source and target
+ * exist and unbind() is not called, even if no Glib::RefPtr to it is kept.
+ *
* A Glib::ObjectBase instance can have multiple bindings.
*
* If you supply transformation functions, it is usually easier to use one of the
@@ -405,9 +411,20 @@ public:
* You should never need to do this manually - use the object via a RefPtr instead.
*/
void unreference() const override;
+
+ /** Sets the binding as having its lifetime managed by the lifetimes of its
+ * source and target objects, rather than requiring a Glib::RefPtr to be kept.
+ *
+ * See bind_property_value() for full information on the lifetimes of bindings.
+ *
+ * @newin{2,64}
+ */
+ void set_manage();
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
private:
+ bool m_manage = false;
+
// The functor TransformProp can be implicitly converted to a SlotTransform
// and used in a call to bind_property_value().
template <typename T_from, typename T_to>
@@ -437,4 +454,22 @@ private:
};
};
+/** Sets a Glib::Binding as having its lifetime managed by the lifetimes of its
+ * source and target objects, rather than requiring a Glib::RefPtr to be kept.
+ *
+ * See bind_property_value() for full information on the lifetimes of bindings.
+ *
+ * @newin{2,64}
+ * @param binding the Glib::Binding to set as managed, or an empty Glib::RefPtr.
+ * @return the same Glib::Binding.
+ */
+Glib::RefPtr<Glib::Binding> const&
+Glib::manage(Glib::RefPtr<Glib::Binding> const& binding)
+{
+ if (binding)
+ binding->set_manage();
+
+ return binding;
+}
+
} // namespace Glib
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]