1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/* Copyright (C) 2000 edwards@bitchx.dimension6.com
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
Modified by drscholl@users.sourceforge.net 2/29/2000.
$Id: timer.c,v 1.10 2001/03/06 06:49:53 drscholl Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <time.h>
#include <stdlib.h>
#include "opennap.h"
#include "debug.h"
typedef struct _timerstruct
{
struct _timerstruct *next;
timer_cb_t func;
void *arg;
time_t next_time;
time_t interval;
int events;
unsigned int refnum;
}
TIMER;
static TIMER *Pending_Timers = NULL;
static unsigned int TimerRef = 0;
static void
schedule_timer (TIMER * ntimer)
{
TIMER **slot;
if (!ntimer->events)
return;
/* we've created it, now put it in order */
for (slot = &Pending_Timers; *slot; slot = &(*slot)->next)
{
if (ntimer->next_time < (*slot)->next_time)
break;
}
ntimer->next = *slot;
*slot = ntimer;
}
/* returns the refnum */
int
add_timer (int interval, int events, timer_cb_t func, void *arg)
{
TIMER *new;
if (!events)
return -1;
new = CALLOC (1, sizeof (TIMER));
if (!new)
{
OUTOFMEMORY ("add_timer");
return -1;
}
new->next_time = global.current_time + interval;
new->interval = interval;
new->func = func;
new->arg = arg;
new->events = events;
new->refnum = TimerRef++;
schedule_timer (new);
return new->refnum;
}
void
exec_timers (time_t now)
{
TIMER *current;
while (Pending_Timers && Pending_Timers->next_time <= now)
{
current = Pending_Timers;
Pending_Timers = current->next;
(*current->func) (current->arg);
switch (current->events)
{
case 0:
FREE (current);
break;
default:
current->events--;
case -1:
/* reschedule */
current->next_time = global.current_time + current->interval;
schedule_timer (current);
break;
}
}
}
/* returns the time offset at which the next pending event is scheduled */
time_t next_timer (void)
{
if (Pending_Timers)
{
if (Pending_Timers->next_time < global.current_time)
return 0; /* now! */
return (Pending_Timers->next_time - global.current_time);
}
return -1;
}
void
free_timers (void)
{
TIMER *ptr;
while (Pending_Timers)
{
ptr = Pending_Timers;
Pending_Timers = Pending_Timers->next;
FREE (ptr);
}
}
/* change the interval at which a timer occurs. note that this does not
* reschedule a currently pending event, and only affect subsequent calls
*/
void
timer_set_interval (unsigned int refnum, int interval)
{
TIMER *t = Pending_Timers;
for (; t; t = t->next)
if (t->refnum == refnum)
{
t->interval = interval;
break;
}
}
|