ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.c
(Generate patch)

Comparing libev/ev.c (file contents):
Revision 1.2 by root, Tue Oct 30 21:42:12 2007 UTC vs.
Revision 1.4 by root, Tue Oct 30 23:10:33 2007 UTC

1#include <math.h> 1#include <math.h>
2#include <stdlib.h> 2#include <stdlib.h>
3 3
4#include <stdio.h> 4#include <stdio.h>
5 5
6#include <assert.h>
6#include <errno.h> 7#include <errno.h>
7#include <sys/time.h> 8#include <sys/time.h>
8#include <time.h> 9#include <time.h>
9 10
10#ifdef CLOCK_MONOTONIC 11#ifdef CLOCK_MONOTONIC
13 14
14#define HAVE_EPOLL 1 15#define HAVE_EPOLL 1
15#define HAVE_REALTIME 1 16#define HAVE_REALTIME 1
16#define HAVE_SELECT 0 17#define HAVE_SELECT 0
17 18
19#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
18#define MAX_BLOCKTIME 60. 20#define MAX_BLOCKTIME 60.
19 21
20#include "ev.h" 22#include "ev.h"
21 23
22struct ev_watcher { 24struct ev_watcher {
25 27
26struct ev_watcher_list { 28struct ev_watcher_list {
27 EV_WATCHER_LIST (ev_watcher_list); 29 EV_WATCHER_LIST (ev_watcher_list);
28}; 30};
29 31
32static ev_tstamp now, diff; /* monotonic clock */
30ev_tstamp ev_now; 33ev_tstamp ev_now;
31int ev_method; 34int ev_method;
32 35
33static int have_monotonic; /* runtime */ 36static int have_monotonic; /* runtime */
34 37
129 if (ev) 132 if (ev)
130 event ((struct ev_watcher *)w, ev); 133 event ((struct ev_watcher *)w, ev);
131 } 134 }
132} 135}
133 136
134static struct ev_timer **timers; 137static struct ev_timer **atimers;
135static int timermax, timercnt; 138static int atimermax, atimercnt;
136 139
140static struct ev_timer **rtimers;
141static int rtimermax, rtimercnt;
142
137static void 143static void
138upheap (int k) 144upheap (struct ev_timer **timers, int k)
139{ 145{
140 struct ev_timer *w = timers [k]; 146 struct ev_timer *w = timers [k];
141 147
142 while (k && timers [k >> 1]->at > w->at) 148 while (k && timers [k >> 1]->at > w->at)
143 { 149 {
150 timers [k]->active = k + 1; 156 timers [k]->active = k + 1;
151 157
152} 158}
153 159
154static void 160static void
155downheap (int k) 161downheap (struct ev_timer **timers, int N, int k)
156{ 162{
157 struct ev_timer *w = timers [k]; 163 struct ev_timer *w = timers [k];
158 164
159 while (k < (timercnt >> 1)) 165 while (k < (N >> 1))
160 { 166 {
161 int j = k << 1; 167 int j = k << 1;
162 168
163 if (j + 1 < timercnt && timers [j]->at > timers [j + 1]->at) 169 if (j + 1 < N && timers [j]->at > timers [j + 1]->at)
164 ++j; 170 ++j;
165 171
166 if (w->at <= timers [j]->at) 172 if (w->at <= timers [j]->at)
167 break; 173 break;
168 174
174 timers [k] = w; 180 timers [k] = w;
175 timers [k]->active = k + 1; 181 timers [k]->active = k + 1;
176} 182}
177 183
178static struct ev_signal **signals; 184static struct ev_signal **signals;
179static int signalmax, signalcnt; 185static int signalmax;
180 186
181static void 187static void
182signals_init (struct ev_signal **base, int count) 188signals_init (struct ev_signal **base, int count)
183{ 189{
184 while (count--) 190 while (count--)
201 have_monotonic = 1; 207 have_monotonic = 1;
202 } 208 }
203#endif 209#endif
204 210
205 ev_now = ev_time (); 211 ev_now = ev_time ();
212 now = get_clock ();
213 diff = ev_now - now;
206 214
207#if HAVE_EPOLL 215#if HAVE_EPOLL
208 if (epoll_init (flags)) 216 if (epoll_init (flags))
209 return ev_method; 217 return ev_method;
210#endif 218#endif
250 258
251 pendingcnt = 0; 259 pendingcnt = 0;
252} 260}
253 261
254static void 262static void
255timer_reify (void) 263timers_reify (struct ev_timer **timers, int timercnt, ev_tstamp now)
256{ 264{
257 while (timercnt && timers [0]->at <= ev_now) 265 while (timercnt && timers [0]->at <= now)
258 { 266 {
259 struct ev_timer *w = timers [0]; 267 struct ev_timer *w = timers [0];
260 268
261 fprintf (stderr, "0 %f, %d c%d\n", w->at, w->active, timercnt);//D
262 /* first reschedule timer */ 269 /* first reschedule or stop timer */
263 if (w->repeat) 270 if (w->repeat)
264 { 271 {
265 fprintf (stderr, "a %f now %f repeat %f, %f\n", w->at, ev_now, w->repeat, w->repeat *1e30);//D
266 if (w->is_abs) 272 if (w->is_abs)
267 w->at += ceil ((ev_now - w->at) / w->repeat + 1.) * w->repeat; 273 w->at += floor ((now - w->at) / w->repeat + 1.) * w->repeat;
268 else 274 else
269 w->at = ev_now + w->repeat; 275 w->at = now + w->repeat;
270 276
271 fprintf (stderr, "b %f\n", w->at);//D 277 assert (w->at > now);
272 278
273 downheap (0); 279 downheap (timers, timercnt, 0);
274 } 280 }
275 else 281 else
276 { 282 {
277 fprintf (stderr, "c %f, %d c%d\n", w->at, w->active, timercnt);//D
278 evtimer_stop (w); /* nonrepeating: stop timer */ 283 evtimer_stop (w); /* nonrepeating: stop timer */
284 --timercnt; /* maybe pass by reference instead? */
279 } 285 }
280 286
281 event ((struct ev_watcher *)w, EV_TIMEOUT); 287 event ((struct ev_watcher *)w, EV_TIMEOUT);
282 } 288 }
283} 289}
284 290
291static void
292time_update ()
293{
294 int i;
295 ev_now = ev_time ();
296
297 if (have_monotonic)
298 {
299 ev_tstamp odiff = diff;
300
301 /* detecting time jumps is much more difficult */
302 for (i = 2; --i; ) /* loop a few times, before making important decisions */
303 {
304 now = get_clock ();
305 diff = ev_now - now;
306
307 if (fabs (odiff - diff) < MIN_TIMEJUMP)
308 return; /* all is well */
309
310 ev_now = ev_time ();
311 }
312
313 /* time jump detected, reschedule atimers */
314 for (i = 0; i < atimercnt; ++i)
315 {
316 struct ev_timer *w = atimers [i];
317 w->at += ceil ((ev_now - w->at) / w->repeat + 1.) * w->repeat;
318 }
319 }
320 else
321 {
322 if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP)
323 /* time jump detected, adjust rtimers */
324 for (i = 0; i < rtimercnt; ++i)
325 rtimers [i]->at += ev_now - now;
326
327 now = ev_now;
328 }
329}
330
285int ev_loop_done; 331int ev_loop_done;
286 332
287int ev_loop (int flags) 333void ev_loop (int flags)
288{ 334{
289 double block; 335 double block;
290 ev_loop_done = flags & EVLOOP_ONESHOT; 336 ev_loop_done = flags & EVLOOP_ONESHOT;
291 337
292 do 338 do
293 { 339 {
294 /* update fd-related kernel structures */ 340 /* update fd-related kernel structures */
295 method_reify (); fdchangecnt = 0; 341 method_reify (); fdchangecnt = 0;
296 342
297 /* calculate blocking time */ 343 /* calculate blocking time */
298 ev_now = ev_time ();
299
300 if (flags & EVLOOP_NONBLOCK) 344 if (flags & EVLOOP_NONBLOCK)
301 block = 0.; 345 block = 0.;
302 else if (!timercnt)
303 block = MAX_BLOCKTIME;
304 else 346 else
305 { 347 {
348 block = MAX_BLOCKTIME;
349
350 if (rtimercnt)
351 {
306 block = timers [0]->at - ev_now + method_fudge; 352 ev_tstamp to = rtimers [0]->at - get_clock () + method_fudge;
353 if (block > to) block = to;
354 }
355
356 if (atimercnt)
357 {
358 ev_tstamp to = atimers [0]->at - ev_time () + method_fudge;
359 if (block > to) block = to;
360 }
361
307 if (block < 0.) block = 0.; 362 if (block < 0.) block = 0.;
308 else if (block > MAX_BLOCKTIME) block = MAX_BLOCKTIME;
309 } 363 }
310 364
311 fprintf (stderr, "block %f\n", block);//D
312 method_poll (block); 365 method_poll (block);
313 366
367 /* update ev_now, do magic */
368 time_update ();
369
314 /* put pending timers into pendign queue and reschedule them */ 370 /* put pending timers into pendign queue and reschedule them */
315 timer_reify (); 371 /* absolute timers first */
372 timers_reify (atimers, atimercnt, ev_now);
373 /* relative timers second */
374 timers_reify (rtimers, rtimercnt, now);
316 375
317 ev_now = ev_time ();
318 call_pending (); 376 call_pending ();
319 } 377 }
320 while (!ev_loop_done); 378 while (!ev_loop_done);
321} 379}
322 380
394evtimer_start (struct ev_timer *w) 452evtimer_start (struct ev_timer *w)
395{ 453{
396 if (ev_is_active (w)) 454 if (ev_is_active (w))
397 return; 455 return;
398 456
399 fprintf (stderr, "t1 %f a %d\n", w->at, w->is_abs);//D
400 if (w->is_abs) 457 if (w->is_abs)
401 { 458 {
402 /* this formula differs from the one in timer_reify becuse we do not round up */ 459 /* this formula differs from the one in timer_reify becuse we do not round up */
403 if (w->repeat) 460 if (w->repeat)
404 w->at += ceil ((ev_now - w->at) / w->repeat) * w->repeat; 461 w->at += ceil ((ev_now - w->at) / w->repeat) * w->repeat;
462
463 ev_start ((struct ev_watcher *)w, ++atimercnt);
464 array_needsize (atimers, atimermax, atimercnt, );
465 atimers [atimercnt - 1] = w;
466 upheap (atimers, atimercnt - 1);
405 } 467 }
406 else 468 else
469 {
407 w->at += ev_now; 470 w->at += now;
408 fprintf (stderr, "t2 %f a %d\n", w->at, w->is_abs);//D
409 471
410 ev_start ((struct ev_watcher *)w, ++timercnt); 472 ev_start ((struct ev_watcher *)w, ++rtimercnt);
411 array_needsize (timers, timermax, timercnt, ); 473 array_needsize (rtimers, rtimermax, rtimercnt, );
412 timers [timercnt - 1] = w; 474 rtimers [rtimercnt - 1] = w;
413 upheap (timercnt - 1); 475 upheap (rtimers, rtimercnt - 1);
476 }
477
414} 478}
415 479
416void 480void
417evtimer_stop (struct ev_timer *w) 481evtimer_stop (struct ev_timer *w)
418{ 482{
419 fprintf (stderr, "-topping %d, %d\n", w->active, timercnt);//D
420 if (!ev_is_active (w)) 483 if (!ev_is_active (w))
421 return; 484 return;
422 485
423 fprintf (stderr, "stopping %d, %d\n", w->active, timercnt);//D 486 if (w->is_abs)
487 {
424 if (w->active < timercnt) 488 if (w->active < atimercnt--)
425 { 489 {
426 timers [w->active - 1] = timers [--timercnt]; 490 atimers [w->active - 1] = atimers [atimercnt];
427 downheap (w->active - 1); 491 downheap (atimers, atimercnt, w->active - 1);
492 }
493 }
494 else
495 {
496 if (w->active < rtimercnt--)
497 {
498 rtimers [w->active - 1] = rtimers [rtimercnt];
499 downheap (rtimers, rtimercnt, w->active - 1);
500 }
428 } 501 }
429 502
430 ev_stop ((struct ev_watcher *)w); 503 ev_stop ((struct ev_watcher *)w);
431} 504}
432 505
461} 534}
462 535
463static void 536static void
464ocb (struct ev_timer *w, int revents) 537ocb (struct ev_timer *w, int revents)
465{ 538{
466 fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data); 539 //fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data);
540 evtimer_stop (w);
541 evtimer_start (w);
467} 542}
468 543
469int main (void) 544int main (void)
470{ 545{
471 struct ev_io sin; 546 struct ev_io sin;
474 549
475 evw_init (&sin, sin_cb, 55); 550 evw_init (&sin, sin_cb, 55);
476 evio_set (&sin, 0, EV_READ); 551 evio_set (&sin, 0, EV_READ);
477 evio_start (&sin); 552 evio_start (&sin);
478 553
479 struct ev_timer t[1000]; 554 struct ev_timer t[10000];
480 555
556#if 1
481 int i; 557 int i;
482 for (i = 0; i < 1000; ++i) 558 for (i = 0; i < 10000; ++i)
483 { 559 {
484 struct ev_timer *w = t + i; 560 struct ev_timer *w = t + i;
485 evw_init (w, ocb, i); 561 evw_init (w, ocb, i);
486 evtimer_set_rel (w, drand48 (), 0); 562 evtimer_set_abs (w, drand48 (), 0.99775533);
487 evtimer_start (w); 563 evtimer_start (w);
488 if (drand48 () < 0.5) 564 if (drand48 () < 0.5)
489 evtimer_stop (w); 565 evtimer_stop (w);
490 } 566 }
567#endif
568
569 struct ev_timer t1;
570 evw_init (&t1, ocb, 0);
571 evtimer_set_abs (&t1, 5, 10);
572 evtimer_start (&t1);
491 573
492 ev_loop (0); 574 ev_loop (0);
493 575
494 return 0; 576 return 0;
495} 577}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines