diff options
author | Ryan Lortie <desrt@desrt.ca> | 2009-07-05 12:30:54 +0100 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2009-07-05 12:30:54 +0100 |
commit | 8792d862db4f61317a45dfe07f7b51e5ccf6741b (patch) | |
tree | f3b429660195bb416d5c6d741e74ecb06ad8006c /glib/gtree.c | |
parent | fc2b3ee560e29b4ef6e70928b0be75d833d75aec (diff) | |
download | glib-8792d862db4f61317a45dfe07f7b51e5ccf6741b.tar.gz |
GTree: switch to GSlice, add refcounts (#587773)
Diffstat (limited to 'glib/gtree.c')
-rw-r--r-- | glib/gtree.c | 88 |
1 files changed, 73 insertions, 15 deletions
diff --git a/glib/gtree.c b/glib/gtree.c index 8ae5e9812..6fb2a9e27 100644 --- a/glib/gtree.c +++ b/glib/gtree.c @@ -47,6 +47,7 @@ struct _GTree GDestroyNotify value_destroy_func; gpointer key_compare_data; guint nnodes; + gint ref_count; }; struct _GTreeNode @@ -177,13 +178,14 @@ g_tree_new_full (GCompareDataFunc key_compare_func, g_return_val_if_fail (key_compare_func != NULL, NULL); - tree = g_new (GTree, 1); + tree = g_slice_new (GTree); tree->root = NULL; tree->key_compare = key_compare_func; tree->key_destroy_func = key_destroy_func; tree->value_destroy_func = value_destroy_func; tree->key_compare_data = key_compare_data; tree->nnodes = 0; + tree->ref_count = 1; return tree; } @@ -231,18 +233,9 @@ g_tree_node_next (GTreeNode *node) return tmp; } - -/** - * g_tree_destroy: - * @tree: a #GTree. - * - * Destroys the #GTree. If keys and/or values are dynamically allocated, you - * should either free them first or create the #GTree using g_tree_new_full(). - * In the latter case the destroy functions you supplied will be called on - * all keys and values before destroying the #GTree. - **/ -void -g_tree_destroy (GTree *tree) + +static void +g_tree_remove_all (GTree *tree) { GTreeNode *node; GTreeNode *next; @@ -250,7 +243,7 @@ g_tree_destroy (GTree *tree) g_return_if_fail (tree != NULL); node = g_tree_first_node (tree); - + while (node) { next = g_tree_node_next (node); @@ -264,7 +257,72 @@ g_tree_destroy (GTree *tree) node = next; } - g_free (tree); +} + +/** + * g_tree_ref: + * @tree: a #GTree. + * + * Increments the reference count of @tree by one. It is safe to call + * this function from any thread. + * + * Return value: the passed in #GTree. + * + * Since: 2.22 + **/ +GTree * +g_tree_ref (GTree *tree) +{ + g_return_val_if_fail (tree != NULL, NULL); + + g_atomic_int_inc (&tree->ref_count); + + return tree; +} + +/** + * g_tree_unref: + * @tree: a #GTree. + * + * Decrements the reference count of @tree by one. If the reference count + * drops to 0, all keys and values will be destroyed (if destroy + * functions were specified) and all memory allocated by @tree will be + * released. + * + * It is safe to call this function from any thread. + * + * Since: 2.22 + **/ +void +g_tree_unref (GTree *tree) +{ + g_return_if_fail (tree != NULL); + + if (g_atomic_int_dec_and_test (&tree->ref_count)) + { + g_tree_remove_all (tree); + g_slice_free (GTree, tree); + } +} + +/** + * g_tree_destroy: + * @tree: a #GTree. + * + * Removes all keys and values from the #GTree and decreases its + * reference count by one. If keys and/or values are dynamically + * allocated, you should either free them first or create the #GTree + * using g_tree_new_full(). In the latter case the destroy functions + * you supplied will be called on all keys and values before destroying + * the #GTree. + **/ +void +g_tree_destroy (GTree *tree) +{ + g_return_if_fail (tree != NULL); + + g_tree_remove_all (tree); + g_tree_unref (tree); } /** |