Annotation of embedaddon/trafshow/events.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1999-2003 Rinet Corp., Novosibirsk, Russia
3: *
4: * Redistribution and use in source forms, with and without modification,
5: * are permitted provided that this entire comment appears intact.
6: *
7: * THIS SOURCE CODE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
8: */
9:
10: #ifdef HAVE_CONFIG_H
11: #include <config.h>
12: #endif
13:
14: #include <sys/types.h>
15: #include <sys/time.h>
16: #include <time.h>
17: #include <stdlib.h>
18: #include <string.h>
19:
20: #include "events.h"
21:
22: #define dprintf(x) /* nope */
23:
24: static EVENT *first_event = 0; /* first system event in table */
25:
26: /*
27: * Subtract 2 timeval structs: out = out - in. Out result always greater 0.
28: */
29: void
30: tv_sub(out, in)
31: struct timeval *out;
32: const struct timeval *in;
33: {
34: if (out->tv_sec > in->tv_sec) {
35: out->tv_sec -= in->tv_sec;
36: if (out->tv_usec >= in->tv_usec) {
37: out->tv_usec -= in->tv_usec;
38: } else {
39: out->tv_sec--;
40: out->tv_usec += 1000000L - in->tv_usec;
41: }
42: } else if (out->tv_sec == in->tv_sec) {
43: out->tv_sec = 0L;
44: out->tv_usec -= in->tv_usec;
45: if (out->tv_usec < 1)
46: out->tv_usec = 100L; /* not zero anyway */
47: } else {
48: out->tv_sec = 0L;
49: out->tv_usec = 100L; /* not zero anyway */
50: }
51: }
52:
53: void
54: tv_add(out, in)
55: struct timeval *out;
56: const struct timeval *in;
57: {
58: out->tv_sec += in->tv_sec;
59: out->tv_usec += in->tv_usec;
60: if (out->tv_usec >= 1000000L) {
61: out->tv_sec++;
62: out->tv_usec -= 1000000L;
63: }
64: }
65:
66: /*
67: * Round timeval to seconds.
68: */
69: u_long
70: tv_round(in)
71: const struct timeval *in;
72: {
73: u_long sec = in->tv_sec;
74: if (in->tv_usec >= 500000L)
75: sec++;
76: return sec;
77: }
78:
79: /*
80: * Return time difference in milliseconds.
81: */
82: u_long
83: tv_diff(tvp1, tvp2)
84: const struct timeval *tvp1, *tvp2;
85: {
86: struct timeval diff;
87:
88: if (!timerisset(tvp1) || !timerisset(tvp2))
89: return 0;
90:
91: if (timercmp(tvp1, tvp2, >)) {
92: diff = *tvp1;
93: tv_sub(&diff, tvp2);
94: } else {
95: diff = *tvp2;
96: tv_sub(&diff, tvp1);
97: }
98: return (diff.tv_sec * 1000 + diff.tv_usec / 1000);
99: }
100:
101: /*
102: * Shift the time to be sharp at (12am + N * period), local time.
103: */
104: void
105: tv_sharp(tvp, period)
106: struct timeval *tvp;
107: int period;
108: {
109: time_t defect;
110: struct tm *tm;
111:
112: if (!tvp) return;
113:
114: tm = localtime((time_t *)&tvp->tv_sec);
115: defect = tm->tm_sec + 60 * tm->tm_min + 3600 * tm->tm_hour;
116: defect %= period;
117: period -= defect;
118: if (period < 1) period = 1;
119: tvp->tv_sec += period;
120: tvp->tv_usec = (long)random() % 1000000L;
121: }
122:
123: /*
124: * Execute pending event and schedule the next nearest.
125: */
126: int
127: select_event(tvp)
128: struct timeval *tvp;
129: {
130: EVENT *ep, *next_event;
131: struct timeval now, gap, earliest;
132:
133: gettimeofday(&now, 0);
134: gap.tv_sec = 0;
135: gap.tv_usec = 1000L; /* 0.001sec grip */
136: tv_add(&gap, &now);
137: again:
138: next_event = 0;
139: timerclear(&earliest);
140:
141: for (ep = first_event; ep; ep = ep->next) {
142: /* skip over the empty slots */
143: if (!ep->func) continue;
144:
145: if (timercmp(&gap, &ep->tv, >)) {
146: void (*func)() = ep->func;
147: ep->func = 0; /* free event slot before */
148:
149: dprintf(("-call_event(%p/%p)", func, ep->arg));
150:
151: (*func)(ep->arg); /* call event function */
152: goto again;
153:
154: } else if (!timerisset(&earliest) ||
155: timercmp(&ep->tv, &earliest, <)) {
156: earliest = ep->tv;
157: next_event = ep;
158: }
159: }
160: if (!next_event) { /* no more awaiting events */
161:
162: dprintf(("select_event: no timeout"));
163:
164: return 1; /* timeout undefined */
165: }
166: if (tvp) {
167: tv_sub(&earliest, &now);
168: *tvp = earliest;
169:
170: dprintf(("=wait_event(%p/%p): timeout=%u.%03d",
171: next_event->func, next_event->arg,
172: (unsigned)tvp->tv_sec, (int)(tvp->tv_usec / 1000)));
173: }
174: return 0; /* timeout defined */
175: }
176:
177: /*
178: * Add the new system event to be executed at the given time.
179: */
180: int
181: add_event(tvp, func, arg)
182: struct timeval *tvp;
183: void (*func)(void *);
184: void *arg;
185: {
186: EVENT *ep, *prev = 0, *next = 0;
187: struct timeval now, gap;
188:
189: if (!tvp) {
190: gettimeofday(&now, 0);
191: gap.tv_sec = 0;
192: gap.tv_usec = 250000L; /* 0.25sec mean a bit later */
193: tv_add(&gap, &now);
194: tvp = ⪆
195: }
196:
197: /*
198: * The same event in queue may cause a looping! Prevent it.
199: */
200: for (ep = first_event; ep; ep = ep->next) {
201: if (ep->func == func && ep->arg == arg) {
202: ep->tv = *tvp;
203: dprintf(("=add_event(%p/%p): modify time", func, arg));
204: return 0;
205: }
206: }
207:
208: /*
209: * Search for first empty or last event slot.
210: */
211: for (ep = first_event; ep; ep = ep->next) {
212: if (!ep->func) {
213: next = ep->next;
214: break;
215: }
216: prev = ep;
217: }
218: if (!ep && (ep = (EVENT *)malloc(sizeof(EVENT))) == 0)
219: return -1;
220: memset(ep, 0, sizeof(EVENT));
221: ep->tv = *tvp;
222: ep->func = func;
223: ep->arg = arg;
224: if (next) ep->next = next;
225: else if (prev) prev->next = ep;
226: if (!first_event) first_event = ep;
227:
228: #ifdef notdef
229: {
230: char at_time[50];
231: strftime(at_time, sizeof(at_time), "%T",
232: localtime((time_t *)&ep->tv.tv_sec));
233: dprintf(("+add_event(%p/%p): schedule=%s.%03d",
234: func, arg, at_time, (int)(tvp->tv_usec / 1000)));
235: }
236: #endif
237: return 0;
238: }
239:
240: /*
241: * Remove system event from queue if any.
242: */
243: int
244: remove_event(func, arg)
245: void (*func)(void *);
246: void *arg;
247: {
248: int found = 0;
249: EVENT *ep;
250:
251: for (ep = first_event; ep; ep = ep->next) {
252: if ((!func || ep->func == func) && ep->arg == arg) {
253: ep->func = 0;
254: found++;
255: }
256: }
257: return found;
258: }
259:
260: /*
261: * Modify existing system event in queue for the new function argument.
262: */
263: int
264: change_event(func, arg, new_arg)
265: void (*func)(void *);
266: void *arg, *new_arg;
267: {
268: int found = 0;
269: EVENT *ep;
270:
271: for (ep = first_event; ep; ep = ep->next) {
272: if ((!func || ep->func == func) && ep->arg == arg) {
273: ep->arg = new_arg;
274: found++;
275: }
276: }
277: return found;
278: }
279:
280: EVENT *
281: find_event(func, arg)
282: void (*func)(void *);
283: void *arg;
284: {
285: EVENT *ep;
286:
287: for (ep = first_event; ep; ep = ep->next) {
288: if (ep->func == func && ep->arg == arg)
289: return ep;
290: }
291: return 0;
292: }
293:
294: void
295: free_events()
296: {
297: EVENT *ep, *next;
298:
299: ep = first_event;
300: while (ep) {
301: next = ep->next;
302: free(ep);
303: ep = next;
304: }
305: first_event = 0;
306: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>