[libgda] Fixed objects referencing in GdaTreeNode and GdaTreeManager



commit 041c7ed16870fc3418859e099ab882460e1d9e47
Author: Vivien Malerba <malerba gnome-db org>
Date:   Wed May 25 20:49:26 2011 +0200

    Fixed objects referencing in GdaTreeNode and GdaTreeManager

 libgda/gda-tree-manager.c |   38 ++++++++++++++++++++++++++++++++------
 libgda/gda-tree-node.c    |    2 +-
 2 files changed, 33 insertions(+), 7 deletions(-)
---
diff --git a/libgda/gda-tree-manager.c b/libgda/gda-tree-manager.c
index 99571da..3296741 100644
--- a/libgda/gda-tree-manager.c
+++ b/libgda/gda-tree-manager.c
@@ -1,5 +1,5 @@
-/* GDA library
- * Copyright (C) 2009 - 2010 The GNOME Foundation.
+/*
+ * Copyright (C) 2009 - 2011 The GNOME Foundation.
  *
  * AUTHORS:
  *      Vivien Malerba <malerba gnome-db org>
@@ -31,7 +31,8 @@ typedef struct {
 } AddedAttribute;
 
 struct _GdaTreeManagerPrivate {
-        GSList  *sub_managers; /* list of GdaTreeManager structures */
+        GSList  *sub_managers; /* list of GdaTreeManager structures, no ref held */
+	GSList  *ref_managers; /* list of GdaTreeManager structures, ref held */
 	gboolean recursive;
 
 	GdaTreeManagerNodeFunc node_create_func;
@@ -112,6 +113,7 @@ gda_tree_manager_init (GdaTreeManager *manager, G_GNUC_UNUSED GdaTreeManagerClas
 
 	manager->priv = g_new0 (GdaTreeManagerPrivate, 1);
 	manager->priv->sub_managers = NULL;
+	manager->priv->ref_managers = NULL;
 	manager->priv->added_attributes = NULL;
 }
 
@@ -124,8 +126,12 @@ gda_tree_manager_dispose (GObject *object)
 
 	if (manager->priv) {
 		if (manager->priv->sub_managers) {
-			g_slist_foreach (manager->priv->sub_managers, (GFunc) g_object_unref, NULL);
 			g_slist_free (manager->priv->sub_managers);
+			manager->priv->sub_managers = NULL;
+		}
+		if (manager->priv->ref_managers) {
+			g_slist_foreach (manager->priv->ref_managers, (GFunc) g_object_unref, NULL);
+			g_slist_free (manager->priv->ref_managers);
 		}
 		if (manager->priv->added_attributes) {
 			GSList *list;
@@ -403,6 +409,19 @@ gda_tree_manager_create_node (GdaTreeManager *manager, GdaTreeNode *parent, cons
 	return node;
 }
 
+static gboolean
+manager_is_sub_manager_of (GdaTreeManager *mgr, GdaTreeManager *sub)
+{
+	if (g_slist_find (mgr->priv->ref_managers, sub))
+		return TRUE;
+	GSList *list;
+	for (list = mgr->priv->sub_managers; list; list = list->next) {
+		if (manager_is_sub_manager_of (GDA_TREE_MANAGER (list->data), sub))
+			return TRUE;
+	}
+	return FALSE;
+}
+
 /**
  * gda_tree_manager_add_manager:
  * @manager: a #GdaTreeManager object
@@ -413,7 +432,8 @@ gda_tree_manager_create_node (GdaTreeManager *manager, GdaTreeNode *parent, cons
  * or several times in the same #GdaTree's structure.
  *
  * Please note that it's possible for @mgr and @sub to be the same object, but beware of the possible
- * infinite recursive behaviour in this case (depending on the actual implementation of the #GdaTreeManager)
+ * infinite recursive behaviour in this case when creating children nodes 
+ * (depending on the actual implementation of the #GdaTreeManager).
  *
  * Since: 4.2
  */
@@ -424,9 +444,15 @@ gda_tree_manager_add_manager (GdaTreeManager *manager, GdaTreeManager *sub)
 	g_return_if_fail (GDA_IS_TREE_MANAGER (sub));
 
 	manager->priv->sub_managers = g_slist_append (manager->priv->sub_managers, sub);
-	g_object_ref (sub);
+
+	/* determine if @sub should be ref'ed or not to avoid circular dependencies */
+	if ((sub != manager) && !manager_is_sub_manager_of (sub, manager)) {
+		manager->priv->ref_managers = g_slist_prepend (manager->priv->ref_managers, sub);
+		g_object_ref (sub);
+	}
 }
 
+
 /**
  * gda_tree_manager_get_managers:
  * @manager: a #GdaTreeManager object
diff --git a/libgda/gda-tree-node.c b/libgda/gda-tree-node.c
index da692d6..755edec 100644
--- a/libgda/gda-tree-node.c
+++ b/libgda/gda-tree-node.c
@@ -886,7 +886,7 @@ _gda_nodes_list_free (GdaTreeNodesList *nl)
 	if (nl->nodes) {
 		g_slist_foreach (nl->nodes, (GFunc) g_object_unref, NULL);
 		g_slist_free (nl->nodes);
-		g_object_unref (nl->mgr);
 	}
+	g_object_unref (nl->mgr);
 	g_free (nl);
 }



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