/*     
 * $RCSfile: xk_queue.c,v $
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1993,1991,1990,1996  Arizona Board of Regents
 *
 * $Log: xk_queue.c,v $
 * Revision 1.1  1997/03/11  20:47:08  dorgival
 * Initial revision
 *
 * Revision 1.1  1997/03/11 20:47:08  dorgival
 * Initial revision
 *
 *
 */

/*
 * General queue manager.  It is not safe for asynchronous usage.
 */
#include <assert.h>

#include "xk_queue.h"


void
queueInit (Queue q)
{
    q->head = q->tail = 0;
}


void
queueAppend(Queue q, void * element)
{
    QueueEl el = element;

    assert(element);

    el->next = 0;
    if (q->tail) {
	q->tail->next = el;
    }
    q->tail = el;
    if (!q->head) {
	q->head = el;
    }
}


void
queueInsert(Queue q, void * afterElement, void * element)
{
    QueueEl after = afterElement;
    QueueEl el = element;

    assert(element && afterElement);
    if (after) {
	el->next = after->next;
	after->next = el;
	if (q->tail == after) {
	    q->tail = el;
	}
    } else {
	/* insert at head of queue: */
	if (q->head) {
	    el->next = q->head->next;
	}
	q->head = el;
	if (!q->tail) {
	    q->tail = el;
	}
    }
}


void *
queueRemove (Queue q)
{
    QueueEl el;

    if (!q->head) {
	/* cannot remove from empty queue: */
	return 0;
    }
    el = q->head;
    q->head = el->next;

    if (!q->head) {
	q->tail = 0;
    }
    return el;
}


void
queueDelete(Queue q, void * afterElement)
{
    QueueEl after = afterElement;
    QueueEl el;

    assert(afterElement);
    if (after) {
	el = after->next;
	if (el) {
	    after->next = el->next;
	    if (q->tail == el) {
		q->tail = after;
	    }
	}
    } else {
	/* remove first element in queue: */
	if (q->head) {
	    q->head = q->head->next;
	    if (!q->head) {
		q->tail = 0;
	    }
	}
    }
}
