~ubuntu-branches/ubuntu/raring/lcd4linux/raring

1.1.2 by Reinhard Tartler
Import upstream version 0.10.1~rc1
1
/* $Id: timer.c 728 2007-01-14 11:14:38Z michael $
2
 * $URL: https://ssl.bulix.org/svn/lcd4linux/branches/0.10.1/timer.c $
1 by Norbert Tretkowski
Import upstream version 0.10.0+cvs20051015
3
 *
4
 * generic timer handling
5
 *
6
 * Copyright (C) 2003, 2004 Michael Reinelt <reinelt@eunet.at>
7
 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2, or (at your option)
12
 * any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
 *
23
 */
24
25
/* 
26
 * exported functions:
27
 *
28
 * int timer_add (void(*callback)(void *data), void *data, int interval, int one_shot);
29
 *   adds a timer to the queue
30
 *
31
 * int timer_process (struct timespec *delay);
32
 *   process timer queue
33
 *
34
 * void timer_exit();
35
 *   release all timers
36
 *
37
 */
38
39
40
#include "config.h"
41
42
#include <stdlib.h>
43
#include <stdio.h>
44
#include <string.h>
45
#include <sys/time.h>
46
#include <time.h>
47
48
#include "debug.h"
49
#include "cfg.h"
50
#include "timer.h"
51
52
#ifdef WITH_DMALLOC
53
#include <dmalloc.h>
54
#endif
55
56
57
typedef struct TIMER {
58
    void (*callback) (void *data);
59
    void *data;
60
    struct timeval when;
61
    int interval;
62
    int one_shot;
63
    int active;
64
} TIMER;
65
66
67
TIMER *Timers = NULL;
68
int nTimers = 0;
69
70
71
static void timer_inc(struct timeval *tv, const int msec)
72
{
73
    tv->tv_sec += msec / 1000;
74
    tv->tv_usec += (msec - 1000 * (msec / 1000)) * 1000;
75
76
    if (tv->tv_usec >= 1000000) {
77
	tv->tv_usec -= 1000000;
78
	tv->tv_sec++;
79
    }
80
}
81
82
83
int timer_add(void (*callback) (void *data), void *data, const int interval, const int one_shot)
84
{
85
    int i;
86
    struct timeval now;
87
88
    /* find a free slot */
89
    for (i = 0; i < nTimers; i++) {
90
	if (Timers[i].active == 0)
91
	    break;
92
    }
93
94
    /* none found, allocate a new slot */
95
    if (i >= nTimers) {
96
	nTimers++;
97
	Timers = realloc(Timers, nTimers * sizeof(*Timers));
98
    }
99
100
    gettimeofday(&now, NULL);
101
102
    /* fill slot */
103
    Timers[i].callback = callback;
104
    Timers[i].data = data;
105
    Timers[i].when = now;
106
    Timers[i].interval = interval;
107
    Timers[i].one_shot = one_shot;
108
    Timers[i].active = 1;
109
110
    /* if one-shot timer, don't fire now */
111
    if (one_shot) {
112
	timer_inc(&Timers[i].when, interval);
113
    }
114
115
    return 0;
116
}
117
118
119
int timer_process(struct timespec *delay)
120
{
121
    int i, flag, min;
122
    struct timeval now;
123
124
    /* the current moment */
125
    gettimeofday(&now, NULL);
126
127
    /* sanity check */
128
    if (nTimers == 0) {
129
	error("huh? not one single timer to process? dazed and confused...");
130
	return -1;
131
    }
132
133
    /* process expired timers */
134
    flag = 0;
135
    for (i = 0; i < nTimers; i++) {
136
	if (Timers[i].active == 0)
137
	    continue;
138
	if (timercmp(&Timers[i].when, &now, <=)) {
139
	    flag = 1;
140
	    /* callback */
141
	    if (Timers[i].callback != NULL) {
142
		Timers[i].callback(Timers[i].data);
143
	    }
144
	    /* respawn or delete timer */
145
	    if (Timers[i].one_shot) {
146
		Timers[i].active = 0;
147
	    } else {
148
		Timers[i].when = now;
149
		timer_inc(&Timers[i].when, Timers[i].interval);
150
	    }
151
	}
152
    }
153
154
    /* find next timer */
155
    flag = 1;
156
    min = -1;
157
    for (i = 0; i < nTimers; i++) {
158
	if (Timers[i].active == 0)
159
	    continue;
160
	if (flag || timercmp(&Timers[i].when, &Timers[min].when, <)) {
161
	    flag = 0;
162
	    min = i;
163
	}
164
    }
165
166
    if (min < 0) {
167
	error("huh? not one single timer left? dazed and confused...");
168
	return -1;
169
    }
170
171
    /* delay until next timer event */
172
    delay->tv_sec = Timers[min].when.tv_sec - now.tv_sec;
173
    delay->tv_nsec = Timers[min].when.tv_usec - now.tv_usec;
174
    if (delay->tv_nsec < 0) {
175
	delay->tv_sec--;
176
	delay->tv_nsec += 1000000;
177
    }
178
    /* nanoseconds!! */
179
    delay->tv_nsec *= 1000;
180
181
    return 0;
182
183
}
184
185
186
void timer_exit(void)
187
{
188
189
    nTimers = 0;
190
191
    if (Timers != NULL) {
192
	free(Timers);;
193
	Timers = NULL;
194
    }
195
}