2003-10-01 Mikael Hallendal <micke@imendio.com>
authorhallski <hallski>
Wed, 01 Oct 2003 13:07:01 +0000
changeset 39 b909b5af5a97
parent 38 8e3d2d3f2ccc
child 40 a6c68984c06a
2003-10-01 Mikael Hallendal <micke@imendio.com> * loudmouth/Makefile.am: - added lm-queue.[ch] * loudmouth/lm-queue.[ch]: copied and extended from GQueue. * loudmouth/lm-connection.c: - Use LmQueue instead of GQueue (lm_connection_open_and_block): Better handling of the queue. (lm_connection_send_with_reply_and_block): - Fixed a bug causing replies to be over looked.
ChangeLog
loudmouth/Makefile.am
loudmouth/lm-connection.c
loudmouth/lm-queue.c
loudmouth/lm-queue.h
--- a/ChangeLog	Wed Oct 01 10:39:20 2003 +0000
+++ b/ChangeLog	Wed Oct 01 13:07:01 2003 +0000
@@ -1,3 +1,17 @@
+2003-10-01  Mikael Hallendal  <micke@imendio.com>
+
+	* loudmouth/Makefile.am: 
+	- added lm-queue.[ch]
+	  
+	* loudmouth/lm-queue.[ch]: copied and extended from GQueue.
+	
+	* loudmouth/lm-connection.c: 
+	- Use LmQueue instead of GQueue
+	(lm_connection_open_and_block): Better handling of the queue.
+	
+	(lm_connection_send_with_reply_and_block): 
+	- Fixed a bug causing replies to be over looked.
+
 2003-10-01  Mikael Hallendal  <micke@imendio.com>
 
         * README.WIN32, win32-config.h: 
--- a/loudmouth/Makefile.am	Wed Oct 01 10:39:20 2003 +0000
+++ b/loudmouth/Makefile.am	Wed Oct 01 13:07:01 2003 +0000
@@ -24,6 +24,8 @@
 	lm-sha.c			\
 	lm-sha.h			\
 	lm-utils.c			\
+	lm-queue.c                      \
+	lm-queue.h                      \
 	$(NULL)
 
 libloudmouthinclude_HEADERS =		\
--- a/loudmouth/lm-connection.c	Wed Oct 01 10:39:20 2003 +0000
+++ b/loudmouth/lm-connection.c	Wed Oct 01 13:07:01 2003 +0000
@@ -42,6 +42,7 @@
 #include "lm-internals.h"
 #include "lm-parser.h"
 #include "lm-sha.h"
+#include "lm-queue.h"
 #include "lm-connection.h"
 
 #define IN_BUFFER_SIZE 1024
@@ -90,7 +91,7 @@
 
 	LmCallback *disconnect_cb;
 
-	GQueue     *incoming_messages;
+	LmQueue    *incoming_messages;
 	GSource    *incoming_source;
 
 	gint        ref_count;
@@ -232,7 +233,7 @@
 		    _lm_message_type_to_string (lm_message_get_type (m)),
 		    lm_message_node_get_attribute (m->node, "from"));
 
-	g_queue_push_tail (connection->incoming_messages, m);
+	lm_queue_push_tail (connection->incoming_messages, m);
 }
 
 static gboolean
@@ -739,7 +740,7 @@
 	
 	connection = ((LmIncomingSource *)source)->connection;
 	
-	return !g_queue_is_empty (connection->incoming_messages);
+	return !lm_queue_is_empty (connection->incoming_messages);
 }
 
 static gboolean
@@ -758,7 +759,7 @@
 	
 	connection = ((LmIncomingSource *) source)->connection;
 
