From: Dana Jansens Date: Thu, 12 Nov 2009 14:40:31 +0000 (-0500) Subject: Make a g_tree_node_free() function to avoid code duplication. Use g_atomic_ function... X-Git-Url: http://git.openbox.org/?a=commitdiff_plain;h=321088e37a2fb4bf53cfac28654da7b60685eeae;p=dana%2Fcg-glib.git Make a g_tree_node_free() function to avoid code duplication. Use g_atomic_ functions to increment/decrement reference counters in a GTreeNode. --- diff --git a/glib/gtree.c b/glib/gtree.c index 858e9316..5ea56fde 100644 --- a/glib/gtree.c +++ b/glib/gtree.c @@ -84,7 +84,7 @@ struct _GTreeNodeData { gpointer key; /* key for this node */ gpointer value; /* value stored at this node */ - guint16 ref_count; + gint ref_count; guint8 stolen; /* true if the node is stolen instead of removed */ }; @@ -171,6 +171,38 @@ g_tree_node_new (GTree *tree, return node; } +static gboolean +g_tree_node_free (GTree *tree, + GTreeNode *node) +{ + gboolean data_free = FALSE; + + /* 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 (g_atomic_int_dec_and_test (&node->data->ref_count)) + { + if (!node->data->stolen) + { + 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); + data_free = TRUE; + } + + g_slice_free1 (sizeof(GTreeNodeVersion) * + (node->version(NOW) == 0 ? 1 : TABLE_SIZE), + node->v); + node->v = NULL; + node->data = NULL; + g_slice_free (GTreeNode, node); + + return data_free; +} + /** * g_tree_new: * @key_compare_func: the function used to order the nodes in the #GTree. @@ -397,37 +429,15 @@ g_tree_node_next (GTreeNode *node, } static inline void -g_tree_node_remove (GTree *tree, GTreeNode *node) +g_tree_node_free_all (GTree *tree, GTreeNode *node) { if (!node) return; - g_tree_node_remove (tree, node->left(NOW)); - g_tree_node_remove (tree, node->right(NOW)); + g_tree_node_free_all (tree, node->left(NOW)); + g_tree_node_free_all (tree, node->right(NOW)); - 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 (--node->data->ref_count == 0) - { - if (!node->data->stolen) - { - 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); - } - - g_slice_free1 (sizeof(GTreeNodeVersion) * - (node->version(NOW) == 0 ? 1 : TABLE_SIZE), - node->v); - node->v = NULL; - node->data = NULL; - g_slice_free (GTreeNode, node); + g_tree_node_free (tree, node); } static void @@ -439,7 +449,7 @@ g_tree_remove_all (GTree *tree) if (tree->version > 0) g_tree_delete_versions (tree, tree->version-1); - g_tree_node_remove (tree, tree->root(NOW)); + g_tree_node_free_all (tree, tree->root(NOW)); tree->roots[0].root = NULL; tree->roots[0].version = tree->version = 0; @@ -635,24 +645,7 @@ g_tree_node_delete_versions (GTree *tree, /* if we removed the last version inside the node, then we can free it */ if (node->nv == 0) { - if (--node->data->ref_count == 0) - { - if (!node->data->stolen) - { - 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); - } - - g_slice_free1 (sizeof(GTreeNodeVersion) * - (node->version(NOW) == 0 ? 1 : TABLE_SIZE), - node->v); - node->v = NULL; - node->data = NULL; - g_slice_free (GTreeNode, node); + g_tree_node_free (tree, node); node = NULL; } @@ -797,7 +790,7 @@ g_tree_node_add_version (GTree *tree, GTreeNode *newnode = g_slice_new(GTreeNode); newnode->v = g_slice_alloc(sizeof(GTreeNodeVersion) * TABLE_SIZE); newnode->data = node->data; - newnode->data->ref_count++; + g_atomic_int_inc (&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; @@ -1160,8 +1153,12 @@ g_tree_remove (GTree *tree, * Removes a key and its associated value from a #GTree without calling * the key and value destroy functions. Note that if the key existed in * earlier versions of the tree (g_tree_next_version() has been called since - * it was inserted), then it cannot be removed from the tree, until all - * versions containing the node are removed from the tree. + * it was inserted), then it cannot be removed from the tree until all + * versions containing the node are removed from the tree, by calling + * g_tree_delete_versions(). However, if the node is removed from the current + * version of the tree with g_tree_steal() then the key and value destroy + * functions will not be called once the last version of the key/value pair + * is removed. * If the key does not exist in the #GTree, the function does nothing. * * Returns: %TRUE if the key was found and able to be removed @@ -1196,7 +1193,7 @@ g_tree_remove_internal (GTree *tree, { GTreeNode *node, *parent; gboolean is_leftchild; - gboolean key_removed = FALSE; + gboolean data_free; g_return_val_if_fail (tree != NULL, FALSE); @@ -1325,38 +1322,15 @@ g_tree_remove_internal (GTree *tree, --node->nv; } + node->data->stolen = steal; + data_free = FALSE; + /* only really delete the node if it was only in the current version, otherwise it needs to be remembered */ if (node->nv == 0) - { - /* 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 (!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_free1 (sizeof(GTreeNodeVersion) * - (node->version(NOW) == 0 ? 1 : TABLE_SIZE), - node->v); - node->v = NULL; - node->data = NULL; - g_slice_free (GTreeNode, node); - } - else if (steal) - node->data->stolen = TRUE; + data_free = g_tree_node_free (tree, node); - return key_removed; + return data_free; } /**