… | |
… | |
9 | #include <assert.h> |
9 | #include <assert.h> |
10 | #include <errno.h> |
10 | #include <errno.h> |
11 | #include <sys/time.h> |
11 | #include <sys/time.h> |
12 | #include <time.h> |
12 | #include <time.h> |
13 | |
13 | |
|
|
14 | #define HAVE_EPOLL 1 |
|
|
15 | |
14 | #ifndef HAVE_MONOTONIC |
16 | #ifndef HAVE_MONOTONIC |
15 | # ifdef CLOCK_MONOTONIC |
17 | # ifdef CLOCK_MONOTONIC |
16 | # define HAVE_MONOTONIC 1 |
18 | # define HAVE_MONOTONIC 1 |
17 | # endif |
19 | # endif |
18 | #endif |
20 | #endif |
… | |
… | |
32 | #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) */ |
33 | #define MAX_BLOCKTIME 60. |
35 | #define MAX_BLOCKTIME 60. |
34 | |
36 | |
35 | #include "ev.h" |
37 | #include "ev.h" |
36 | |
38 | |
37 | struct ev_watcher { |
|
|
38 | EV_WATCHER (ev_watcher); |
|
|
39 | }; |
|
|
40 | |
|
|
41 | struct ev_watcher_list { |
|
|
42 | EV_WATCHER_LIST (ev_watcher_list); |
|
|
43 | }; |
|
|
44 | |
|
|
45 | typedef struct ev_watcher *W; |
39 | typedef struct ev_watcher *W; |
46 | typedef struct ev_watcher_list *WL; |
40 | typedef struct ev_watcher_list *WL; |
|
|
41 | typedef struct ev_watcher_time *WT; |
47 | |
42 | |
48 | static ev_tstamp now, diff; /* monotonic clock */ |
43 | static ev_tstamp now, diff; /* monotonic clock */ |
49 | ev_tstamp ev_now; |
44 | ev_tstamp ev_now; |
50 | int ev_method; |
45 | int ev_method; |
51 | |
46 | |
… | |
… | |
163 | event (events [i], type); |
158 | event (events [i], type); |
164 | } |
159 | } |
165 | |
160 | |
166 | /*****************************************************************************/ |
161 | /*****************************************************************************/ |
167 | |
162 | |
168 | static struct ev_timer **atimers; |
163 | static struct ev_timer **timers; |
169 | static int atimermax, atimercnt; |
164 | static int timermax, timercnt; |
170 | |
165 | |
171 | static struct ev_timer **rtimers; |
166 | static struct ev_periodic **periodics; |
172 | static int rtimermax, rtimercnt; |
167 | static int periodicmax, periodiccnt; |
173 | |
168 | |
174 | static void |
169 | static void |
175 | upheap (struct ev_timer **timers, int k) |
170 | upheap (WT *timers, int k) |
176 | { |
171 | { |
177 | struct ev_timer *w = timers [k]; |
172 | WT w = timers [k]; |
178 | |
173 | |
179 | while (k && timers [k >> 1]->at > w->at) |
174 | while (k && timers [k >> 1]->at > w->at) |
180 | { |
175 | { |
181 | timers [k] = timers [k >> 1]; |
176 | timers [k] = timers [k >> 1]; |
182 | timers [k]->active = k + 1; |
177 | timers [k]->active = k + 1; |
… | |
… | |
187 | timers [k]->active = k + 1; |
182 | timers [k]->active = k + 1; |
188 | |
183 | |
189 | } |
184 | } |
190 | |
185 | |
191 | static void |
186 | static void |
192 | downheap (struct ev_timer **timers, int N, int k) |
187 | downheap (WT *timers, int N, int k) |
193 | { |
188 | { |
194 | struct ev_timer *w = timers [k]; |
189 | WT w = timers [k]; |
195 | |
190 | |
196 | while (k < (N >> 1)) |
191 | while (k < (N >> 1)) |
197 | { |
192 | { |
198 | int j = k << 1; |
193 | int j = k << 1; |
199 | |
194 | |
… | |
… | |
325 | if (ev_method == EVMETHOD_NONE) select_init (flags); |
320 | if (ev_method == EVMETHOD_NONE) select_init (flags); |
326 | #endif |
321 | #endif |
327 | |
322 | |
328 | if (ev_method) |
323 | if (ev_method) |
329 | { |
324 | { |
330 | evw_init (&sigev, sigcb, 0); |
325 | evw_init (&sigev, sigcb); |
331 | siginit (); |
326 | siginit (); |
332 | } |
327 | } |
333 | |
328 | |
334 | return ev_method; |
329 | return ev_method; |
335 | } |
330 | } |
… | |
… | |
406 | |
401 | |
407 | pendingcnt = 0; |
402 | pendingcnt = 0; |
408 | } |
403 | } |
409 | |
404 | |
410 | static void |
405 | static void |
411 | timers_reify (struct ev_timer **timers, int timercnt, ev_tstamp now) |
406 | timers_reify () |
412 | { |
407 | { |
413 | while (timercnt && timers [0]->at <= now) |
408 | while (timercnt && timers [0]->at <= now) |
414 | { |
409 | { |
415 | struct ev_timer *w = timers [0]; |
410 | struct ev_timer *w = timers [0]; |
416 | |
411 | |
417 | /* first reschedule or stop timer */ |
412 | /* first reschedule or stop timer */ |
418 | if (w->repeat) |
413 | if (w->repeat) |
419 | { |
414 | { |
420 | if (w->is_abs) |
|
|
421 | w->at += floor ((now - w->at) / w->repeat + 1.) * w->repeat; |
|
|
422 | else |
|
|
423 | w->at = now + w->repeat; |
415 | w->at = now + w->repeat; |
424 | |
416 | assert (("timer timeout in the past, negative repeat?", w->at > now)); |
425 | assert (w->at > now); |
|
|
426 | |
|
|
427 | downheap (timers, timercnt, 0); |
417 | downheap ((WT *)timers, timercnt, 0); |
428 | } |
418 | } |
429 | else |
419 | else |
430 | { |
|
|
431 | evtimer_stop (w); /* nonrepeating: stop timer */ |
420 | evtimer_stop (w); /* nonrepeating: stop timer */ |
432 | --timercnt; /* maybe pass by reference instead? */ |
|
|
433 | } |
|
|
434 | |
421 | |
435 | event ((W)w, EV_TIMEOUT); |
422 | event ((W)w, EV_TIMEOUT); |
436 | } |
423 | } |
437 | } |
424 | } |
438 | |
425 | |
439 | static void |
426 | static void |
|
|
427 | periodics_reify () |
|
|
428 | { |
|
|
429 | while (periodiccnt && periodics [0]->at <= ev_now) |
|
|
430 | { |
|
|
431 | struct ev_periodic *w = periodics [0]; |
|
|
432 | |
|
|
433 | /* first reschedule or stop timer */ |
|
|
434 | if (w->interval) |
|
|
435 | { |
|
|
436 | w->at += floor ((ev_now - w->at) / w->interval + 1.) * w->interval; |
|
|
437 | assert (("periodic timeout in the past, negative interval?", w->at > ev_now)); |
|
|
438 | downheap ((WT *)periodics, periodiccnt, 0); |
|
|
439 | } |
|
|
440 | else |
|
|
441 | evperiodic_stop (w); /* nonrepeating: stop timer */ |
|
|
442 | |
|
|
443 | event ((W)w, EV_TIMEOUT); |
|
|
444 | } |
|
|
445 | } |
|
|
446 | |
|
|
447 | static void |
|
|
448 | periodics_reschedule (ev_tstamp diff) |
|
|
449 | { |
|
|
450 | int i; |
|
|
451 | |
|
|
452 | /* adjust periodics after time jump */ |
|
|
453 | for (i = 0; i < periodiccnt; ++i) |
|
|
454 | { |
|
|
455 | struct ev_periodic *w = periodics [i]; |
|
|
456 | |
|
|
457 | if (w->interval) |
|
|
458 | { |
|
|
459 | ev_tstamp diff = ceil ((ev_now - w->at) / w->interval) * w->interval; |
|
|
460 | |
|
|
461 | if (fabs (diff) >= 1e-4) |
|
|
462 | { |
|
|
463 | evperiodic_stop (w); |
|
|
464 | evperiodic_start (w); |
|
|
465 | |
|
|
466 | i = 0; /* restart loop, inefficient, but time jumps should be rare */ |
|
|
467 | } |
|
|
468 | } |
|
|
469 | } |
|
|
470 | } |
|
|
471 | |
|
|
472 | static void |
440 | time_update () |
473 | time_update () |
441 | { |
474 | { |
442 | int i; |
475 | int i; |
|
|
476 | |
443 | ev_now = ev_time (); |
477 | ev_now = ev_time (); |
444 | |
478 | |
445 | if (have_monotonic) |
479 | if (have_monotonic) |
446 | { |
480 | { |
447 | ev_tstamp odiff = diff; |
481 | ev_tstamp odiff = diff; |
448 | |
482 | |
449 | /* detecting time jumps is much more difficult */ |
|
|
450 | for (i = 2; --i; ) /* loop a few times, before making important decisions */ |
483 | for (i = 4; --i; ) /* loop a few times, before making important decisions */ |
451 | { |
484 | { |
452 | now = get_clock (); |
485 | now = get_clock (); |
453 | diff = ev_now - now; |
486 | diff = ev_now - now; |
454 | |
487 | |
455 | if (fabs (odiff - diff) < MIN_TIMEJUMP) |
488 | if (fabs (odiff - diff) < MIN_TIMEJUMP) |
456 | return; /* all is well */ |
489 | return; /* all is well */ |
457 | |
490 | |
458 | ev_now = ev_time (); |
491 | ev_now = ev_time (); |
459 | } |
492 | } |
460 | |
493 | |
461 | /* time jump detected, reschedule atimers */ |
494 | periodics_reschedule (diff - odiff); |
462 | for (i = 0; i < atimercnt; ++i) |
495 | /* no timer adjustment, as the monotonic clock doesn't jump */ |
463 | { |
|
|
464 | struct ev_timer *w = atimers [i]; |
|
|
465 | w->at += ceil ((ev_now - w->at) / w->repeat + 1.) * w->repeat; |
|
|
466 | } |
|
|
467 | } |
496 | } |
468 | else |
497 | else |
469 | { |
498 | { |
470 | if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP) |
499 | if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP) |
471 | /* time jump detected, adjust rtimers */ |
500 | { |
|
|
501 | periodics_reschedule (ev_now - now); |
|
|
502 | |
|
|
503 | /* adjust timers. this is easy, as the offset is the same for all */ |
472 | for (i = 0; i < rtimercnt; ++i) |
504 | for (i = 0; i < timercnt; ++i) |
473 | rtimers [i]->at += ev_now - now; |
505 | timers [i]->at += diff; |
|
|
506 | } |
474 | |
507 | |
475 | now = ev_now; |
508 | now = ev_now; |
476 | } |
509 | } |
477 | } |
510 | } |
478 | |
511 | |
479 | int ev_loop_done; |
512 | int ev_loop_done; |
480 | |
513 | |
481 | void ev_loop (int flags) |
514 | void ev_loop (int flags) |
482 | { |
515 | { |
483 | double block; |
516 | double block; |
484 | ev_loop_done = flags & EVLOOP_ONESHOT; |
517 | ev_loop_done = flags & EVLOOP_ONESHOT ? 1 : 0; |
485 | |
518 | |
486 | if (checkcnt) |
519 | if (checkcnt) |
487 | { |
520 | { |
488 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
521 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
489 | call_pending (); |
522 | call_pending (); |
… | |
… | |
493 | { |
526 | { |
494 | /* update fd-related kernel structures */ |
527 | /* update fd-related kernel structures */ |
495 | fd_reify (); |
528 | fd_reify (); |
496 | |
529 | |
497 | /* calculate blocking time */ |
530 | /* calculate blocking time */ |
|
|
531 | |
|
|
532 | /* we only need this for !monotonic clock, but as we always have timers, we just calculate it every time */ |
|
|
533 | ev_now = ev_time (); |
|
|
534 | |
498 | if (flags & EVLOOP_NONBLOCK || idlecnt) |
535 | if (flags & EVLOOP_NONBLOCK || idlecnt) |
499 | block = 0.; |
536 | block = 0.; |
500 | else |
537 | else |
501 | { |
538 | { |
502 | block = MAX_BLOCKTIME; |
539 | block = MAX_BLOCKTIME; |
503 | |
540 | |
504 | if (rtimercnt) |
541 | if (timercnt) |
505 | { |
542 | { |
506 | ev_tstamp to = rtimers [0]->at - get_clock () + method_fudge; |
543 | ev_tstamp to = timers [0]->at - (have_monotonic ? get_clock () : ev_now) + method_fudge; |
507 | if (block > to) block = to; |
544 | if (block > to) block = to; |
508 | } |
545 | } |
509 | |
546 | |
510 | if (atimercnt) |
547 | if (periodiccnt) |
511 | { |
548 | { |
512 | ev_tstamp to = atimers [0]->at - ev_time () + method_fudge; |
549 | ev_tstamp to = periodics [0]->at - ev_now + method_fudge; |
513 | if (block > to) block = to; |
550 | if (block > to) block = to; |
514 | } |
551 | } |
515 | |
552 | |
516 | if (block < 0.) block = 0.; |
553 | if (block < 0.) block = 0.; |
517 | } |
554 | } |
… | |
… | |
520 | |
557 | |
521 | /* update ev_now, do magic */ |
558 | /* update ev_now, do magic */ |
522 | time_update (); |
559 | time_update (); |
523 | |
560 | |
524 | /* queue pending timers and reschedule them */ |
561 | /* queue pending timers and reschedule them */ |
525 | /* absolute timers first */ |
562 | periodics_reify (); /* absolute timers first */ |
526 | timers_reify (atimers, atimercnt, ev_now); |
|
|
527 | /* relative timers second */ |
563 | timers_reify (); /* relative timers second */ |
528 | timers_reify (rtimers, rtimercnt, now); |
|
|
529 | |
564 | |
530 | /* queue idle watchers unless io or timers are pending */ |
565 | /* queue idle watchers unless io or timers are pending */ |
531 | if (!pendingcnt) |
566 | if (!pendingcnt) |
532 | queue_events ((W *)idles, idlecnt, EV_IDLE); |
567 | queue_events ((W *)idles, idlecnt, EV_IDLE); |
533 | |
568 | |
… | |
… | |
535 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
570 | queue_events ((W *)checks, checkcnt, EV_CHECK); |
536 | |
571 | |
537 | call_pending (); |
572 | call_pending (); |
538 | } |
573 | } |
539 | while (!ev_loop_done); |
574 | while (!ev_loop_done); |
|
|
575 | |
|
|
576 | if (ev_loop_done != 2) |
|
|
577 | ev_loop_done = 0; |
540 | } |
578 | } |
541 | |
579 | |
542 | /*****************************************************************************/ |
580 | /*****************************************************************************/ |
543 | |
581 | |
544 | static void |
582 | static void |
… | |
… | |
610 | ++fdchangecnt; |
648 | ++fdchangecnt; |
611 | array_needsize (fdchanges, fdchangemax, fdchangecnt, ); |
649 | array_needsize (fdchanges, fdchangemax, fdchangecnt, ); |
612 | fdchanges [fdchangecnt - 1] = w->fd; |
650 | fdchanges [fdchangecnt - 1] = w->fd; |
613 | } |
651 | } |
614 | |
652 | |
|
|
653 | |
615 | void |
654 | void |
616 | evtimer_start (struct ev_timer *w) |
655 | evtimer_start (struct ev_timer *w) |
617 | { |
656 | { |
618 | if (ev_is_active (w)) |
657 | if (ev_is_active (w)) |
619 | return; |
658 | return; |
620 | |
659 | |
621 | if (w->is_abs) |
660 | w->at += now; |
622 | { |
|
|
623 | /* this formula differs from the one in timer_reify becuse we do not round up */ |
|
|
624 | if (w->repeat) |
|
|
625 | w->at += ceil ((ev_now - w->at) / w->repeat) * w->repeat; |
|
|
626 | |
661 | |
|
|
662 | assert (("timer repeat value less than zero not allowed", w->repeat >= 0.)); |
|
|
663 | |
627 | ev_start ((W)w, ++atimercnt); |
664 | ev_start ((W)w, ++timercnt); |
628 | array_needsize (atimers, atimermax, atimercnt, ); |
665 | array_needsize (timers, timermax, timercnt, ); |
629 | atimers [atimercnt - 1] = w; |
666 | timers [timercnt - 1] = w; |
630 | upheap (atimers, atimercnt - 1); |
667 | upheap ((WT *)timers, timercnt - 1); |
631 | } |
|
|
632 | else |
|
|
633 | { |
|
|
634 | w->at += now; |
|
|
635 | |
|
|
636 | ev_start ((W)w, ++rtimercnt); |
|
|
637 | array_needsize (rtimers, rtimermax, rtimercnt, ); |
|
|
638 | rtimers [rtimercnt - 1] = w; |
|
|
639 | upheap (rtimers, rtimercnt - 1); |
|
|
640 | } |
|
|
641 | |
|
|
642 | } |
668 | } |
643 | |
669 | |
644 | void |
670 | void |
645 | evtimer_stop (struct ev_timer *w) |
671 | evtimer_stop (struct ev_timer *w) |
646 | { |
672 | { |
647 | if (!ev_is_active (w)) |
673 | if (!ev_is_active (w)) |
648 | return; |
674 | return; |
649 | |
675 | |
650 | if (w->is_abs) |
|
|
651 | { |
|
|
652 | if (w->active < atimercnt--) |
676 | if (w->active < timercnt--) |
653 | { |
677 | { |
654 | atimers [w->active - 1] = atimers [atimercnt]; |
678 | timers [w->active - 1] = timers [timercnt]; |
|
|
679 | downheap ((WT *)timers, timercnt, w->active - 1); |
|
|
680 | } |
|
|
681 | |
|
|
682 | w->at = w->repeat; |
|
|
683 | |
|
|
684 | ev_stop ((W)w); |
|
|
685 | } |
|
|
686 | |
|
|
687 | void |
|
|
688 | evtimer_again (struct ev_timer *w) |
|
|
689 | { |
|
|
690 | if (ev_is_active (w)) |
|
|
691 | { |
|
|
692 | if (w->repeat) |
|
|
693 | { |
|
|
694 | w->at = now + w->repeat; |
655 | downheap (atimers, atimercnt, w->active - 1); |
695 | downheap ((WT *)timers, timercnt, w->active - 1); |
656 | } |
|
|
657 | } |
|
|
658 | else |
|
|
659 | { |
|
|
660 | if (w->active < rtimercnt--) |
|
|
661 | { |
696 | } |
662 | rtimers [w->active - 1] = rtimers [rtimercnt]; |
697 | else |
663 | downheap (rtimers, rtimercnt, w->active - 1); |
698 | evtimer_stop (w); |
664 | } |
699 | } |
|
|
700 | else if (w->repeat) |
|
|
701 | evtimer_start (w); |
|
|
702 | } |
|
|
703 | |
|
|
704 | void |
|
|
705 | evperiodic_start (struct ev_periodic *w) |
|
|
706 | { |
|
|
707 | if (ev_is_active (w)) |
|
|
708 | return; |
|
|
709 | |
|
|
710 | assert (("periodic interval value less than zero not allowed", w->interval >= 0.)); |
|
|
711 | |
|
|
712 | /* this formula differs from the one in periodic_reify because we do not always round up */ |
|
|
713 | if (w->interval) |
|
|
714 | w->at += ceil ((ev_now - w->at) / w->interval) * w->interval; |
|
|
715 | |
|
|
716 | ev_start ((W)w, ++periodiccnt); |
|
|
717 | array_needsize (periodics, periodicmax, periodiccnt, ); |
|
|
718 | periodics [periodiccnt - 1] = w; |
|
|
719 | upheap ((WT *)periodics, periodiccnt - 1); |
|
|
720 | } |
|
|
721 | |
|
|
722 | void |
|
|
723 | evperiodic_stop (struct ev_periodic *w) |
|
|
724 | { |
|
|
725 | if (!ev_is_active (w)) |
|
|
726 | return; |
|
|
727 | |
|
|
728 | if (w->active < periodiccnt--) |
|
|
729 | { |
|
|
730 | periodics [w->active - 1] = periodics [periodiccnt]; |
|
|
731 | downheap ((WT *)periodics, periodiccnt, w->active - 1); |
665 | } |
732 | } |
666 | |
733 | |
667 | ev_stop ((W)w); |
734 | ev_stop ((W)w); |
668 | } |
735 | } |
669 | |
736 | |
… | |
… | |
734 | |
801 | |
735 | /*****************************************************************************/ |
802 | /*****************************************************************************/ |
736 | |
803 | |
737 | #if 0 |
804 | #if 0 |
738 | |
805 | |
|
|
806 | struct ev_io wio; |
|
|
807 | |
739 | static void |
808 | static void |
740 | sin_cb (struct ev_io *w, int revents) |
809 | sin_cb (struct ev_io *w, int revents) |
741 | { |
810 | { |
742 | fprintf (stderr, "sin %d, revents %d\n", w->fd, revents); |
811 | fprintf (stderr, "sin %d, revents %d\n", w->fd, revents); |
743 | } |
812 | } |
… | |
… | |
752 | |
821 | |
753 | static void |
822 | static void |
754 | scb (struct ev_signal *w, int revents) |
823 | scb (struct ev_signal *w, int revents) |
755 | { |
824 | { |
756 | fprintf (stderr, "signal %x,%d\n", revents, w->signum); |
825 | fprintf (stderr, "signal %x,%d\n", revents, w->signum); |
|
|
826 | evio_stop (&wio); |
|
|
827 | evio_start (&wio); |
757 | } |
828 | } |
758 | |
829 | |
759 | static void |
830 | static void |
760 | gcb (struct ev_signal *w, int revents) |
831 | gcb (struct ev_signal *w, int revents) |
761 | { |
832 | { |
762 | fprintf (stderr, "generic %x\n", revents); |
833 | fprintf (stderr, "generic %x\n", revents); |
|
|
834 | |
763 | } |
835 | } |
764 | |
836 | |
765 | int main (void) |
837 | int main (void) |
766 | { |
838 | { |
767 | struct ev_io sin; |
|
|
768 | |
|
|
769 | ev_init (0); |
839 | ev_init (0); |
770 | |
840 | |
771 | evw_init (&sin, sin_cb, 55); |
|
|
772 | evio_set (&sin, 0, EV_READ); |
841 | evio_init (&wio, sin_cb, 0, EV_READ); |
773 | evio_start (&sin); |
842 | evio_start (&wio); |
774 | |
843 | |
775 | struct ev_timer t[10000]; |
844 | struct ev_timer t[10000]; |
776 | |
845 | |
777 | #if 0 |
846 | #if 0 |
778 | int i; |
847 | int i; |
779 | for (i = 0; i < 10000; ++i) |
848 | for (i = 0; i < 10000; ++i) |
780 | { |
849 | { |
781 | struct ev_timer *w = t + i; |
850 | struct ev_timer *w = t + i; |
782 | evw_init (w, ocb, i); |
851 | evw_init (w, ocb, i); |
783 | evtimer_set_abs (w, drand48 (), 0.99775533); |
852 | evtimer_init_abs (w, ocb, drand48 (), 0.99775533); |
784 | evtimer_start (w); |
853 | evtimer_start (w); |
785 | if (drand48 () < 0.5) |
854 | if (drand48 () < 0.5) |
786 | evtimer_stop (w); |
855 | evtimer_stop (w); |
787 | } |
856 | } |
788 | #endif |
857 | #endif |
789 | |
858 | |
790 | struct ev_timer t1; |
859 | struct ev_timer t1; |
791 | evw_init (&t1, ocb, 0); |
860 | evtimer_init (&t1, ocb, 5, 10); |
792 | evtimer_set_abs (&t1, 5, 10); |
|
|
793 | evtimer_start (&t1); |
861 | evtimer_start (&t1); |
794 | |
862 | |
795 | struct ev_signal sig; |
863 | struct ev_signal sig; |
796 | evw_init (&sig, scb, 65535); |
|
|
797 | evsignal_set (&sig, SIGQUIT); |
864 | evsignal_init (&sig, scb, SIGQUIT); |
798 | evsignal_start (&sig); |
865 | evsignal_start (&sig); |
799 | |
866 | |
800 | struct ev_check cw; |
867 | struct ev_check cw; |
801 | evw_init (&cw, gcb, 0); |
868 | evcheck_init (&cw, gcb); |
802 | evcheck_start (&cw); |
869 | evcheck_start (&cw); |
803 | |
870 | |
804 | struct ev_idle iw; |
871 | struct ev_idle iw; |
805 | evw_init (&iw, gcb, 0); |
872 | evidle_init (&iw, gcb); |
806 | evidle_start (&iw); |
873 | evidle_start (&iw); |
807 | |
874 | |
808 | ev_loop (0); |
875 | ev_loop (0); |
809 | |
876 | |
810 | return 0; |
877 | return 0; |