loudmouth/src/lm-message-queue.c
changeset 0 d0f3a028347a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/src/lm-message-queue.c	Tue Feb 02 01:10:06 2010 +0200
@@ -0,0 +1,234 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006 Imendio AB
+ *
+ * This program 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 program 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 program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "lm-message-queue.h"
+#include "lm-debug.h"
+
+struct _LmMessageQueue {
+	GQueue                  *messages;
+
+	GMainContext            *context;
+	GSource                 *source;
+
+	LmMessageQueueCallback  callback;
+	gpointer                user_data;
+
+	gint                    ref_count;
+};
+
+typedef struct {
+	GSource         source;
+	LmMessageQueue *queue;
+} MessageQueueSource;
+
+static void        message_queue_free            (LmMessageQueue *queue);
+static gboolean    message_queue_prepare_func    (GSource         *source,
+						  gint            *timeout);
+static gboolean    message_queue_check_func      (GSource         *source);
+static gboolean    message_queue_dispatch_func   (GSource         *source,
+						  GSourceFunc      callback,
+						  gpointer         user_data);
+
+static GSourceFuncs source_funcs = {
+	message_queue_prepare_func,
+	message_queue_check_func,
+	message_queue_dispatch_func,
+	NULL
+};
+
+static void
+foreach_free_message (LmMessage *m, gpointer user_data)
+{
+	lm_message_unref (m);
+	UNUSED_FORMAL_PARAM(user_data);
+}
+
+static void
+message_queue_free (LmMessageQueue *queue)
+{
+	lm_message_queue_detach (queue);
+	
+	g_queue_foreach (queue->messages, (GFunc) foreach_free_message, NULL);
+	g_queue_free (queue->messages);
+
+	g_free (queue);
+}
+
+//Prepare has to return true for check method to be called.
+static gboolean
+message_queue_prepare_func (GSource *source, gint *timeout)
+{
+	LmMessageQueue *queue;
+
+	queue = ((MessageQueueSource *)source)->queue;
+	UNUSED_FORMAL_PARAM(timeout);
+	return !g_queue_is_empty (queue->messages);
+}
+
+//check has to return true for Dispatch method to be called.
+static gboolean
+message_queue_check_func (GSource *source)
+{
+//	return FALSE;
+UNUSED_FORMAL_PARAM(source);
+return TRUE;
+}
+
+static gboolean
+message_queue_dispatch_func (GSource     *source,
+			     GSourceFunc  callback,
+			     gpointer     user_data)
+{
+	LmMessageQueue *queue;
+
+	queue = ((MessageQueueSource *)source)->queue;
+
+	if (queue->callback) {
+		(queue->callback) (queue, queue->user_data);
+	}
+	UNUSED_FORMAL_PARAM(source);
+	UNUSED_FORMAL_PARAM(callback);
+	return TRUE;
+}
+
+LmMessageQueue *
+lm_message_queue_new (LmMessageQueueCallback  callback,
+		      gpointer                user_data)
+{
+	LmMessageQueue *queue;
+
+	queue = g_new0 (LmMessageQueue, 1);
+
+	queue->messages = g_queue_new ();
+	queue->context = NULL;
+	queue->source = NULL;
+	queue->ref_count = 1;
+
+	queue->callback = callback;
+	queue->user_data = user_data;
+
+	return queue;
+}
+
+void
+lm_message_queue_attach (LmMessageQueue *queue, GMainContext *context)
+{
+	GSource *source;
+
+	if (queue->source) {
+		if (queue->context == context) {
+			/* Already attached */
+			return;
+		}
+		lm_message_queue_detach (queue);
+	}
+
+	if (context)  {
+		queue->context = g_main_context_ref (context);
+	}
+	
+	source = g_source_new (&source_funcs, sizeof (MessageQueueSource));
+	((MessageQueueSource *)source)->queue = queue;
+	queue->source = source;
+
+	g_source_attach (source, queue->context);
+}
+
+void
+lm_message_queue_detach (LmMessageQueue *queue)
+{
+	if (queue->source) {
+		g_source_destroy (queue->source);
+		g_source_unref (queue->source);
+	}
+
+	if (queue->context) {
+		g_main_context_unref (queue->context);
+	}
+
+	queue->source = NULL;
+	queue->context = NULL;
+}
+
+void
+lm_message_queue_push_tail (LmMessageQueue *queue, LmMessage *m)
+{
+	g_return_if_fail (queue != NULL);
+	g_return_if_fail (m != NULL);
+
+	g_queue_push_tail (queue->messages, m);
+}
+
+LmMessage *
+lm_message_queue_peek_nth (LmMessageQueue *queue, guint n)
+{
+	g_return_val_if_fail (queue != NULL, NULL);
+
+	return (LmMessage *) g_queue_peek_nth (queue->messages, n);
+}
+
+LmMessage *
+lm_message_queue_pop_nth (LmMessageQueue *queue, guint n)
+{
+	g_return_val_if_fail (queue != NULL, NULL);
+
+	return (LmMessage *) g_queue_pop_nth (queue->messages, n);
+}
+
+guint
+lm_message_queue_get_length (LmMessageQueue *queue)
+{
+	g_return_val_if_fail (queue != NULL, 0);
+
+	return g_queue_get_length (queue->messages);
+}
+
+gboolean 
+lm_message_queue_is_empty (LmMessageQueue *queue)
+{
+	g_return_val_if_fail (queue != NULL, TRUE);
+
+	return g_queue_is_empty (queue->messages);
+}
+
+LmMessageQueue *
+lm_message_queue_ref (LmMessageQueue *queue)
+{
+	g_return_val_if_fail (queue != NULL, NULL);
+
+	queue->ref_count++;
+
+	return queue;
+}
+
+void
+lm_message_queue_unref (LmMessageQueue *queue)
+{
+	g_return_if_fail (queue != NULL);
+
+	queue->ref_count--;
+
+	if (queue->ref_count <= 0) {
+		message_queue_free (queue);
+	}
+}
+