-	m = (LmMessage *) g_queue_pop_head (connection->incoming_messages);
+	m = (LmMessage *) lm_queue_pop_head (connection->incoming_messages);
 	
 	if (m) {
 		connection_handle_message (connection, m);
@@ -820,7 +821,7 @@
 	connection->port              = LM_CONNECTION_DEFAULT_PORT;
 	connection->use_ssl           = FALSE;
 	connection->disconnect_cb     = NULL;
-	connection->incoming_messages = g_queue_new ();
+	connection->incoming_messages = lm_queue_new ();
 	connection->incoming_source   = connection_create_source (connection);
 	
 	connection->id_handlers = g_hash_table_new_full (g_str_hash, 
@@ -920,7 +921,6 @@
 	gboolean   result;
 	gboolean   finished = FALSE;
 	gboolean   ret_val = FALSE;
-	gint       last_len = 0;
 
 	g_return_val_if_fail (connection != NULL, FALSE);
 	
@@ -962,23 +962,25 @@
 	g_source_unref (connection->incoming_source);
 
 	while (!finished) {
-		gint len;
+		gint n;
 		
 		g_main_context_iteration (NULL, TRUE);
 		
-		len = connection->incoming_messages->length;
-		
-		if (len > last_len) {
+		if (lm_queue_is_empty (connection->incoming_messages)) {
+			continue;
+		}
+
+		for (n = 0; n < connection->incoming_messages->length; n++) {
 			LmMessage *m;
-			
-			last_len = len;
-			m = (LmMessage *) g_queue_peek_tail (connection->incoming_messages);
+
+			m = lm_queue_peek_nth (connection->incoming_messages, n);
 			if (lm_message_get_type (m) == LM_MESSAGE_TYPE_STREAM) {
 				connection->stream_id = 
 					g_strdup (lm_message_node_get_attribute (m->node, "id"));
 				ret_val = TRUE;
 				finished = TRUE;
-				g_queue_pop_tail (connection->incoming_messages);
+				lm_queue_remove_nth (connection->incoming_messages, n);
+				break;
 			}
 		}
 	}
@@ -1399,7 +1401,6 @@
 {
 	gchar     *id;
 	LmMessage *reply = NULL;
-	gint       last_len = 0;
 
 	if (lm_message_node_get_attribute (message->node, "id")) {
 		id = g_strdup (lm_message_node_get_attribute (message->node, 
@@ -1415,24 +1416,27 @@
 	lm_connection_send (connection, message, error);
 
 	while (!reply) {
-		gint         len;
 		const gchar *m_id;
-		
+		gint         n;
+
 		g_main_context_iteration (NULL, TRUE);
-		
-		len = connection->incoming_messages->length;
-		
-		if (len > last_len) {
+	
+		if (lm_queue_is_empty (connection->incoming_messages)) {
+			continue;
+		}
+
+		for (n = 0; n < connection->incoming_messages->length; n++) {
 			LmMessage *m;
-			last_len = len;
-			m = (LmMessage *) g_queue_peek_tail (connection->incoming_messages);
+
+			m = lm_queue_peek_nth (connection->incoming_messages, n);
+
 			m_id = lm_message_node_get_attribute (m->node, "id");
 			
 			if (m_id && strcmp (m_id, id) == 0) {
 				reply = m;
+				lm_queue_remove_nth (connection->incoming_messages, n);
+				break;
 			}
-
-			g_queue_pop_tail (connection->incoming_messages);
 		}
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-queue.c	Wed Oct 01 13:07:01 2003 +0000
@@ -0,0 +1,300 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * LmQueue: 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 Lesser 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
+ * 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.
+ */
+
+/* This file is copied from gqueue.c in Glib */
+
+#include "config.h"
+
+#include "glib.h"
+#include "lm-queue.h"
+
+G_LOCK_DEFINE_STATIC (queue_memchunk);
+static GMemChunk   *queue_memchunk = NULL;
+static GTrashStack *free_queue_nodes = NULL;
+
+LmQueue*
+lm_queue_new (void)
+{
+	LmQueue *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 LmQueue chunk",
+							  sizeof (GNode),
+							  sizeof (GNode) * 128,
+							  G_ALLOC_ONLY);
+		queue = g_chunk_new (LmQueue, queue_memchunk);
+	}
+	G_UNLOCK (queue_memchunk);
+
+	queue->head = NULL;
+	queue->tail = NULL;
+	queue->length = 0;
+
+	return queue;
+}
+
+void
+lm_queue_free (LmQueue *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
+lm_queue_push_head (LmQueue   *queue,
+		    LmMessage *m)
+{
+	g_return_if_fail (queue != NULL);
+
+	queue->head = g_list_prepend (queue->head, m);
+	if (!queue->tail)
+		queue->tail = queue->head;
+	queue->length++;
+}
+
+void
+lm_queue_push_head_link (LmQueue *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
+lm_queue_push_tail (LmQueue  *queue,
+		    LmMessage *m)
+{
+	g_return_if_fail (queue != NULL);
+
+	queue->tail = g_list_append (queue->tail, m);
+	if (queue->tail->next)
+		queue->tail = queue->tail->next;
+	else
+		queue->head = queue->tail;
+	queue->length++;
+}
+
+void
+lm_queue_push_tail_link (LmQueue *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++;
+}
+
+LmMessage *
+lm_queue_pop_head (LmQueue *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 (LmMessage *) data;
+	}
+
+	return NULL;
+}
+
+GList*
+lm_queue_pop_head_link (LmQueue *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;
+}
+
+LmMessage *
+lm_queue_pop_tail (LmQueue *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 (LmMessage *) data;
+	}
+
+	return NULL;
+}
+
+GList*
+lm_queue_pop_tail_link (LmQueue *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
+lm_queue_is_empty (LmQueue *queue)
+{
+	g_return_val_if_fail (queue != NULL, TRUE);
+
+	return queue->head == NULL;
+}
+
+LmMessage *
+lm_queue_peek_head (LmQueue *queue)
+{
+	g_return_val_if_fail (queue != NULL, NULL);
+
+	return (LmMessage *) queue->head ? queue->head->data : NULL;
+}
+
+LmMessage *
+lm_queue_peek_tail (LmQueue *queue)
+{
+	g_return_val_if_fail (queue != NULL, NULL);
+
+	return (LmMessage *) queue->tail ? queue->tail->data : NULL;
+}
+
+LmMessage * 
+lm_queue_peek_nth (LmQueue *queue, int n)
+{
+	gpointer data;
+	
+	g_return_val_if_fail (queue != NULL, NULL);
+	g_return_val_if_fail (n >= 0, NULL);
+
+	data = g_list_nth_data (queue->head, n);
+
+	return (LmMessage *) data;
+}
+
+LmMessage *
+lm_queue_remove_nth (LmQueue *queue, int n)
+{
+	GList    *link;
+	gpointer  data;
+
+	g_return_val_if_fail (queue != NULL, NULL);
+	g_return_val_if_fail (n >= 0, NULL);
+	g_return_val_if_fail (n < queue->length, NULL);
+
+	if (n == 0) {
+		return lm_queue_pop_head (queue);
+	}
+	
+	if (n == queue->length - 1) {
+		return lm_queue_pop_tail (queue);
+	}
+
+	link = g_list_nth (queue->head, n);
+	data = link->data;
+
+	queue->head = g_list_delete_link (queue->head, link);
+	queue->length--;
+	
+	return (LmMessage *) data;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-queue.h	Wed Oct 01 13:07:01 2003 +0000
@@ -0,0 +1,75 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * 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.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+/* This file is copied from gqueue.h in Glib */
+
+#ifndef __lm_queue_H__
+#define __lm_queue_H__
+
+#include <glib/glist.h>
+
+#include "lm-message.h"
+
+G_BEGIN_DECLS
+
+typedef struct _LmQueue		LmQueue;
+
+struct _LmQueue
+{
+  GList *head;
+  GList *tail;
+  guint  length;
+};
+
+/* Queues
+ */
+LmQueue*    lm_queue_new            (void);
+void        lm_queue_free           (LmQueue  *queue);
+void        lm_queue_push_head      (LmQueue  *queue,
+				     LmMessage *message);
+void        lm_queue_push_tail      (LmQueue  *queue,
+				     LmMessage *message);
+LmMessage * lm_queue_pop_head       (LmQueue  *queue);
+LmMessage * lm_queue_pop_tail       (LmQueue  *queue);
+gboolean    lm_queue_is_empty       (LmQueue  *queue);
+LmMessage * lm_queue_peek_head      (LmQueue  *queue);
+LmMessage * lm_queue_peek_tail      (LmQueue  *queue);
+void        lm_queue_push_head_link (LmQueue  *queue,
+				     GList   *link_);
+void        lm_queue_push_tail_link (LmQueue  *queue,
+				     GList   *link_);
+
+LmMessage * lm_queue_peek_nth       (LmQueue  *queue,
+				     int       n);
+LmMessage * lm_queue_remove_nth     (LmQueue  *queue,
+				     int       n);
+
+GList*      lm_queue_pop_head_link  (LmQueue  *queue);
+GList*      lm_queue_pop_tail_link  (LmQueue  *queue); 
+
+G_END_DECLS
+
+#endif /* __lm_queue_H__ */