summaryrefslogtreecommitdiff
path: root/glib/gtree.c
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2009-07-05 12:30:54 +0100
committerRyan Lortie <desrt@desrt.ca>2009-07-05 12:30:54 +0100
commit8792d862db4f61317a45dfe07f7b51e5ccf6741b (patch)
treef3b429660195bb416d5c6d741e74ecb06ad8006c /glib/gtree.c
parentfc2b3ee560e29b4ef6e70928b0be75d833d75aec (diff)
downloadglib-8792d862db4f61317a45dfe07f7b51e5ccf6741b.tar.gz
GTree: switch to GSlice, add refcounts (#587773)
Diffstat (limited to 'glib/gtree.c')
-rw-r--r--glib/gtree.c88
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);
}
/**