git @ Cat's Eye Technologies beta-Juliet / master src / equeue.c
master

Tree @master (Download .tar.gz)

equeue.c @masterraw · history · blame

/*
 * Copyright (c)2004 Cat's Eye Technologies.  All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * 
 *   Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 * 
 *   Neither the name of Cat's Eye Technologies nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission. 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
/*
 * equeue.c
 * Event queue housekeeping and manipulation for 2Iota.
 * $Id: equeue.c 518 2010-04-28 17:48:38Z cpressey $
 */

#include <stdio.h>
#include <stdlib.h>

#include "equeue.h"
#include "symstr.h"
#include "etime.h"
#include "ehist.h"
#include "debug.h"
#include "2iota.h"

struct equeue *
equeue_new(void)
{
	struct equeue *eq;

	MALLOC(eq, equeue, "event queue");

	eq->head = NULL;
	return(eq);
}

/*
 * If delay == NULL, use a delay of zero.
 */
struct equeue_entry *
equeue_insert(struct equeue *eq, struct symstr *ss, struct etime *delay)
{
	struct equeue_entry *eqe;
	struct etime et;

	if (delay == NULL)
		et = etime_zero;
	else
		et = *delay;

	MALLOC(eqe, equeue_entry, "event queue entry");

	eqe->name = ss;		/* Note that this is NOT dup'ed. */
	eqe->delay = et;

	eqe->next = eq->head;
	eqe->prev = NULL;
	if (eq->head != NULL)
		eq->head->prev = eqe;

	eq->head = eqe;

	debug_trace(TRACE_QUEUE, "Inserted %S with delay %T", ss, &et);
	
	return(eqe);
}

/*
 * Remove the next-up entry from the queue.  NULL is returned if the queue is empty.
 */
struct equeue_entry *
equeue_remove(struct equeue *eq)
{
	struct equeue_entry *eqe, *soonest;

	if (eq->head == NULL)
		return(NULL);

	soonest = eq->head;
	for (eqe = eq->head; eqe != NULL; eqe = eqe->next) {
		if (etime_compare(&eqe->delay, &soonest->delay) < 0)
			soonest = eqe;
	}

	/* unlink soonest */
	
	if (soonest->prev == NULL)
		eq->head = soonest->next;
	else
		soonest->prev->next = soonest->next;
	if (soonest->next != NULL)
		soonest->next->prev = soonest->prev;

	soonest->next = NULL;
	soonest->prev = NULL;

	debug_trace(TRACE_QUEUE, "Removed %S with delay %T",
	    soonest->name, &soonest->delay);

	return(soonest);
}

void
equeue_time_passes(struct equeue *eq, struct etime *dur)
{
	struct equeue_entry *eqe;

	for (eqe = eq->head; eqe != NULL; eqe = eqe->next) {
		etime_delta(&eqe->delay, dur, -1);
	}
}

/*
 * Transfer all equeue entries from the event queue from_eq
 * to the event queue to_eq.  NOTE: from_eq is then deallocated.
 */
void
equeue_transfer(struct equeue *to_eq, struct equeue *from_eq)
{
	struct equeue_entry *eqe;

	if (to_eq->head == NULL) {
		to_eq->head = from_eq->head;
	} else {
		eqe = to_eq->head;
		while (eqe->next != NULL)
			eqe = eqe->next;
		eqe->next = from_eq->head;
		if (from_eq->head != NULL)
			from_eq->head->prev = eqe->next;
	}

	from_eq->head = NULL;
	equeue_free(from_eq);
}

void
equeue_free(struct equeue *eq)
{
	struct equeue_entry *eqe, *neqe;

	if (eq == NULL)
		return;

	eqe = eq->head;
	while (eqe != NULL) {
		neqe = eqe->next;
		equeue_entry_free(eqe);
		eqe = neqe;
	}
	
	free(eq);
}

void
equeue_entry_free(struct equeue_entry *eqe)
{
	if (eqe == NULL)
		return;
	symstr_free(eqe->name);
	free(eqe);
}

void
equeue_dump(struct equeue *eq)
{
	struct equeue_entry *eqe;
	
	for (eqe = eq->head; eqe != NULL; eqe = eqe->next) {
		symstr_dump(eqe->name);
		fprintf(stderr, " in ");
		etime_dump(&eqe->delay);
		fprintf(stderr, "\n");
	}
}