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.
--- 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__ */