File: timer.c

package info (click to toggle)
opennap 0.44-2
  • links: PTS
  • area: main
  • in suites: sarge, woody
  • size: 1,568 kB
  • ctags: 1,750
  • sloc: ansic: 20,321; sh: 475; makefile: 98
file content (141 lines) | stat: -rw-r--r-- 2,783 bytes parent folder | download
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;
	}
}