loudmouth/src/lm-message-queue.c
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:10:06 +0200
changeset 0 d0f3a028347a
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/* -*- 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);
	}
}