#include "defs.h"
static int id = 0;
static struct timeout_q *Q = 0;
static int in_callout = 0;
struct timeout_q {
struct timeout_q *next;
int id;
cfunc_t func;
char *data;
int time;
};
#ifdef IGMP_DEBUG
static void print_Q(void);
#else
#define print_Q()
#endif
void
callout_init(void)
{
Q = (struct timeout_q *) 0;
}
void
age_callout_queue(void)
{
struct timeout_q *ptr;
if (in_callout)
return;
in_callout = 1;
ptr = Q;
while (ptr) {
if (!ptr->time) {
Q = Q->next;
in_callout = 0;
if (ptr->func)
ptr->func(ptr->data);
in_callout = 1;
free(ptr);
ptr = Q;
}
else {
ptr->time --;
#ifdef IGMP_DEBUG
logit(LOG_DEBUG,0,"[callout, age_callout_queue] -- time (%d)", ptr->time);
#endif
in_callout = 0; return;
}
}
in_callout = 0;
return;
}
int
timer_setTimer(int delay, cfunc_t action, char *data)
{
struct timeout_q *ptr, *node, *prev;
if (in_callout)
return -1;
in_callout = 1;
node = malloc(sizeof(struct timeout_q));
if (node == 0) {
logit(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n");
in_callout = 0;
return -1;
}
node->func = action;
node->data = data;
node->time = delay;
node->next = 0;
node->id = ++id;
prev = ptr = Q;
if (!Q)
Q = node;
else {
while (ptr) {
if (delay < ptr->time) {
node->next = ptr;
if (ptr == Q)
Q = node;
else
prev->next = node;
ptr->time -= node->time;
print_Q();
in_callout = 0;
return node->id;
} else {
delay -= ptr->time; node->time = delay;
prev = ptr;
ptr = ptr->next;
}
}
prev->next = node;
}
print_Q();
in_callout = 0;
return node->id;
}
void
timer_clearTimer(int timer_id)
{
struct timeout_q *ptr, *prev;
if (in_callout)
return;
if (!timer_id)
return;
in_callout = 1;
prev = ptr = Q;
print_Q();
while (ptr) {
if (ptr->id == timer_id) {
if (ptr == Q)
Q = Q->next;
else
prev->next = ptr->next;
if (ptr->next != 0)
(ptr->next)->time += ptr->time;
free(ptr->data);
free(ptr);
print_Q();
in_callout = 0;
return;
}
prev = ptr;
ptr = ptr->next;
}
print_Q();
in_callout = 0;
}
#ifdef IGMP_DEBUG
static void
print_Q(void)
{
struct timeout_q *ptr;
for(ptr = Q; ptr; ptr = ptr->next)
logit(LOG_DEBUG,0,"(%d,%d) ", ptr->id, ptr->time);
}
#endif
int
secs_remaining(int timer_id)
{
struct timeout_q *ptr;
int left=0;
for (ptr = Q; ptr && ptr->id != timer_id; ptr = ptr->next)
left += ptr->time;
if (!ptr)
return 0;
return left + ptr->time;
}