[gtk+] treemodelfilter: correct forgotten unref of parent on level destroy
- From: Kristian Rietveld <kristian src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] treemodelfilter: correct forgotten unref of parent on level destroy
- Date: Sun, 11 Sep 2011 14:55:49 +0000 (UTC)
commit 3db7344f33616983ca0b17b48200cf735679f695
Author: Kristian Rietveld <kris gtk org>
Date: Sun Sep 11 16:53:27 2011 +0200
treemodelfilter: correct forgotten unref of parent on level destroy
gtk_tree_model_filter_free_level() should always release ref on parent
unless the parent has been removed in the child model. The unit tests
added in the previous commit test this.
gtk/gtktreemodelfilter.c | 81 +++++++++++++++++++++++++++++-----------------
1 files changed, 51 insertions(+), 30 deletions(-)
---
diff --git a/gtk/gtktreemodelfilter.c b/gtk/gtktreemodelfilter.c
index b401a0d..df09dda 100644
--- a/gtk/gtktreemodelfilter.c
+++ b/gtk/gtktreemodelfilter.c
@@ -423,7 +423,8 @@ static void gtk_tree_model_filter_build_level (GtkTr
static void gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
FilterLevel *filter_level,
- gboolean unref,
+ gboolean unref_self,
+ gboolean unref_parent,
gboolean unref_external);
static GtkTreePath *gtk_tree_model_filter_elt_get_path (FilterLevel *level,
@@ -602,7 +603,7 @@ gtk_tree_model_filter_finalize (GObject *object)
gtk_tree_path_free (filter->priv->virtual_root);
if (filter->priv->root)
- gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE, FALSE);
+ gtk_tree_model_filter_free_level (filter, filter->priv->root, TRUE, TRUE, FALSE);
g_free (filter->priv->modify_types);
@@ -892,7 +893,7 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
if (empty &&
(parent_level && parent_level->ext_ref_count == 0))
{
- gtk_tree_model_filter_free_level (filter, new_level, FALSE, FALSE);
+ gtk_tree_model_filter_free_level (filter, new_level, FALSE, TRUE, FALSE);
return;
}
@@ -931,7 +932,8 @@ gtk_tree_model_filter_build_level (GtkTreeModelFilter *filter,
static void
gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
FilterLevel *filter_level,
- gboolean unref,
+ gboolean unref_self,
+ gboolean unref_parent,
gboolean unref_external)
{
GSequenceIter *siter;
@@ -947,9 +949,17 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
FilterElt *elt = g_sequence_get (siter);
if (elt->children)
- gtk_tree_model_filter_free_level (filter,
- FILTER_LEVEL (elt->children),
- unref, unref_external);
+ {
+ /* If we recurse and unref_self == FALSE, then unref_parent
+ * must also be FALSE (otherwise a still unref a node in this
+ * level).
+ */
+ gtk_tree_model_filter_free_level (filter,
+ FILTER_LEVEL (elt->children),
+ unref_self,
+ unref_self == FALSE ? FALSE : unref_parent,
+ unref_external);
+ }
if (unref_external)
{
@@ -962,13 +972,13 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
while (elt->ext_ref_count > 0)
gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
&f_iter,
- TRUE, unref);
+ TRUE, unref_self);
}
}
/* Release the reference on the first item.
*/
- if (unref)
+ if (unref_self)
{
GtkTreeIter f_iter;
@@ -1000,17 +1010,14 @@ gtk_tree_model_filter_free_level (GtkTreeModelFilter *filter,
if (filter_level->parent_elt)
{
/* Release reference on parent */
- if (unref)
- {
- GtkTreeIter parent_iter;
+ GtkTreeIter parent_iter;
- parent_iter.stamp = filter->priv->stamp;
- parent_iter.user_data = filter_level->parent_level;
- parent_iter.user_data2 = filter_level->parent_elt;
+ parent_iter.stamp = filter->priv->stamp;
+ parent_iter.user_data = filter_level->parent_level;
+ parent_iter.user_data2 = filter_level->parent_elt;
- gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
- &parent_iter, FALSE, TRUE);
- }
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (filter),
+ &parent_iter, FALSE, unref_parent);
filter_level->parent_elt->children = NULL;
}
@@ -1052,8 +1059,8 @@ gtk_tree_model_filter_prune_level (GtkTreeModelFilter *filter,
if (elt->children)
gtk_tree_model_filter_free_level (filter,
- FILTER_LEVEL (elt->children), TRUE,
- TRUE);
+ FILTER_LEVEL (elt->children),
+ TRUE, TRUE, TRUE);
}
/* For the first item, only drop the external references */
@@ -1316,7 +1323,7 @@ gtk_tree_model_filter_clear_cache_helper (GtkTreeModelFilter *filter,
level->parent_level && level->parent_level != filter->priv->root &&
level->parent_level->ext_ref_count == 0)
{
- gtk_tree_model_filter_free_level (filter, level, TRUE, FALSE);
+ gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, FALSE);
return;
}
}
@@ -1693,7 +1700,7 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
* the case length == 1.
*/
if (elt->children)
- gtk_tree_model_filter_free_level (filter, elt->children, TRUE, TRUE);
+ gtk_tree_model_filter_free_level (filter, elt->children, TRUE, TRUE, TRUE);
/* If the first node is being removed, transfer, the reference */
if (elt == g_sequence_get (g_sequence_get_begin_iter (level->seq)))
@@ -1751,7 +1758,7 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
level->parent_level->ext_ref_count > 0))
{
/* Otherwise, the level can be removed */
- gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE);
+ gtk_tree_model_filter_free_level (filter, level, TRUE, TRUE, TRUE);
}
else
{
@@ -1768,7 +1775,7 @@ gtk_tree_model_filter_remove_elt_from_level (GtkTreeModelFilter *filter,
#endif
if (elt->children)
gtk_tree_model_filter_free_level (filter, elt->children,
- TRUE, TRUE);
+ TRUE, TRUE, TRUE);
}
else
{
@@ -2422,7 +2429,7 @@ gtk_tree_model_filter_virtual_root_deleted (GtkTreeModelFilter *filter,
* nodes will fail, since the respective nodes in the child model are
* no longer there.
*/
- gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE, FALSE);
+ gtk_tree_model_filter_free_level (filter, filter->priv->root, FALSE, TRUE, FALSE);
gtk_tree_model_filter_increment_stamp (filter);
@@ -2601,20 +2608,34 @@ gtk_tree_model_filter_row_deleted (GtkTreeModel *c_model,
while (elt->ext_ref_count > 0)
gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
TRUE, FALSE);
- while (elt->ref_count > 0)
- gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
- FALSE, FALSE);
if (g_sequence_get_length (level->seq) == 1)
{
+ if (elt->children)
+ /* If this last node has children, then the recursion in free_level
+ * will release this reference.
+ */
+ while (elt->ref_count > 1)
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
+ FALSE, FALSE);
+ else
+ while (elt->ref_count > 0)
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
+ FALSE, FALSE);
+
/* kill level */
- gtk_tree_model_filter_free_level (filter, level, FALSE, FALSE);
+ gtk_tree_model_filter_free_level (filter, level, FALSE, TRUE, FALSE);
}
else
{
GSequenceIter *tmp;
gboolean is_first;
+ /* Release last references, if needed */
+ while (elt->ref_count > 0)
+ gtk_tree_model_filter_real_unref_node (GTK_TREE_MODEL (data), &iter,
+ FALSE, FALSE);
+
lookup_elt_with_offset (level->seq, elt->offset, &siter);
is_first = g_sequence_get_begin_iter (level->seq) == siter;
@@ -3638,7 +3659,7 @@ gtk_tree_model_filter_set_model (GtkTreeModelFilter *filter,
/* reset our state */
if (filter->priv->root)
gtk_tree_model_filter_free_level (filter, filter->priv->root,
- TRUE, FALSE);
+ TRUE, TRUE, FALSE);
filter->priv->root = NULL;
g_object_unref (filter->priv->child_model);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]