From 2940a0f63e1009c0ce85ca800bef3b3444f447d2 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 30 Oct 2009 21:03:21 -0400 Subject: [PATCH] Free a node's data and return TRUE for g_tree_remove() only if it's the last version of the node in the persistent tree. --- glib/gtree.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/glib/gtree.c b/glib/gtree.c index ae0755c3..1a2e2e1e 100644 --- a/glib/gtree.c +++ b/glib/gtree.c @@ -84,6 +84,7 @@ struct _GTreeNodeData { gpointer key; /* key for this node */ gpointer value; /* value stored at this node */ + guint ref_count; }; struct _GTreeNode @@ -153,6 +154,7 @@ g_tree_node_new (GTree *tree, node->data = g_slice_new(GTreeNodeData); node->data->key = key; node->data->value = value; + node->data->ref_count = 1; /* for the version 0, only allocate one set of pointers for a node, so that we don't use a lot more memory when persistence isn't even @@ -537,6 +539,7 @@ g_tree_node_next_version (GTree *tree, /* we filled the node's pointer table and need to make a new GTreeNode */ GTreeNode *newnode = g_slice_new(GTreeNode); newnode->data = node->data; + newnode->data->ref_count++; newnode->v[0] = node->v[0]; /* copy the latest version to here */ newnode->v[0].version = tree->version; newnode->nv = 1; @@ -904,6 +907,7 @@ g_tree_remove_internal (GTree *tree, { GTreeNode *node, *parent; gboolean is_leftchild; + gboolean key_removed = FALSE; g_return_val_if_fail (tree != NULL, FALSE); @@ -1022,24 +1026,30 @@ g_tree_remove_internal (GTree *tree, it needs to be remembered */ if (node->nv == 1 && node->version(NOW) == tree->version) { - if (!steal) + /* free the node's data if it's the last node which is using it. just + because the version of the node was created in the latest version + of the tree, doesn't mean there aren't older versions around still */ + if (--node->data->ref_count == 0) { - if (tree->key_destroy_func) - tree->key_destroy_func (node->data->key); - if (tree->value_destroy_func) - tree->value_destroy_func (node->data->value); + if (!steal) + { + if (tree->key_destroy_func) + tree->key_destroy_func (node->data->key); + if (tree->value_destroy_func) + tree->value_destroy_func (node->data->value); + } + g_slice_free (GTreeNodeData, node->data); + + key_removed = TRUE; } - g_slice_free (GTreeNodeData, node->data); g_slice_free1 (sizeof(GTreeNodeVersion) * (node->version(NOW) == 0 ? 1 : MAX_IN_DEGREE + 1), node->v); g_slice_free (GTreeNode, node); - - return TRUE; } - return FALSE; + return key_removed; } /** -- 2.34.1