/* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * GQueue: Double ended queue implementation, piggy backed on GList. * Copyright (C) 1998 Tim Janik * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library 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. */ /* * MT safe */ #include "glib.h" G_LOCK_DEFINE_STATIC (queue_memchunk); static GMemChunk *queue_memchunk = NULL; static GTrashStack *free_queue_nodes = NULL; GQueue* g_queue_new (void) { GQueue *queue; G_LOCK (queue_memchunk); queue = g_trash_stack_pop (&free_queue_nodes); 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); queue->head = NULL; queue->tail = NULL; queue->length = 0; return queue; } void g_queue_free (GQueue *queue) { g_return_if_fail (queue != NULL); g_list_free (queue->head); #ifdef ENABLE_GC_FRIENDLY queue->head = NULL; queue->tail = NULL; #endif /* ENABLE_GC_FRIENDLY */ G_LOCK (queue_memchunk); g_trash_stack_push (&free_queue_nodes, queue); G_UNLOCK (queue_memchunk); } void g_queue_push_head (GQueue *queue, gpointer data) { g_return_if_fail (queue != NULL); queue->head = g_list_prepend (queue->head, data); if (!queue->tail) queue->tail = queue->head; queue->length++; } void g_queue_push_head_link (GQueue *queue, GList *link) { g_return_if_fail (queue != NULL); g_return_if_fail (link != NULL); g_return_if_fail (link->prev == NULL); g_return_if_fail (link->next == NULL); link->next = queue->head; if (queue->head) queue->head->prev = link; else queue->tail = link; queue->head = link; queue->length++; } void g_queue_push_tail (GQueue *queue, gpointer data) { g_return_if_fail (queue != NULL); queue->tail = g_list_append (queue->tail, data); if (queue->tail->next) queue->tail = queue->tail->next; else queue->head = queue->tail; queue->length++; } void g_queue_push_tail_link (GQueue *queue, GList *link) { g_return_if_fail (queue != NULL); g_return_if_fail (link != NULL); g_return_if_fail (link->prev == NULL); g_return_if_fail (link->next == NULL); link->prev = queue->tail; if (queue->tail) queue->tail->next = link; else queue->head = link; queue->tail = link; queue->length++; } gpointer g_queue_pop_head (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); if (queue->head) { GList *node = queue->head; gpointer data = node->data; queue->head = node->next; if (queue->head) queue->head->prev = NULL; else queue->tail = NULL; g_list_free_1 (node); queue->length--; return data; } return NULL; } GList* g_queue_pop_head_link (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); if (queue->head) { GList *node = queue->head; queue->head = node->next; if (queue->head) { queue->head->prev = NULL; node->next = NULL; } else queue->tail = NULL; queue->length--; return node; } return NULL; } gpointer g_queue_pop_tail (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); if (queue->tail) { GList *node = queue->tail; gpointer data = node->data; queue->tail = node->prev; if (queue->tail) queue->tail->next = NULL; else queue->head = NULL; queue->length--; g_list_free_1 (node); return data; } return NULL; } GList* g_queue_pop_tail_link (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); if (queue->tail) { GList *node = queue->tail; queue->tail = node->prev; if (queue->tail) { queue->tail->next = NULL; node->prev = NULL; } else queue->head = NULL; queue->length--; return node; } return NULL; } gboolean g_queue_is_empty (GQueue *queue) { g_return_val_if_fail (queue != NULL, TRUE); return queue->head == NULL; } gpointer g_queue_peek_head (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); return queue->head ? queue->head->data : NULL; } gpointer g_queue_peek_tail (GQueue *queue) { g_return_val_if_fail (queue != NULL, NULL); return queue->tail ? queue->tail->data : NULL; }