[gtk+] Avoid unreferencing deleted nodes



commit dec7a340471c019411d3555254c3219f1208cb3a
Author: Kristian Rietveld <kris gtk org>
Date:   Thu Jun 2 22:01:45 2011 +0200

    Avoid unreferencing deleted nodes
    
    Now that we call unref_node in free_level, we have to take care that
    free_level may only unref (parent) nodes when these still exist in the
    child model.  After row-deleted has been received for a node, its
    children may no longer unref this node.

 gtk/gtktreemodelsort.c |   48 +++++++++++++++++++++++++++++-------------------
 1 files changed, 29 insertions(+), 19 deletions(-)
---
diff --git a/gtk/gtktreemodelsort.c b/gtk/gtktreemodelsort.c
index 90c387c..e64f370 100644
--- a/gtk/gtktreemodelsort.c
+++ b/gtk/gtktreemodelsort.c
@@ -355,7 +355,8 @@ static void         gtk_tree_model_sort_build_level       (GtkTreeModelSort *tre
 							   SortLevel        *parent_level,
 							   gint              parent_elt_index);
 static void         gtk_tree_model_sort_free_level        (GtkTreeModelSort *tree_model_sort,
-							   SortLevel        *sort_level);
+							   SortLevel        *sort_level,
+                                                           gboolean          unref);
 static void         gtk_tree_model_sort_increment_stamp   (GtkTreeModelSort *tree_model_sort);
 static void         gtk_tree_model_sort_sort_level        (GtkTreeModelSort *tree_model_sort,
 							   SortLevel        *level,
@@ -497,7 +498,7 @@ gtk_tree_model_sort_finalize (GObject *object)
   gtk_tree_model_sort_set_model (tree_model_sort, NULL);
 
   if (priv->root)
-    gtk_tree_model_sort_free_level (tree_model_sort, priv->root);
+    gtk_tree_model_sort_free_level (tree_model_sort, priv->root, TRUE);
 
   if (priv->sort_list)
     {
@@ -817,7 +818,7 @@ gtk_tree_model_sort_row_inserted (GtkTreeModel          *s_model,
 
   if (level->ref_count == 0 && level != priv->root)
     {
-      gtk_tree_model_sort_free_level (tree_model_sort, level);
+      gtk_tree_model_sort_free_level (tree_model_sort, level, TRUE);
       goto done;
     }
 
@@ -900,20 +901,25 @@ gtk_tree_model_sort_row_deleted (GtkTreeModel *s_model,
   while (elt->ref_count > 0)
     gtk_tree_model_sort_real_unref_node (GTK_TREE_MODEL (data), &iter, FALSE);
 
+  /* If this node has children, we free the level (recursively) here
+   * and specify that unref may not be used, because parent and its
+   * children have been removed by now.
+   */
+  if (elt->children)
+    gtk_tree_model_sort_free_level (tree_model_sort,
+                                    elt->children, FALSE);
+
   if (level->ref_count == 0)
     {
-      /* This will prune the level, so I can just emit the signal and 
-       * not worry about cleaning this level up. 
-       * Careful, root level is not cleaned up in increment stamp.
-       */
       gtk_tree_model_sort_increment_stamp (tree_model_sort);
       gtk_tree_model_row_deleted (GTK_TREE_MODEL (data), path);
       gtk_tree_path_free (path);
 
       if (level == tree_model_sort->priv->root)
 	{
-	  gtk_tree_model_sort_free_level (tree_model_sort, 
-					  tree_model_sort->priv->root);
+	  gtk_tree_model_sort_free_level (tree_model_sort,
+					  tree_model_sort->priv->root,
+                                          TRUE);
 	  tree_model_sort->priv->root = NULL;
 	}
       return;
@@ -2096,7 +2102,7 @@ gtk_tree_model_sort_set_model (GtkTreeModelSort *tree_model_sort,
 
       /* reset our state */
       if (priv->root)
-	gtk_tree_model_sort_free_level (tree_model_sort, priv->root);
+	gtk_tree_model_sort_free_level (tree_model_sort, priv->root, TRUE);
       priv->root = NULL;
       _gtk_tree_data_list_header_free (priv->sort_list);
       priv->sort_list = NULL;
@@ -2521,7 +2527,8 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
 
 static void
 gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
-				SortLevel        *sort_level)
+				SortLevel        *sort_level,
+                                gboolean          unref)
 {
   GtkTreeModelSortPrivate *priv = tree_model_sort->priv;
   gint i;
@@ -2532,7 +2539,7 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
     {
       if (g_array_index (sort_level->array, SortElt, i).children)
 	gtk_tree_model_sort_free_level (tree_model_sort,
-					SORT_LEVEL (g_array_index (sort_level->array, SortElt, i).children));
+					SORT_LEVEL (g_array_index (sort_level->array, SortElt, i).children), unref);
     }
 
   if (sort_level->ref_count == 0)
@@ -2554,14 +2561,17 @@ gtk_tree_model_sort_free_level (GtkTreeModelSort *tree_model_sort,
 
   if (sort_level->parent_elt_index >= 0)
     {
-      GtkTreeIter parent_iter;
+      if (unref)
+        {
+          GtkTreeIter parent_iter;
 
-      parent_iter.stamp = tree_model_sort->priv->stamp;
-      parent_iter.user_data = sort_level->parent_level;
-      parent_iter.user_data2 = SORT_LEVEL_PARENT_ELT (sort_level);
+          parent_iter.stamp = tree_model_sort->priv->stamp;
+          parent_iter.user_data = sort_level->parent_level;
+          parent_iter.user_data2 = SORT_LEVEL_PARENT_ELT (sort_level);
 
-      gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort),
-                                      &parent_iter);
+          gtk_tree_model_sort_unref_node (GTK_TREE_MODEL (tree_model_sort),
+                                          &parent_iter);
+        }
 
       SORT_LEVEL_PARENT_ELT (sort_level)->children = NULL;
     }
@@ -2604,7 +2614,7 @@ gtk_tree_model_sort_clear_cache_helper (GtkTreeModelSort *tree_model_sort,
     }
 
   if (level->ref_count == 0 && level != tree_model_sort->priv->root)
-    gtk_tree_model_sort_free_level (tree_model_sort, level);
+    gtk_tree_model_sort_free_level (tree_model_sort, level, TRUE);
 }
 
 /**



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