#if !defined(lint) && !defined(__INSIGHT__)
static char sos__rcsid[] = "eventq.c,v 1.1.1.1 1995/06/16 17:42:40 seth Exp";
static char sos__copyright[] = "Copyright (c) 1994, 1995 SOS Corporation";
static char sos__contact[] = "SOS Corporation <sos-info@soscorp.com> +1 800 SOS UNIX";
#endif /* not lint */

/*
 * ++Copyright Released Product++
 *
 * Copyright (c) 1994, 1995 Sources of Supply Corporation ("SOS").
 * All rights reserved.
 *
 * The SOS Released Product License Agreement specifies the terms and
 * conditions for redistribution.  You may find the License Agreement
 * in the file LICENSE.
 *
 * SOS Corporation
 * 461 5th Ave.; 16th floor
 * New York, NY 10017
 *
 * +1 800 SOS UNIX
 * <sos-info@soscorp.com>
 *
 * --Copyright Released Product--
 */

/*
 * Generic event queue--events occur at or after their scheduled times
 * (granularity depends on granularity of caller)
 */

#include "sos.h"

#include <pq.h>


struct seq_event
{
  time_t when;
  void (*event)(void *args);
  void *args;
};


static int seq_compare(struct seq_event *a, struct seq_event *b);



/*
 * Add an event to the event queue
 * return number of second to next event
 *
 * -1 on error
 */
int sos_event_enqueue(pq_h equeue, time_t when, void (*event)(void *args), void *args, void **handle)
{
  int diff;
  struct seq_event *new = malloc(sizeof(struct seq_event));
  struct seq_event *head;

  if (!new || !equeue)
    return(-1);

  new->when = when;
  new->event = event;
  new->args = args;

  if (pq_insert(equeue, new) < 0)
    return(-1);

  head = pq_head(equeue);
  if (!head)
    return(-1);			/* We just added something!!! */

  if (handle)
    *handle = new;

  diff = head->when - time(NULL);
  if (diff < 0)
    diff = 0;
}



/*
 * Check to see if any events need to be fired
 * (fire all those up for consideration)
 * return number of second to next event
 *
 * -1 on error
 * 0 if no more events
 */
int sos_event_check(pq_h equeue)
{
  struct seq_event *head;

  while (head = pq_head(equeue))
    {
      int diff = head->when - time(NULL);

      if (diff > 0)
	return(diff);

      (*head->event)(head->args);

      /* This had better be the same as head */
      pq_extract_head(equeue);
      free(head);
    }

  return(0);			/* No more events */
}



/*
 * Check to see if any events need to be fired
 * return number of second to next event
 *
 * -1 on error
 * 0 if no more events
 */
pq_h sos_event_createq()
{
  return(pq_create(seq_compare,PQ_RETURN_ERROR,NULL));
}



/*
 * Function for event queue comparisons
 */
static int seq_compare(struct seq_event *a, struct seq_event *b)
{
  return(a->when < b->when);
}
