/*
 * msgqueue.c
 * Primitive message queue.
 *
 * Copyright (C) Leni Mayo 2001-2002
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License, version 2, as
 *	published by the Free Software Foundation.
 *	
 *	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 General Public License for more details.
 *	
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*
 * Note:
 * The use of a singly linked list here implies worst-case complexity
 * of O(n) for msgqueueAdd().  Don't worry about this too much for the mo.
 * leni - Fri Dec 14 09:50:22 EST 2001
 */

#include <stdlib.h> /* for free() */
#include "msgqueue.h"

static GSList *pList = NULL; 

typedef struct
{
	ServiceId id;    /* identifies the Node */
	Event     event; /* the event to be dispatched to the Node's fsm */
} Item;

void msgqueueInitialise()
{
	pList = NULL;
}

void msgqueueCleanup()
{
	GSList *pElement;

	for (pElement = pList; pElement != NULL; pElement = pElement->next)
	{
		assert(pElement->data);
		free(pElement->data);
	}

	if (pList != NULL)
	{
		g_slist_free(pList);
	}
}

void msgqueueAdd(const ServiceId id, Event event)
{
	Item *pItem;

	assert(id != 0);

	pItem = malloc(sizeof(Item));  /* leni TODO: test memory alloc */
	pItem->id = id;
	pItem->event = event;

	pList = g_slist_append(pList, pItem);
}

/*
 * returns true if an element was removed from the queue,
 *         false if the queue was empty
 */
int msgqueueRemove(ServiceId *pId, Event *pEvent)
{
	GSList *pElement;
	int ret = FALSE;

	assert(pId);
	assert(pEvent);

	if (pList)
	{
		pElement = pList;

		pList = g_slist_remove_link(pList, pElement);

		*pId = ((Item *) pElement->data)->id;
		*pEvent = ((Item *) pElement->data)->event;

		free(pElement->data);
		g_slist_free_1(pElement);

		ret = TRUE;
	}

	return ret;
}
