ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.c
Revision: 1.1
Committed: Tue Oct 30 20:59:31 2007 UTC (16 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Log Message:
initial roguh cut that doesn't immediately barf

File Contents

# Content
1 #include <math.h>
2 #include <stdlib.h>
3
4 #include <stdio.h>
5
6 #include <errno.h>
7 #include <sys/time.h>
8 #include <time.h>
9
10 #ifdef CLOCK_MONOTONIC
11 # define HAVE_MONOTONIC 1
12 #endif
13
14 #define HAVE_EPOLL 1
15 #define HAVE_REALTIME 1
16 #define HAVE_SELECT 0
17
18 #define MAX_BLOCKTIME 60.
19
20 #include "ev.h"
21
22 struct ev_watcher {
23 EV_WATCHER (ev_watcher);
24 };
25
26 struct ev_watcher_list {
27 EV_WATCHER_LIST (ev_watcher_list);
28 };
29
30 ev_tstamp ev_now;
31 int ev_method;
32
33 static int have_monotonic; /* runtime */
34
35 static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */
36 static void (*method_reify)(void);
37 static void (*method_poll)(ev_tstamp timeout);
38
39 ev_tstamp
40 ev_time (void)
41 {
42 #if HAVE_REALTIME
43 struct timespec ts;
44 clock_gettime (CLOCK_REALTIME, &ts);
45 return ts.tv_sec + ts.tv_nsec * 1e-9;
46 #else
47 struct timeval tv;
48 gettimeofday (&tv, 0);
49 return tv.tv_sec + tv.tv_usec * 1e-6;
50 #endif
51 }
52
53 static ev_tstamp
54 get_clock (void)
55 {
56 #if HAVE_MONOTONIC
57 if (have_monotonic)
58 {
59 struct timespec ts;
60 clock_gettime (CLOCK_MONOTONIC, &ts);
61 return ts.tv_sec + ts.tv_nsec * 1e-9;
62 }
63 #endif
64
65 return ev_time ();
66 }
67
68 #define array_needsize(base,cur,cnt,init) \
69 if ((cnt) > cur) \
70 { \
71 int newcnt = cur; \
72 do \
73 { \
74 newcnt += (newcnt >> 1) + 16; \
75 } \
76 while ((cnt) > newcnt); \
77 fprintf (stderr, "resize(" # base ") from %d to %d\n", cur, newcnt);\
78 base = realloc (base, sizeof (*base) * (newcnt)); \
79 init (base + cur, newcnt - cur); \
80 cur = newcnt; \
81 }
82
83 typedef struct
84 {
85 struct ev_io *head;
86 unsigned char wev, rev; /* want, received event set */
87 } ANFD;
88
89 static ANFD *anfds;
90 static int anfdmax;
91
92 static int *fdchanges;
93 static int fdchangemax, fdchangecnt;
94
95 static void
96 anfds_init (ANFD *base, int count)
97 {
98 while (count--)
99 {
100 base->head = 0;
101 base->wev = base->rev = EV_NONE;
102 ++base;
103 }
104 }
105
106 typedef struct
107 {
108 struct ev_watcher *w;
109 int events;
110 } ANPENDING;
111
112 static ANPENDING *pendings;
113 static int pendingmax, pendingcnt;
114
115 static void
116 event (struct ev_watcher *w, int events)
117 {
118 w->pending = ++pendingcnt;
119 array_needsize (pendings, pendingmax, pendingcnt, );
120 pendings [pendingcnt - 1].w = w;
121 pendings [pendingcnt - 1].events = events;
122 }
123
124 static void
125 fd_event (int fd, int events)
126 {
127 ANFD *anfd = anfds + fd;
128 struct ev_io *w;
129
130 for (w = anfd->head; w; w = w->next)
131 {
132 int ev = w->events & events;
133
134 if (ev)
135 event ((struct ev_watcher *)w, ev);
136 }
137 }
138
139 static struct ev_timer **timers;
140 static int timermax, timercnt;
141
142 static void
143 upheap (int k)
144 {
145 struct ev_timer *w = timers [k];
146
147 while (k && timers [k >> 1]->at > w->at)
148 {
149 timers [k] = timers [k >> 1];
150 timers [k]->active = k + 1;
151 k >>= 1;
152 }
153
154 timers [k] = w;
155 timers [k]->active = k + 1;
156
157 }
158
159 static void
160 downheap (int k)
161 {
162 struct ev_timer *w = timers [k];
163
164 while (k <= (timercnt >> 1))
165 {
166 int j = k << 1;
167
168 if (j + 1 < timercnt && timers [j]->at > timers [j + 1]->at)
169 ++j;
170
171 if (w->at <= timers [j]->at)
172 break;
173
174 timers [k] = timers [j];
175 timers [k]->active = k;
176 k = j;
177 }
178
179 timers [k] = w;
180 timers [k]->active = k + 1;
181 }
182
183 static struct ev_signal **signals;
184 static int signalmax, signalcnt;
185
186 static void
187 signals_init (struct ev_signal **base, int count)
188 {
189 while (count--)
190 *base++ = 0;
191 }
192
193 #if HAVE_EPOLL
194 # include "ev_epoll.c"
195 #endif
196 #if HAVE_SELECT
197 # include "ev_select.c"
198 #endif
199
200 int ev_init (int flags)
201 {
202 #if HAVE_MONOTONIC
203 {
204 struct timespec ts;
205 if (!clock_gettime (CLOCK_MONOTONIC, &ts))
206 have_monotonic = 1;
207 }
208 #endif
209
210 ev_now = ev_time ();
211
212 #if HAVE_EPOLL
213 if (epoll_init (flags))
214 return ev_method;
215 #endif
216 #if HAVE_SELECT
217 if (select_init (flags))
218 return ev_method;
219 #endif
220
221 ev_method = EVMETHOD_NONE;
222 return ev_method;
223 }
224
225 void ev_prefork (void)
226 {
227 }
228
229 void ev_postfork_parent (void)
230 {
231 }
232
233 void ev_postfork_child (void)
234 {
235 #if HAVE_EPOLL
236 epoll_postfork_child ();
237 #endif
238 }
239
240 static void
241 call_pending ()
242 {
243 int i;
244
245 for (i = 0; i < pendingcnt; ++i)
246 {
247 ANPENDING *p = pendings + i;
248
249 if (p->w)
250 {
251 p->w->pending = 0;
252 p->w->cb (p->w, p->events);
253 }
254 }
255
256 pendingcnt = 0;
257 }
258
259 static void
260 timer_reify (void)
261 {
262 while (timercnt && timers [0]->at <= ev_now)
263 {
264 struct ev_timer *w = timers [0];
265
266 /* first reschedule timer */
267 if (w->repeat)
268 {
269 fprintf (stderr, "a %f now %f repeat %f, %f\n", w->at, ev_now, w->repeat, w->repeat *1e30);//D
270 if (w->is_abs)
271 w->at += floor ((ev_now - w->at) / w->repeat + 1.) * w->repeat;
272 else
273 w->at = ev_now + w->repeat;
274
275 fprintf (stderr, "b %f\n", w->at);//D
276
277 downheap (0);
278 }
279 else
280 evtimer_stop (w); /* nonrepeating: stop timer */
281
282 event ((struct ev_watcher *)w, EV_TIMEOUT);
283 }
284 }
285
286 int ev_loop_done;
287
288 int ev_loop (int flags)
289 {
290 double block;
291 ev_loop_done = flags & EVLOOP_ONESHOT;
292
293 do
294 {
295 /* update fd-related kernel structures */
296 method_reify (); fdchangecnt = 0;
297
298 /* calculate blocking time */
299 ev_now = ev_time ();
300
301 if (flags & EVLOOP_NONBLOCK)
302 block = 0.;
303 else if (!timercnt)
304 block = MAX_BLOCKTIME;
305 else
306 {
307 block = timers [0]->at - ev_now + method_fudge;
308 if (block < 0.) block = 0.;
309 else if (block > MAX_BLOCKTIME) block = MAX_BLOCKTIME;
310 }
311
312 fprintf (stderr, "block %f\n", block);//D
313 method_poll (block);
314
315 /* put pending timers into pendign queue and reschedule them */
316 timer_reify ();
317
318 ev_now = ev_time ();
319 call_pending ();
320 }
321 while (!ev_loop_done);
322 }
323
324 static void
325 wlist_add (struct ev_watcher_list **head, struct ev_watcher_list *elem)
326 {
327 elem->next = *head;
328 *head = elem;
329 }
330
331 static void
332 wlist_del (struct ev_watcher_list **head, struct ev_watcher_list *elem)
333 {
334 while (*head)
335 {
336 if (*head == elem)
337 {
338 *head = elem->next;
339 return;
340 }
341
342 head = &(*head)->next;
343 }
344 }
345
346 static void
347 ev_start (struct ev_watcher *w, int active)
348 {
349 w->pending = 0;
350 w->active = active;
351 }
352
353 static void
354 ev_stop (struct ev_watcher *w)
355 {
356 if (w->pending)
357 pendings [w->pending - 1].w = 0;
358
359 w->active = 0;
360 /* nop */
361 }
362
363 void
364 evio_start (struct ev_io *w)
365 {
366 if (ev_is_active (w))
367 return;
368
369 int fd = w->fd;
370
371 ev_start ((struct ev_watcher *)w, 1);
372 array_needsize (anfds, anfdmax, fd + 1, anfds_init);
373 wlist_add ((struct ev_watcher_list **)&anfds[fd].head, (struct ev_watcher_list *)w);
374
375 ++fdchangecnt;
376 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
377 fdchanges [fdchangecnt - 1] = fd;
378 }
379
380 void
381 evio_stop (struct ev_io *w)
382 {
383 if (!ev_is_active (w))
384 return;
385
386 wlist_del ((struct ev_watcher_list **)&anfds[w->fd].head, (struct ev_watcher_list *)w);
387 ev_stop ((struct ev_watcher *)w);
388
389 ++fdchangecnt;
390 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
391 fdchanges [fdchangecnt - 1] = w->fd;
392 }
393
394 void
395 evtimer_start (struct ev_timer *w)
396 {
397 if (ev_is_active (w))
398 return;
399
400 fprintf (stderr, "t1 %f a %d\n", w->at, w->is_abs);//D
401 if (w->is_abs)
402 {
403 if (w->repeat)
404 w->at += ceil ((ev_now - w->at) / w->repeat) * w->repeat;
405 }
406 else
407 w->at += ev_now;
408 fprintf (stderr, "t2 %f a %d\n", w->at, w->is_abs);//D
409
410 ev_start ((struct ev_watcher *)w, ++timercnt);
411 array_needsize (timers, timermax, timercnt, );
412 timers [timercnt - 1] = w;
413 upheap (timercnt - 1);
414 }
415
416 void
417 evtimer_stop (struct ev_timer *w)
418 {
419 if (!ev_is_active (w))
420 return;
421
422 timers [w->active - 1] = timers [--timercnt];
423 downheap (w->active - 1);
424 ev_stop ((struct ev_watcher *)w);
425 }
426
427 void
428 evsignal_start (struct ev_signal *w)
429 {
430 if (ev_is_active (w))
431 return;
432
433 ev_start ((struct ev_watcher *)w, 1);
434 array_needsize (signals, signalmax, w->signum, signals_init);
435 wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w);
436 }
437
438 void
439 evsignal_stop (struct ev_signal *w)
440 {
441 if (!ev_is_active (w))
442 return;
443
444 wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w);
445 ev_stop ((struct ev_watcher *)w);
446 }
447
448 /*****************************************************************************/
449 #if 1
450
451 static void
452 sin_cb (struct ev_io *w, int revents)
453 {
454 fprintf (stderr, "sin %d, revents %d\n", w->fd, revents);
455 }
456
457 static void
458 ocb (struct ev_timer *w, int revents)
459 {
460 fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data);
461 }
462
463 int main (void)
464 {
465 struct ev_io sin;
466
467 ev_init (0);
468
469 evw_init (&sin, sin_cb, 55);
470 evio_set (&sin, 0, EV_READ);
471 evio_start (&sin);
472
473 struct ev_timer t1;
474 evw_init (&t1, ocb, 1);
475 evtimer_set_rel (&t1, 1, 0);
476 evtimer_start (&t1);
477
478 struct ev_timer t2;
479 evw_init (&t2, ocb, 2);
480 evtimer_set_abs (&t2, ev_time () + 2, 0);
481 evtimer_start (&t2);
482
483 ev_loop (0);
484
485 return 0;
486 }
487
488 #endif
489
490
491
492