X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgqueue.c;h=3176614204be576e403b59cd2894cfe8bd2295cb;hb=ea4f9ce8a060d53cbc299e4c384089f6cc926caa;hp=9db4d5c8bd3cb3b15d09ac53e9ed80c494ddb157;hpb=d201974f56d7b805f70b5c5703be79e8db73526e;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gqueue.c b/glib/gqueue.c index 9db4d5c..3176614 100644 --- a/glib/gqueue.c +++ b/glib/gqueue.c @@ -15,80 +15,314 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . */ /* * MT safe */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "glib.h" +/** + * SECTION:queue + * @Title: Double-ended Queues + * @Short_description: double-ended queue data structure + * + * The #GQueue structure and its associated functions provide a standard + * queue data structure. Internally, GQueue uses the same data structure + * as #GList to store elements. + * + * The data contained in each element can be either integer values, by + * using one of the [Type Conversion Macros][glib-Type-Conversion-Macros], + * or simply pointers to any type of data. + * + * To create a new GQueue, use g_queue_new(). + * + * To initialize a statically-allocated GQueue, use #G_QUEUE_INIT or + * g_queue_init(). + * + * To add elements, use g_queue_push_head(), g_queue_push_head_link(), + * g_queue_push_tail() and g_queue_push_tail_link(). + * + * To remove elements, use g_queue_pop_head() and g_queue_pop_tail(). + * + * To free the entire queue, use g_queue_free(). + */ +#include "config.h" +#include "gqueue.h" -G_LOCK_DEFINE_STATIC (queue_memchunk); -static GMemChunk *queue_memchunk = NULL; -static GTrashStack *free_queue_nodes = NULL; +#include "gtestutils.h" +#include "gslice.h" /** * g_queue_new: * - * Creates a new #GQueue. + * Creates a new #GQueue. * - * Returns: a new #GQueue. + * Returns: a newly allocated #GQueue **/ -GQueue* +GQueue * g_queue_new (void) { - GQueue *queue; + return g_slice_new0 (GQueue); +} - G_LOCK (queue_memchunk); - queue = g_trash_stack_pop (&free_queue_nodes); +/** + * g_queue_free: + * @queue: a #GQueue + * + * Frees the memory allocated for the #GQueue. Only call this function + * if @queue was created with g_queue_new(). If queue elements contain + * dynamically-allocated memory, they should be freed first. + * + * If queue elements contain dynamically-allocated memory, you should + * either use g_queue_free_full() or free them manually first. + **/ +void +g_queue_free (GQueue *queue) +{ + g_return_if_fail (queue != NULL); - if (!queue) - { - if (!queue_memchunk) - queue_memchunk = g_mem_chunk_new ("GLib GQueue chunk", - sizeof (GNode), - sizeof (GNode) * 128, - G_ALLOC_ONLY); - queue = g_chunk_new (GQueue, queue_memchunk); - } - G_UNLOCK (queue_memchunk); + g_list_free (queue->head); + g_slice_free (GQueue, queue); +} - queue->head = NULL; - queue->tail = NULL; +/** + * g_queue_free_full: + * @queue: a pointer to a #GQueue + * @free_func: the function to be called to free each element's data + * + * Convenience method, which frees all the memory used by a #GQueue, + * and calls the specified destroy function on every element's data. + * + * Since: 2.32 + */ +void +g_queue_free_full (GQueue *queue, + GDestroyNotify free_func) +{ + g_queue_foreach (queue, (GFunc) free_func, NULL); + g_queue_free (queue); +} + +/** + * g_queue_init: + * @queue: an uninitialized #GQueue + * + * A statically-allocated #GQueue must be initialized with this function + * before it can be used. Alternatively you can initialize it with + * #G_QUEUE_INIT. It is not necessary to initialize queues created with + * g_queue_new(). + * + * Since: 2.14 + */ +void +g_queue_init (GQueue *queue) +{ + g_return_if_fail (queue != NULL); + + queue->head = queue->tail = NULL; queue->length = 0; +} - return queue; +/** + * g_queue_clear: + * @queue: a #GQueue + * + * Removes all the elements in @queue. If queue elements contain + * dynamically-allocated memory, they should be freed first. + * + * Since: 2.14 + */ +void +g_queue_clear (GQueue *queue) +{ + g_return_if_fail (queue != NULL); + + g_list_free (queue->head); + g_queue_init (queue); } /** - * g_queue_free: + * g_queue_is_empty: * @queue: a #GQueue. * - * Frees the memory allocated for the #GQueue. - **/ + * Returns %TRUE if the queue is empty. + * + * Returns: %TRUE if the queue is empty + */ +gboolean +g_queue_is_empty (GQueue *queue) +{ + g_return_val_if_fail (queue != NULL, TRUE); + + return queue->head == NULL; +} + +/** + * g_queue_get_length: + * @queue: a #GQueue + * + * Returns the number of items in @queue. + * + * Returns: the number of items in @queue + * + * Since: 2.4 + */ +guint +g_queue_get_length (GQueue *queue) +{ + g_return_val_if_fail (queue != NULL, 0); + + return queue->length; +} + +/** + * g_queue_reverse: + * @queue: a #GQueue + * + * Reverses the order of the items in @queue. + * + * Since: 2.4 + */ void -g_queue_free (GQueue *queue) +g_queue_reverse (GQueue *queue) { g_return_if_fail (queue != NULL); - g_list_free (queue->head); + queue->tail = queue->head; + queue->head = g_list_reverse (queue->head); +} + +/** + * g_queue_copy: + * @queue: a #GQueue + * + * Copies a @queue. Note that is a shallow copy. If the elements in the + * queue consist of pointers to data, the pointers are copied, but the + * actual data is not. + * + * Returns: a copy of @queue + * + * Since: 2.4 + */ +GQueue * +g_queue_copy (GQueue *queue) +{ + GQueue *result; + GList *list; + + g_return_val_if_fail (queue != NULL, NULL); + + result = g_queue_new (); + + for (list = queue->head; list != NULL; list = list->next) + g_queue_push_tail (result, list->data); + + return result; +} -#ifdef ENABLE_GC_FRIENDLY - queue->head = NULL; - queue->tail = NULL; -#endif /* ENABLE_GC_FRIENDLY */ +/** + * g_queue_foreach: + * @queue: a #GQueue + * @func: the function to call for each element's data + * @user_data: user data to pass to @func + * + * Calls @func for each element in the queue passing @user_data to the + * function. + * + * Since: 2.4 + */ +void +g_queue_foreach (GQueue *queue, + GFunc func, + gpointer user_data) +{ + GList *list; + + g_return_if_fail (queue != NULL); + g_return_if_fail (func != NULL); + + list = queue->head; + while (list) + { + GList *next = list->next; + func (list->data, user_data); + list = next; + } +} + +/** + * g_queue_find: + * @queue: a #GQueue + * @data: data to find + * + * Finds the first link in @queue which contains @data. + * + * Returns: the first link in @queue which contains @data + * + * Since: 2.4 + */ +GList * +g_queue_find (GQueue *queue, + gconstpointer data) +{ + g_return_val_if_fail (queue != NULL, NULL); - G_LOCK (queue_memchunk); - g_trash_stack_push (&free_queue_nodes, queue); - G_UNLOCK (queue_memchunk); + return g_list_find (queue->head, data); +} + +/** + * g_queue_find_custom: + * @queue: a #GQueue + * @data: user data passed to @func + * @func: a #GCompareFunc to call for each element. It should return 0 + * when the desired element is found + * + * Finds an element in a #GQueue, using a supplied function to find the + * desired element. It iterates over the queue, calling the given function + * which should return 0 when the desired element is found. The function + * takes two gconstpointer arguments, the #GQueue element's data as the + * first argument and the given user data as the second argument. + * + * Returns: the found link, or %NULL if it wasn't found + * + * Since: 2.4 + */ +GList * +g_queue_find_custom (GQueue *queue, + gconstpointer data, + GCompareFunc func) +{ + g_return_val_if_fail (queue != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + return g_list_find_custom (queue->head, data, func); +} + +/** + * g_queue_sort: + * @queue: a #GQueue + * @compare_func: the #GCompareDataFunc used to sort @queue. This function + * is passed two elements of the queue and should return 0 if they are + * equal, a negative value if the first comes before the second, and + * a positive value if the second comes before the first. + * @user_data: user data passed to @compare_func + * + * Sorts @queue using @compare_func. + * + * Since: 2.4 + */ +void +g_queue_sort (GQueue *queue, + GCompareDataFunc compare_func, + gpointer user_data) +{ + g_return_if_fail (queue != NULL); + g_return_if_fail (compare_func != NULL); + + queue->head = g_list_sort_with_data (queue->head, compare_func, user_data); + queue->tail = g_list_last (queue->head); } /** @@ -97,10 +331,10 @@ g_queue_free (GQueue *queue) * @data: the data for the new element. * * Adds a new element at the head of the queue. - **/ + */ void -g_queue_push_head (GQueue *queue, - gpointer data) +g_queue_push_head (GQueue *queue, + gpointer data) { g_return_if_fail (queue != NULL); @@ -111,16 +345,43 @@ g_queue_push_head (GQueue *queue, } /** + * g_queue_push_nth: + * @queue: a #GQueue + * @data: the data for the new element + * @n: the position to insert the new element. If @n is negative or + * larger than the number of elements in the @queue, the element is + * added to the end of the queue. + * + * Inserts a new element into @queue at the given position. + * + * Since: 2.4 + */ +void +g_queue_push_nth (GQueue *queue, + gpointer data, + gint n) +{ + g_return_if_fail (queue != NULL); + + if (n < 0 || n >= queue->length) + { + g_queue_push_tail (queue, data); + return; + } + + g_queue_insert_before (queue, g_queue_peek_nth_link (queue, n), data); +} + +/** * g_queue_push_head_link: - * @queue: a #GQueue. - * @link_: a single #GList element, not a list with - * more than one element. + * @queue: a #GQueue + * @link_: a single #GList element, not a list with more than one element * * Adds a new element at the head of the queue. - **/ + */ void g_queue_push_head_link (GQueue *queue, - GList *link) + GList *link) { g_return_if_fail (queue != NULL); g_return_if_fail (link != NULL); @@ -138,14 +399,14 @@ g_queue_push_head_link (GQueue *queue, /** * g_queue_push_tail: - * @queue: a #GQueue. - * @data: the data for the new element. + * @queue: a #GQueue + * @data: the data for the new element * * Adds a new element at the tail of the queue. - **/ + */ void -g_queue_push_tail (GQueue *queue, - gpointer data) +g_queue_push_tail (GQueue *queue, + gpointer data) { g_return_if_fail (queue != NULL); @@ -159,15 +420,14 @@ g_queue_push_tail (GQueue *queue, /** * g_queue_push_tail_link: - * @queue: a #GQueue. - * @link_: a single #GList element, not a list with - * more than one element. + * @queue: a #GQueue + * @link_: a single #GList element, not a list with more than one element * * Adds a new element at the tail of the queue. - **/ + */ void g_queue_push_tail_link (GQueue *queue, - GList *link) + GList *link) { g_return_if_fail (queue != NULL); g_return_if_fail (link != NULL); @@ -184,14 +444,65 @@ g_queue_push_tail_link (GQueue *queue, } /** + * g_queue_push_nth_link: + * @queue: a #GQueue + * @n: the position to insert the link. If this is negative or larger than + * the number of elements in @queue, the link is added to the end of + * @queue. + * @link_: the link to add to @queue + * + * Inserts @link into @queue at the given position. + * + * Since: 2.4 + */ +void +g_queue_push_nth_link (GQueue *queue, + gint n, + GList *link_) +{ + GList *next; + GList *prev; + + g_return_if_fail (queue != NULL); + g_return_if_fail (link_ != NULL); + + if (n < 0 || n >= queue->length) + { + g_queue_push_tail_link (queue, link_); + return; + } + + g_assert (queue->head); + g_assert (queue->tail); + + next = g_queue_peek_nth_link (queue, n); + prev = next->prev; + + if (prev) + prev->next = link_; + next->prev = link_; + + link_->next = next; + link_->prev = prev; + + if (queue->head->prev) + queue->head = queue->head->prev; + + if (queue->tail->next) + queue->tail = queue->tail->next; + + queue->length++; +} + +/** * g_queue_pop_head: - * @queue: a #GQueue. + * @queue: a #GQueue * - * Removes the first element of the queue. + * Removes the first element of the queue and returns its data. * - * Returns: the data of the first element in the queue, or %NULL if the queue - * is empty. - **/ + * Returns: the data of the first element in the queue, or %NULL + * if the queue is empty + */ gpointer g_queue_pop_head (GQueue *queue) { @@ -204,9 +515,9 @@ g_queue_pop_head (GQueue *queue) queue->head = node->next; if (queue->head) - queue->head->prev = NULL; + queue->head->prev = NULL; else - queue->tail = NULL; + queue->tail = NULL; g_list_free_1 (node); queue->length--; @@ -218,14 +529,14 @@ g_queue_pop_head (GQueue *queue) /** * g_queue_pop_head_link: - * @queue: a #GQueue. + * @queue: a #GQueue * - * Removes the first element of the queue. + * Removes and returns the first element of the queue. * - * Returns: the #GList element at the head of the queue, or %NULL if the queue - * is empty. - **/ -GList* + * Returns: the #GList element at the head of the queue, or %NULL + * if the queue is empty + */ +GList * g_queue_pop_head_link (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); @@ -236,12 +547,12 @@ g_queue_pop_head_link (GQueue *queue) queue->head = node->next; if (queue->head) - { - queue->head->prev = NULL; - node->next = NULL; - } + { + queue->head->prev = NULL; + node->next = NULL; + } else - queue->tail = NULL; + queue->tail = NULL; queue->length--; return node; @@ -251,14 +562,50 @@ g_queue_pop_head_link (GQueue *queue) } /** + * g_queue_peek_head_link: + * @queue: a #GQueue + * + * Returns the first link in @queue. + * + * Returns: the first link in @queue, or %NULL if @queue is empty + * + * Since: 2.4 + */ +GList * +g_queue_peek_head_link (GQueue *queue) +{ + g_return_val_if_fail (queue != NULL, NULL); + + return queue->head; +} + +/** + * g_queue_peek_tail_link: + * @queue: a #GQueue + * + * Returns the last link in @queue. + * + * Returns: the last link in @queue, or %NULL if @queue is empty + * + * Since: 2.4 + */ +GList * +g_queue_peek_tail_link (GQueue *queue) +{ + g_return_val_if_fail (queue != NULL, NULL); + + return queue->tail; +} + +/** * g_queue_pop_tail: - * @queue: a #GQueue. + * @queue: a #GQueue * - * Removes the last element of the queue. + * Removes the last element of the queue and returns its data. * - * Returns: the data of the last element in the queue, or %NULL if the queue - * is empty. - **/ + * Returns: the data of the last element in the queue, or %NULL + * if the queue is empty + */ gpointer g_queue_pop_tail (GQueue *queue) { @@ -271,9 +618,9 @@ g_queue_pop_tail (GQueue *queue) queue->tail = node->prev; if (queue->tail) - queue->tail->next = NULL; + queue->tail->next = NULL; else - queue->head = NULL; + queue->head = NULL; queue->length--; g_list_free_1 (node); @@ -284,15 +631,46 @@ g_queue_pop_tail (GQueue *queue) } /** + * g_queue_pop_nth: + * @queue: a #GQueue + * @n: the position of the element + * + * Removes the @n'th element of @queue and returns its data. + * + * Returns: the element's data, or %NULL if @n is off the end of @queue + * + * Since: 2.4 + */ +gpointer +g_queue_pop_nth (GQueue *queue, + guint n) +{ + GList *nth_link; + gpointer result; + + g_return_val_if_fail (queue != NULL, NULL); + + if (n >= queue->length) + return NULL; + + nth_link = g_queue_peek_nth_link (queue, n); + result = nth_link->data; + + g_queue_delete_link (queue, nth_link); + + return result; +} + +/** * g_queue_pop_tail_link: - * @queue: a #GQueue. + * @queue: a #GQueue * - * Removes the last element of the queue. + * Removes and returns the last element of the queue. * - * Returns: the #GList element at the tail of the queue, or %NULL if the queue - * is empty. - **/ -GList* + * Returns: the #GList element at the tail of the queue, or %NULL + * if the queue is empty + */ +GList * g_queue_pop_tail_link (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); @@ -303,12 +681,12 @@ g_queue_pop_tail_link (GQueue *queue) queue->tail = node->prev; if (queue->tail) - { - queue->tail->next = NULL; - node->prev = NULL; - } + { + queue->tail->next = NULL; + node->prev = NULL; + } else - queue->head = NULL; + queue->head = NULL; queue->length--; return node; @@ -318,30 +696,153 @@ g_queue_pop_tail_link (GQueue *queue) } /** - * g_queue_is_empty: - * @queue: a #GQueue. + * g_queue_pop_nth_link: + * @queue: a #GQueue + * @n: the link's position + * + * Removes and returns the link at the given position. + * + * Returns: the @n'th link, or %NULL if @n is off the end of @queue + * + * Since: 2.4 + */ +GList* +g_queue_pop_nth_link (GQueue *queue, + guint n) +{ + GList *link; + + g_return_val_if_fail (queue != NULL, NULL); + + if (n >= queue->length) + return NULL; + + link = g_queue_peek_nth_link (queue, n); + g_queue_unlink (queue, link); + + return link; +} + +/** + * g_queue_peek_nth_link: + * @queue: a #GQueue + * @n: the position of the link + * + * Returns the link at the given position + * + * Returns: the link at the @n'th position, or %NULL + * if @n is off the end of the list + * + * Since: 2.4 + */ +GList * +g_queue_peek_nth_link (GQueue *queue, + guint n) +{ + GList *link; + gint i; + + g_return_val_if_fail (queue != NULL, NULL); + + if (n >= queue->length) + return NULL; + + if (n > queue->length / 2) + { + n = queue->length - n - 1; + + link = queue->tail; + for (i = 0; i < n; ++i) + link = link->prev; + } + else + { + link = queue->head; + for (i = 0; i < n; ++i) + link = link->next; + } + + return link; +} + +/** + * g_queue_link_index: + * @queue: a #GQueue + * @link_: a #GList link + * + * Returns the position of @link_ in @queue. + * + * Returns: the position of @link_, or -1 if the link is + * not part of @queue + * + * Since: 2.4 + */ +gint +g_queue_link_index (GQueue *queue, + GList *link_) +{ + g_return_val_if_fail (queue != NULL, -1); + + return g_list_position (queue->head, link_); +} + +/** + * g_queue_unlink: + * @queue: a #GQueue + * @link_: a #GList link that must be part of @queue * - * Returns %TRUE if the queue is empty. + * Unlinks @link_ so that it will no longer be part of @queue. + * The link is not freed. * - * Returns: %TRUE if the queue is empty. - **/ -gboolean -g_queue_is_empty (GQueue *queue) + * @link_ must be part of @queue. + * + * Since: 2.4 + */ +void +g_queue_unlink (GQueue *queue, + GList *link_) { - g_return_val_if_fail (queue != NULL, TRUE); + g_return_if_fail (queue != NULL); + g_return_if_fail (link_ != NULL); - return queue->head == NULL; + if (link_ == queue->tail) + queue->tail = queue->tail->prev; + + queue->head = g_list_remove_link (queue->head, link_); + queue->length--; +} + +/** + * g_queue_delete_link: + * @queue: a #GQueue + * @link_: a #GList link that must be part of @queue + * + * Removes @link_ from @queue and frees it. + * + * @link_ must be part of @queue. + * + * Since: 2.4 + */ +void +g_queue_delete_link (GQueue *queue, + GList *link_) +{ + g_return_if_fail (queue != NULL); + g_return_if_fail (link_ != NULL); + + g_queue_unlink (queue, link_); + g_list_free (link_); } /** * g_queue_peek_head: - * @queue: a #GQueue. + * @queue: a #GQueue * * Returns the first element of the queue. * - * Returns: the data of the first element in the queue, or %NULL if the queue - * is empty. - **/ + * Returns: the data of the first element in the queue, or %NULL + * if the queue is empty + */ gpointer g_queue_peek_head (GQueue *queue) { @@ -352,13 +853,13 @@ g_queue_peek_head (GQueue *queue) /** * g_queue_peek_tail: - * @queue: a #GQueue. + * @queue: a #GQueue * * Returns the last element of the queue. * - * Returns: the data of the last element in the queue, or %NULL if the queue - * is empty. - **/ + * Returns: the data of the last element in the queue, or %NULL + * if the queue is empty + */ gpointer g_queue_peek_tail (GQueue *queue) { @@ -366,3 +867,210 @@ g_queue_peek_tail (GQueue *queue) return queue->tail ? queue->tail->data : NULL; } + +/** + * g_queue_peek_nth: + * @queue: a #GQueue + * @n: the position of the element + * + * Returns the @n'th element of @queue. + * + * Returns: the data for the @n'th element of @queue, + * or %NULL if @n is off the end of @queue + * + * Since: 2.4 + */ +gpointer +g_queue_peek_nth (GQueue *queue, + guint n) +{ + GList *link; + + g_return_val_if_fail (queue != NULL, NULL); + + link = g_queue_peek_nth_link (queue, n); + + if (link) + return link->data; + + return NULL; +} + +/** + * g_queue_index: + * @queue: a #GQueue + * @data: the data to find + * + * Returns the position of the first element in @queue which contains @data. + * + * Returns: the position of the first element in @queue which + * contains @data, or -1 if no element in @queue contains @data + * + * Since: 2.4 + */ +gint +g_queue_index (GQueue *queue, + gconstpointer data) +{ + g_return_val_if_fail (queue != NULL, -1); + + return g_list_index (queue->head, data); +} + +/** + * g_queue_remove: + * @queue: a #GQueue + * @data: the data to remove + * + * Removes the first element in @queue that contains @data. + * + * Returns: %TRUE if @data was found and removed from @queue + * + * Since: 2.4 + */ +gboolean +g_queue_remove (GQueue *queue, + gconstpointer data) +{ + GList *link; + + g_return_val_if_fail (queue != NULL, FALSE); + + link = g_list_find (queue->head, data); + + if (link) + g_queue_delete_link (queue, link); + + return (link != NULL); +} + +/** + * g_queue_remove_all: + * @queue: a #GQueue + * @data: the data to remove + * + * Remove all elements whose data equals @data from @queue. + * + * Returns: the number of elements removed from @queue + * + * Since: 2.4 + */ +guint +g_queue_remove_all (GQueue *queue, + gconstpointer data) +{ + GList *list; + guint old_length; + + g_return_val_if_fail (queue != NULL, 0); + + old_length = queue->length; + + list = queue->head; + while (list) + { + GList *next = list->next; + + if (list->data == data) + g_queue_delete_link (queue, list); + + list = next; + } + + return (old_length - queue->length); +} + +/** + * g_queue_insert_before: + * @queue: a #GQueue + * @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to + * push at the tail of the queue. + * @data: the data to insert + * + * Inserts @data into @queue before @sibling. + * + * @sibling must be part of @queue. Since GLib 2.44 a %NULL sibling pushes the + * data at the tail of the queue. + * + * Since: 2.4 + */ +void +g_queue_insert_before (GQueue *queue, + GList *sibling, + gpointer data) +{ + g_return_if_fail (queue != NULL); + + if (sibling == NULL) + { + /* We don't use g_list_insert_before() with a NULL sibling because it + * would be a O(n) operation and we would need to update manually the tail + * pointer. + */ + g_queue_push_tail (queue, data); + } + else + { + queue->head = g_list_insert_before (queue->head, sibling, data); + queue->length++; + } +} + +/** + * g_queue_insert_after: + * @queue: a #GQueue + * @sibling: (nullable): a #GList link that must be part of @queue, or %NULL to + * push at the head of the queue. + * @data: the data to insert + * + * Inserts @data into @queue after @sibling. + * + * @sibling must be part of @queue. Since GLib 2.44 a %NULL sibling pushes the + * data at the head of the queue. + * + * Since: 2.4 + */ +void +g_queue_insert_after (GQueue *queue, + GList *sibling, + gpointer data) +{ + g_return_if_fail (queue != NULL); + + if (sibling == NULL) + g_queue_push_head (queue, data); + else + g_queue_insert_before (queue, sibling->next, data); +} + +/** + * g_queue_insert_sorted: + * @queue: a #GQueue + * @data: the data to insert + * @func: the #GCompareDataFunc used to compare elements in the queue. It is + * called with two elements of the @queue and @user_data. It should + * return 0 if the elements are equal, a negative value if the first + * element comes before the second, and a positive value if the second + * element comes before the first. + * @user_data: user data passed to @func + * + * Inserts @data into @queue using @func to determine the new position. + * + * Since: 2.4 + */ +void +g_queue_insert_sorted (GQueue *queue, + gpointer data, + GCompareDataFunc func, + gpointer user_data) +{ + GList *list; + + g_return_if_fail (queue != NULL); + + list = queue->head; + while (list && func (list->data, data, user_data) < 0) + list = list->next; + + g_queue_insert_before (queue, list, data); +}