… | |
… | |
33 | |
33 | |
34 | #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ |
34 | #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ |
35 | #define MAX_BLOCKTIME 60. |
35 | #define MAX_BLOCKTIME 60. |
36 | |
36 | |
37 | #include "ev.h" |
37 | #include "ev.h" |
38 | |
|
|
39 | struct ev_watcher { |
|
|
40 | EV_WATCHER (ev_watcher); |
|
|
41 | }; |
|
|
42 | |
|
|
43 | struct ev_watcher_list { |
|
|
44 | EV_WATCHER_LIST (ev_watcher_list); |
|
|
45 | }; |
|
|
46 | |
|
|
47 | struct ev_watcher_time { |
|
|
48 | EV_WATCHER_TIME (ev_watcher_time); |
|
|
49 | }; |
|
|
50 | |
38 | |
51 | typedef struct ev_watcher *W; |
39 | typedef struct ev_watcher *W; |
52 | typedef struct ev_watcher_list *WL; |
40 | typedef struct ev_watcher_list *WL; |
53 | typedef struct ev_watcher_time *WT; |
41 | typedef struct ev_watcher_time *WT; |
54 | |
42 | |
… | |
… | |
95 | |
83 | |
96 | #define array_needsize(base,cur,cnt,init) \ |
84 | #define array_needsize(base,cur,cnt,init) \ |
97 | if ((cnt) > cur) \ |
85 | if ((cnt) > cur) \ |
98 | { \ |
86 | { \ |
99 | int newcnt = cur ? cur << 1 : 16; \ |
87 | int newcnt = cur ? cur << 1 : 16; \ |
100 | fprintf (stderr, "resize(" # base ") from %d to %d\n", cur, newcnt);\ |
|
|
101 | base = realloc (base, sizeof (*base) * (newcnt)); \ |
88 | base = realloc (base, sizeof (*base) * (newcnt)); \ |
102 | init (base + cur, newcnt - cur); \ |
89 | init (base + cur, newcnt - cur); \ |
103 | cur = newcnt; \ |
90 | cur = newcnt; \ |
104 | } |
91 | } |
105 | |
92 | |
… | |
… | |
455 | event ((W)w, EV_TIMEOUT); |
442 | event ((W)w, EV_TIMEOUT); |
456 | } |
443 | } |
457 | } |
444 | } |
458 | |
445 | |
459 | static void |
446 | static void |
460 | time_jump (ev_tstamp diff) |
447 | periodics_reschedule (ev_tstamp diff) |
461 | { |
448 | { |
462 | int i; |
449 | int i; |
463 | |
450 | |
464 | /* adjust periodics */ |
451 | /* adjust periodics after time jump */ |
465 | for (i = 0; i < periodiccnt; ++i) |
452 | for (i = 0; i < periodiccnt; ++i) |
466 | { |
453 | { |
467 | struct ev_periodic *w = periodics [i]; |
454 | struct ev_periodic *w = periodics [i]; |
468 | |
455 | |
469 | if (w->interval) |
456 | if (w->interval) |
… | |
… | |
477 | |
464 | |
478 | i = 0; /* restart loop, inefficient, but time jumps should be rare */ |
465 | i = 0; /* restart loop, inefficient, but time jumps should be rare */ |
479 | } |
466 | } |
480 | } |
467 | } |
481 | } |
468 | } |
482 | |
|
|
483 | /* adjust timers. this is easy, as the offset is the same for all */ |
|
|
484 | for (i = 0; i < timercnt; ++i) |
|
|
485 | timers [i]->at += diff; |
|
|
486 | } |
469 | } |
487 | |
470 | |
488 | static void |
471 | static void |
489 | time_update () |
472 | time_update () |
490 | { |
473 | { |
… | |
… | |
505 | return; /* all is well */ |
488 | return; /* all is well */ |
506 | |
489 | |
507 | ev_now = ev_time (); |
490 | ev_now = ev_time (); |
508 | } |
491 | } |
509 | |
492 | |
510 | time_jump (diff - odiff); |
493 | periodics_reschedule (diff - odiff); |
|
|
494 | /* no timer adjustment, as the monotonic clock doesn't jump */ |
511 | } |
495 | } |
512 | else |
496 | else |
513 | { |
497 | { |
514 | if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP) |
498 | if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP) |
515 | time_jump (ev_now - now); |
499 | { |
|
|
500 | periodics_reschedule (ev_now - now); |
|
|
501 | |
|
|
502 | /* adjust timers. this is easy, as the offset is the same for all */ |
|
|
503 | for (i = 0; i < timercnt; ++i) |
|
|
504 | timers [i]->at += diff; |
|
|
505 | } |
516 | |
506 | |
517 | now = ev_now; |
507 | now = ev_now; |
518 | } |
508 | } |
519 | } |
509 | } |
520 | |
510 | |
521 | int ev_loop_done; |
511 | int ev_loop_done; |
522 | |
512 | |
523 | void ev_loop (int flags) |
513 | void ev_loop (int flags) |
524 | { |
514 | { |
525 | double block; |
515 | double block; |
526 | ev_loop_done = flags & EVLOOP_ONESHOT; |
516 | ev_loop_done = flags & EVLOOP_ONESHOT ? 1 : 0; |
527 | |
517 | |
528 | if (checkcnt) |
518 | if (checkcnt) |
529 | { |
519 | { |
530 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
520 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
531 | call_pending (); |
521 | call_pending (); |
… | |
… | |
547 | { |
537 | { |
548 | block = MAX_BLOCKTIME; |
538 | block = MAX_BLOCKTIME; |
549 | |
539 | |
550 | if (timercnt) |
540 | if (timercnt) |
551 | { |
541 | { |
552 | ev_tstamp to = timers [0]->at - get_clock () + method_fudge; |
542 | ev_tstamp to = timers [0]->at - (have_monotonic ? get_clock () : ev_now) + method_fudge; |
553 | if (block > to) block = to; |
543 | if (block > to) block = to; |
554 | } |
544 | } |
555 | |
545 | |
556 | if (periodiccnt) |
546 | if (periodiccnt) |
557 | { |
547 | { |
… | |
… | |
579 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
569 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
580 | |
570 | |
581 | call_pending (); |
571 | call_pending (); |
582 | } |
572 | } |
583 | while (!ev_loop_done); |
573 | while (!ev_loop_done); |
|
|
574 | |
|
|
575 | if (ev_loop_done != 2) |
|
|
576 | ev_loop_done = 0; |
584 | } |
577 | } |
585 | |
578 | |
586 | /*****************************************************************************/ |
579 | /*****************************************************************************/ |
587 | |
580 | |
588 | static void |
581 | static void |
… | |
… | |
662 | { |
655 | { |
663 | if (ev_is_active (w)) |
656 | if (ev_is_active (w)) |
664 | return; |
657 | return; |
665 | |
658 | |
666 | w->at += now; |
659 | w->at += now; |
|
|
660 | |
|
|
661 | assert (("timer repeat value less than zero not allowed", w->repeat >= 0.)); |
667 | |
662 | |
668 | ev_start ((W)w, ++timercnt); |
663 | ev_start ((W)w, ++timercnt); |
669 | array_needsize (timers, timermax, timercnt, ); |
664 | array_needsize (timers, timermax, timercnt, ); |
670 | timers [timercnt - 1] = w; |
665 | timers [timercnt - 1] = w; |
671 | upheap ((WT *)timers, timercnt - 1); |
666 | upheap ((WT *)timers, timercnt - 1); |
… | |
… | |
681 | { |
676 | { |
682 | timers [w->active - 1] = timers [timercnt]; |
677 | timers [w->active - 1] = timers [timercnt]; |
683 | downheap ((WT *)timers, timercnt, w->active - 1); |
678 | downheap ((WT *)timers, timercnt, w->active - 1); |
684 | } |
679 | } |
685 | |
680 | |
|
|
681 | w->at = w->repeat; |
|
|
682 | |
686 | ev_stop ((W)w); |
683 | ev_stop ((W)w); |
|
|
684 | } |
|
|
685 | |
|
|
686 | void |
|
|
687 | evtimer_again (struct ev_timer *w) |
|
|
688 | { |
|
|
689 | if (ev_is_active (w)) |
|
|
690 | { |
|
|
691 | if (w->repeat) |
|
|
692 | { |
|
|
693 | w->at = now + w->repeat; |
|
|
694 | downheap ((WT *)timers, timercnt, w->active - 1); |
|
|
695 | } |
|
|
696 | else |
|
|
697 | evtimer_stop (w); |
|
|
698 | } |
|
|
699 | else if (w->repeat) |
|
|
700 | evtimer_start (w); |
687 | } |
701 | } |
688 | |
702 | |
689 | void |
703 | void |
690 | evperiodic_start (struct ev_periodic *w) |
704 | evperiodic_start (struct ev_periodic *w) |
691 | { |
705 | { |
692 | if (ev_is_active (w)) |
706 | if (ev_is_active (w)) |
693 | return; |
707 | return; |
|
|
708 | |
|
|
709 | assert (("periodic interval value less than zero not allowed", w->interval >= 0.)); |
694 | |
710 | |
695 | /* this formula differs from the one in periodic_reify because we do not always round up */ |
711 | /* this formula differs from the one in periodic_reify because we do not always round up */ |
696 | if (w->interval) |
712 | if (w->interval) |
697 | w->at += ceil ((ev_now - w->at) / w->interval) * w->interval; |
713 | w->at += ceil ((ev_now - w->at) / w->interval) * w->interval; |
698 | |
714 | |
… | |
… | |
782 | ev_stop ((W)w); |
798 | ev_stop ((W)w); |
783 | } |
799 | } |
784 | |
800 | |
785 | /*****************************************************************************/ |
801 | /*****************************************************************************/ |
786 | |
802 | |
787 | #if 1 |
803 | #if 0 |
788 | |
804 | |
789 | struct ev_io wio; |
805 | struct ev_io wio; |
790 | |
806 | |
791 | static void |
807 | static void |
792 | sin_cb (struct ev_io *w, int revents) |
808 | sin_cb (struct ev_io *w, int revents) |