ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.c
Revision: 1.23
Committed: Wed Oct 31 20:10:17 2007 UTC (16 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.22: +29 -20 lines
Log Message:
better resize

File Contents

# User Rev Content
1 root 1.17 /*
2     * Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
3     * All rights reserved.
4     *
5     * Redistribution and use in source and binary forms, with or without
6     * modification, are permitted provided that the following conditions are
7     * met:
8     *
9     * * Redistributions of source code must retain the above copyright
10     * notice, this list of conditions and the following disclaimer.
11     *
12     * * Redistributions in binary form must reproduce the above
13     * copyright notice, this list of conditions and the following
14     * disclaimer in the documentation and/or other materials provided
15     * with the distribution.
16     *
17     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28     */
29    
30 root 1.1 #include <math.h>
31     #include <stdlib.h>
32 root 1.7 #include <unistd.h>
33     #include <fcntl.h>
34     #include <signal.h>
35 root 1.16 #include <stddef.h>
36 root 1.1
37     #include <stdio.h>
38    
39 root 1.4 #include <assert.h>
40 root 1.1 #include <errno.h>
41 root 1.22 #include <sys/types.h>
42     #include <sys/wait.h>
43 root 1.1 #include <sys/time.h>
44     #include <time.h>
45    
46 root 1.10 #ifndef HAVE_MONOTONIC
47     # ifdef CLOCK_MONOTONIC
48     # define HAVE_MONOTONIC 1
49     # endif
50 root 1.1 #endif
51    
52 root 1.10 #ifndef HAVE_SELECT
53     # define HAVE_SELECT 1
54     #endif
55    
56     #ifndef HAVE_EPOLL
57     # define HAVE_EPOLL 0
58     #endif
59    
60     #ifndef HAVE_REALTIME
61     # define HAVE_REALTIME 1 /* posix requirement, but might be slower */
62     #endif
63 root 1.1
64 root 1.4 #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
65 root 1.1 #define MAX_BLOCKTIME 60.
66 root 1.22 #define PID_HASHSIZE 16 /* size of pid hahs table, must be power of two */
67 root 1.1
68     #include "ev.h"
69    
70 root 1.10 typedef struct ev_watcher *W;
71     typedef struct ev_watcher_list *WL;
72 root 1.12 typedef struct ev_watcher_time *WT;
73 root 1.10
74 root 1.4 static ev_tstamp now, diff; /* monotonic clock */
75 root 1.1 ev_tstamp ev_now;
76     int ev_method;
77    
78     static int have_monotonic; /* runtime */
79    
80     static ev_tstamp method_fudge; /* stupid epoll-returns-early bug */
81 root 1.5 static void (*method_modify)(int fd, int oev, int nev);
82 root 1.1 static void (*method_poll)(ev_tstamp timeout);
83    
84 root 1.8 /*****************************************************************************/
85    
86 root 1.1 ev_tstamp
87     ev_time (void)
88     {
89     #if HAVE_REALTIME
90     struct timespec ts;
91     clock_gettime (CLOCK_REALTIME, &ts);
92     return ts.tv_sec + ts.tv_nsec * 1e-9;
93     #else
94     struct timeval tv;
95     gettimeofday (&tv, 0);
96     return tv.tv_sec + tv.tv_usec * 1e-6;
97     #endif
98     }
99    
100     static ev_tstamp
101     get_clock (void)
102     {
103     #if HAVE_MONOTONIC
104     if (have_monotonic)
105     {
106     struct timespec ts;
107     clock_gettime (CLOCK_MONOTONIC, &ts);
108     return ts.tv_sec + ts.tv_nsec * 1e-9;
109     }
110     #endif
111    
112     return ev_time ();
113     }
114    
115     #define array_needsize(base,cur,cnt,init) \
116     if ((cnt) > cur) \
117     { \
118 root 1.23 int newcnt = cur; \
119     do \
120     { \
121     newcnt = (newcnt << 1) | 4 & ~3; \
122     } \
123     while ((cnt) > newcnt); \
124     \
125 root 1.1 base = realloc (base, sizeof (*base) * (newcnt)); \
126     init (base + cur, newcnt - cur); \
127     cur = newcnt; \
128     }
129    
130 root 1.8 /*****************************************************************************/
131    
132 root 1.1 typedef struct
133     {
134     struct ev_io *head;
135     unsigned char wev, rev; /* want, received event set */
136     } ANFD;
137    
138     static ANFD *anfds;
139     static int anfdmax;
140    
141     static int *fdchanges;
142     static int fdchangemax, fdchangecnt;
143    
144     static void
145     anfds_init (ANFD *base, int count)
146     {
147     while (count--)
148     {
149     base->head = 0;
150     base->wev = base->rev = EV_NONE;
151     ++base;
152     }
153     }
154    
155     typedef struct
156     {
157 root 1.10 W w;
158 root 1.1 int events;
159     } ANPENDING;
160    
161     static ANPENDING *pendings;
162     static int pendingmax, pendingcnt;
163    
164     static void
165 root 1.10 event (W w, int events)
166 root 1.1 {
167 root 1.16 if (w->active)
168     {
169     w->pending = ++pendingcnt;
170     array_needsize (pendings, pendingmax, pendingcnt, );
171     pendings [pendingcnt - 1].w = w;
172     pendings [pendingcnt - 1].events = events;
173     }
174 root 1.1 }
175    
176     static void
177     fd_event (int fd, int events)
178     {
179     ANFD *anfd = anfds + fd;
180     struct ev_io *w;
181    
182     for (w = anfd->head; w; w = w->next)
183     {
184     int ev = w->events & events;
185    
186     if (ev)
187 root 1.10 event ((W)w, ev);
188 root 1.1 }
189     }
190    
191 root 1.9 static void
192 root 1.10 queue_events (W *events, int eventcnt, int type)
193 root 1.9 {
194     int i;
195    
196     for (i = 0; i < eventcnt; ++i)
197     event (events [i], type);
198     }
199    
200 root 1.19 /* called on EBADF to verify fds */
201     static void
202     fd_recheck ()
203     {
204     int fd;
205    
206     for (fd = 0; fd < anfdmax; ++fd)
207     if (anfds [fd].wev)
208     if (fcntl (fd, F_GETFD) == -1 && errno == EBADF)
209     while (anfds [fd].head)
210     evio_stop (anfds [fd].head);
211     }
212    
213 root 1.8 /*****************************************************************************/
214    
215 root 1.12 static struct ev_timer **timers;
216     static int timermax, timercnt;
217 root 1.4
218 root 1.12 static struct ev_periodic **periodics;
219     static int periodicmax, periodiccnt;
220 root 1.1
221     static void
222 root 1.12 upheap (WT *timers, int k)
223 root 1.1 {
224 root 1.12 WT w = timers [k];
225 root 1.1
226     while (k && timers [k >> 1]->at > w->at)
227     {
228     timers [k] = timers [k >> 1];
229     timers [k]->active = k + 1;
230     k >>= 1;
231     }
232    
233     timers [k] = w;
234     timers [k]->active = k + 1;
235    
236     }
237    
238     static void
239 root 1.12 downheap (WT *timers, int N, int k)
240 root 1.1 {
241 root 1.12 WT w = timers [k];
242 root 1.1
243 root 1.4 while (k < (N >> 1))
244 root 1.1 {
245     int j = k << 1;
246    
247 root 1.4 if (j + 1 < N && timers [j]->at > timers [j + 1]->at)
248 root 1.1 ++j;
249    
250     if (w->at <= timers [j]->at)
251     break;
252    
253     timers [k] = timers [j];
254 root 1.2 timers [k]->active = k + 1;
255 root 1.1 k = j;
256     }
257    
258     timers [k] = w;
259     timers [k]->active = k + 1;
260     }
261    
262 root 1.8 /*****************************************************************************/
263    
264 root 1.7 typedef struct
265     {
266     struct ev_signal *head;
267     sig_atomic_t gotsig;
268     } ANSIG;
269    
270     static ANSIG *signals;
271 root 1.4 static int signalmax;
272 root 1.1
273 root 1.7 static int sigpipe [2];
274     static sig_atomic_t gotsig;
275     static struct ev_io sigev;
276    
277 root 1.1 static void
278 root 1.7 signals_init (ANSIG *base, int count)
279 root 1.1 {
280     while (count--)
281 root 1.7 {
282     base->head = 0;
283     base->gotsig = 0;
284     ++base;
285     }
286     }
287    
288     static void
289     sighandler (int signum)
290     {
291     signals [signum - 1].gotsig = 1;
292    
293     if (!gotsig)
294     {
295     gotsig = 1;
296     write (sigpipe [1], &gotsig, 1);
297     }
298     }
299    
300     static void
301     sigcb (struct ev_io *iow, int revents)
302     {
303     struct ev_signal *w;
304     int sig;
305    
306     gotsig = 0;
307     read (sigpipe [0], &revents, 1);
308    
309     for (sig = signalmax; sig--; )
310     if (signals [sig].gotsig)
311     {
312     signals [sig].gotsig = 0;
313    
314     for (w = signals [sig].head; w; w = w->next)
315 root 1.10 event ((W)w, EV_SIGNAL);
316 root 1.7 }
317     }
318    
319     static void
320     siginit (void)
321     {
322     fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC);
323     fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC);
324    
325     /* rather than sort out wether we really need nb, set it */
326     fcntl (sigpipe [0], F_SETFL, O_NONBLOCK);
327     fcntl (sigpipe [1], F_SETFL, O_NONBLOCK);
328    
329     evio_set (&sigev, sigpipe [0], EV_READ);
330     evio_start (&sigev);
331 root 1.1 }
332    
333 root 1.8 /*****************************************************************************/
334    
335 root 1.9 static struct ev_idle **idles;
336     static int idlemax, idlecnt;
337    
338 root 1.20 static struct ev_prepare **prepares;
339     static int preparemax, preparecnt;
340    
341 root 1.9 static struct ev_check **checks;
342     static int checkmax, checkcnt;
343    
344     /*****************************************************************************/
345    
346 root 1.22 static struct ev_child *childs [PID_HASHSIZE];
347     static struct ev_signal childev;
348    
349     #ifndef WCONTINUED
350     # define WCONTINUED 0
351     #endif
352    
353     static void
354     childcb (struct ev_signal *sw, int revents)
355     {
356     struct ev_child *w;
357     int pid, status;
358    
359     while ((pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)) != -1)
360     for (w = childs [pid & (PID_HASHSIZE - 1)]; w; w = w->next)
361     if (w->pid == pid || w->pid == -1)
362     {
363     w->status = status;
364     event ((W)w, EV_CHILD);
365     }
366     }
367    
368     /*****************************************************************************/
369    
370 root 1.1 #if HAVE_EPOLL
371     # include "ev_epoll.c"
372     #endif
373     #if HAVE_SELECT
374     # include "ev_select.c"
375     #endif
376    
377     int ev_init (int flags)
378     {
379 root 1.23 if (!ev_method)
380     {
381 root 1.1 #if HAVE_MONOTONIC
382 root 1.23 {
383     struct timespec ts;
384     if (!clock_gettime (CLOCK_MONOTONIC, &ts))
385     have_monotonic = 1;
386     }
387 root 1.1 #endif
388    
389 root 1.23 ev_now = ev_time ();
390     now = get_clock ();
391     diff = ev_now - now;
392 root 1.1
393 root 1.23 if (pipe (sigpipe))
394     return 0;
395 root 1.7
396 root 1.23 ev_method = EVMETHOD_NONE;
397 root 1.1 #if HAVE_EPOLL
398 root 1.23 if (ev_method == EVMETHOD_NONE) epoll_init (flags);
399 root 1.1 #endif
400     #if HAVE_SELECT
401 root 1.23 if (ev_method == EVMETHOD_NONE) select_init (flags);
402 root 1.1 #endif
403    
404 root 1.23 if (ev_method)
405     {
406     evw_init (&sigev, sigcb);
407     siginit ();
408 root 1.22
409 root 1.23 evsignal_init (&childev, childcb, SIGCHLD);
410     evsignal_start (&childev);
411     }
412 root 1.7 }
413    
414 root 1.1 return ev_method;
415     }
416    
417 root 1.8 /*****************************************************************************/
418    
419 root 1.1 void ev_prefork (void)
420     {
421 root 1.11 /* nop */
422 root 1.1 }
423    
424     void ev_postfork_parent (void)
425     {
426 root 1.11 /* nop */
427 root 1.1 }
428    
429     void ev_postfork_child (void)
430     {
431     #if HAVE_EPOLL
432 root 1.5 if (ev_method == EVMETHOD_EPOLL)
433     epoll_postfork_child ();
434 root 1.1 #endif
435 root 1.7
436     evio_stop (&sigev);
437     close (sigpipe [0]);
438     close (sigpipe [1]);
439     pipe (sigpipe);
440     siginit ();
441 root 1.1 }
442    
443 root 1.8 /*****************************************************************************/
444    
445 root 1.1 static void
446 root 1.5 fd_reify (void)
447     {
448     int i;
449    
450     for (i = 0; i < fdchangecnt; ++i)
451     {
452     int fd = fdchanges [i];
453     ANFD *anfd = anfds + fd;
454     struct ev_io *w;
455    
456     int wev = 0;
457    
458     for (w = anfd->head; w; w = w->next)
459     wev |= w->events;
460    
461     if (anfd->wev != wev)
462     {
463     method_modify (fd, anfd->wev, wev);
464     anfd->wev = wev;
465     }
466     }
467    
468     fdchangecnt = 0;
469     }
470    
471     static void
472 root 1.1 call_pending ()
473     {
474 root 1.18 while (pendingcnt)
475 root 1.1 {
476 root 1.18 ANPENDING *p = pendings + --pendingcnt;
477 root 1.1
478     if (p->w)
479     {
480     p->w->pending = 0;
481     p->w->cb (p->w, p->events);
482     }
483     }
484     }
485    
486     static void
487 root 1.12 timers_reify ()
488 root 1.1 {
489 root 1.4 while (timercnt && timers [0]->at <= now)
490 root 1.1 {
491     struct ev_timer *w = timers [0];
492    
493 root 1.16 event ((W)w, EV_TIMEOUT);
494    
495 root 1.4 /* first reschedule or stop timer */
496 root 1.1 if (w->repeat)
497     {
498 root 1.12 w->at = now + w->repeat;
499     assert (("timer timeout in the past, negative repeat?", w->at > now));
500     downheap ((WT *)timers, timercnt, 0);
501     }
502     else
503     evtimer_stop (w); /* nonrepeating: stop timer */
504     }
505     }
506 root 1.4
507 root 1.12 static void
508     periodics_reify ()
509     {
510     while (periodiccnt && periodics [0]->at <= ev_now)
511     {
512     struct ev_periodic *w = periodics [0];
513 root 1.1
514 root 1.12 /* first reschedule or stop timer */
515     if (w->interval)
516     {
517     w->at += floor ((ev_now - w->at) / w->interval + 1.) * w->interval;
518     assert (("periodic timeout in the past, negative interval?", w->at > ev_now));
519     downheap ((WT *)periodics, periodiccnt, 0);
520 root 1.1 }
521     else
522 root 1.12 evperiodic_stop (w); /* nonrepeating: stop timer */
523    
524     event ((W)w, EV_TIMEOUT);
525     }
526     }
527    
528     static void
529 root 1.13 periodics_reschedule (ev_tstamp diff)
530 root 1.12 {
531     int i;
532    
533 root 1.13 /* adjust periodics after time jump */
534 root 1.12 for (i = 0; i < periodiccnt; ++i)
535     {
536     struct ev_periodic *w = periodics [i];
537    
538     if (w->interval)
539 root 1.4 {
540 root 1.12 ev_tstamp diff = ceil ((ev_now - w->at) / w->interval) * w->interval;
541    
542     if (fabs (diff) >= 1e-4)
543     {
544     evperiodic_stop (w);
545     evperiodic_start (w);
546    
547     i = 0; /* restart loop, inefficient, but time jumps should be rare */
548     }
549 root 1.4 }
550 root 1.12 }
551 root 1.1 }
552    
553 root 1.4 static void
554     time_update ()
555     {
556     int i;
557 root 1.12
558 root 1.4 ev_now = ev_time ();
559    
560     if (have_monotonic)
561     {
562     ev_tstamp odiff = diff;
563    
564 root 1.12 for (i = 4; --i; ) /* loop a few times, before making important decisions */
565 root 1.4 {
566     now = get_clock ();
567     diff = ev_now - now;
568    
569     if (fabs (odiff - diff) < MIN_TIMEJUMP)
570     return; /* all is well */
571    
572     ev_now = ev_time ();
573     }
574    
575 root 1.13 periodics_reschedule (diff - odiff);
576     /* no timer adjustment, as the monotonic clock doesn't jump */
577 root 1.4 }
578     else
579     {
580     if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP)
581 root 1.13 {
582     periodics_reschedule (ev_now - now);
583    
584     /* adjust timers. this is easy, as the offset is the same for all */
585     for (i = 0; i < timercnt; ++i)
586     timers [i]->at += diff;
587     }
588 root 1.4
589     now = ev_now;
590     }
591     }
592    
593 root 1.1 int ev_loop_done;
594    
595 root 1.4 void ev_loop (int flags)
596 root 1.1 {
597     double block;
598 root 1.13 ev_loop_done = flags & EVLOOP_ONESHOT ? 1 : 0;
599 root 1.1
600 root 1.20 do
601 root 1.9 {
602 root 1.20 /* queue check watchers (and execute them) */
603 root 1.21 if (preparecnt)
604 root 1.20 {
605     queue_events ((W *)prepares, preparecnt, EV_PREPARE);
606     call_pending ();
607     }
608 root 1.9
609 root 1.1 /* update fd-related kernel structures */
610 root 1.5 fd_reify ();
611 root 1.1
612     /* calculate blocking time */
613 root 1.12
614 root 1.21 /* we only need this for !monotonic clockor timers, but as we basically
615     always have timers, we just calculate it always */
616 root 1.12 ev_now = ev_time ();
617    
618 root 1.9 if (flags & EVLOOP_NONBLOCK || idlecnt)
619 root 1.1 block = 0.;
620     else
621     {
622 root 1.4 block = MAX_BLOCKTIME;
623    
624 root 1.12 if (timercnt)
625 root 1.4 {
626 root 1.14 ev_tstamp to = timers [0]->at - (have_monotonic ? get_clock () : ev_now) + method_fudge;
627 root 1.4 if (block > to) block = to;
628     }
629    
630 root 1.12 if (periodiccnt)
631 root 1.4 {
632 root 1.12 ev_tstamp to = periodics [0]->at - ev_now + method_fudge;
633 root 1.4 if (block > to) block = to;
634     }
635    
636 root 1.1 if (block < 0.) block = 0.;
637     }
638    
639     method_poll (block);
640    
641 root 1.4 /* update ev_now, do magic */
642     time_update ();
643    
644 root 1.9 /* queue pending timers and reschedule them */
645 root 1.20 timers_reify (); /* relative timers called last */
646     periodics_reify (); /* absolute timers called first */
647 root 1.1
648 root 1.9 /* queue idle watchers unless io or timers are pending */
649     if (!pendingcnt)
650 root 1.10 queue_events ((W *)idles, idlecnt, EV_IDLE);
651 root 1.9
652 root 1.20 /* queue check watchers, to be executed first */
653     if (checkcnt)
654     queue_events ((W *)checks, checkcnt, EV_CHECK);
655 root 1.9
656 root 1.1 call_pending ();
657     }
658     while (!ev_loop_done);
659 root 1.13
660     if (ev_loop_done != 2)
661     ev_loop_done = 0;
662 root 1.1 }
663    
664 root 1.8 /*****************************************************************************/
665    
666 root 1.1 static void
667 root 1.10 wlist_add (WL *head, WL elem)
668 root 1.1 {
669     elem->next = *head;
670     *head = elem;
671     }
672    
673     static void
674 root 1.10 wlist_del (WL *head, WL elem)
675 root 1.1 {
676     while (*head)
677     {
678     if (*head == elem)
679     {
680     *head = elem->next;
681     return;
682     }
683    
684     head = &(*head)->next;
685     }
686     }
687    
688     static void
689 root 1.16 ev_clear (W w)
690     {
691     if (w->pending)
692     {
693     pendings [w->pending - 1].w = 0;
694     w->pending = 0;
695     }
696     }
697    
698     static void
699 root 1.10 ev_start (W w, int active)
700 root 1.1 {
701     w->active = active;
702     }
703    
704     static void
705 root 1.10 ev_stop (W w)
706 root 1.1 {
707     w->active = 0;
708     }
709    
710 root 1.8 /*****************************************************************************/
711    
712 root 1.1 void
713     evio_start (struct ev_io *w)
714     {
715     if (ev_is_active (w))
716     return;
717    
718     int fd = w->fd;
719    
720 root 1.10 ev_start ((W)w, 1);
721 root 1.1 array_needsize (anfds, anfdmax, fd + 1, anfds_init);
722 root 1.10 wlist_add ((WL *)&anfds[fd].head, (WL)w);
723 root 1.1
724     ++fdchangecnt;
725     array_needsize (fdchanges, fdchangemax, fdchangecnt, );
726     fdchanges [fdchangecnt - 1] = fd;
727     }
728    
729     void
730     evio_stop (struct ev_io *w)
731     {
732 root 1.16 ev_clear ((W)w);
733 root 1.1 if (!ev_is_active (w))
734     return;
735    
736 root 1.10 wlist_del ((WL *)&anfds[w->fd].head, (WL)w);
737     ev_stop ((W)w);
738 root 1.1
739     ++fdchangecnt;
740     array_needsize (fdchanges, fdchangemax, fdchangecnt, );
741     fdchanges [fdchangecnt - 1] = w->fd;
742     }
743    
744     void
745     evtimer_start (struct ev_timer *w)
746     {
747     if (ev_is_active (w))
748     return;
749    
750 root 1.12 w->at += now;
751    
752 root 1.13 assert (("timer repeat value less than zero not allowed", w->repeat >= 0.));
753    
754 root 1.12 ev_start ((W)w, ++timercnt);
755     array_needsize (timers, timermax, timercnt, );
756     timers [timercnt - 1] = w;
757     upheap ((WT *)timers, timercnt - 1);
758     }
759    
760     void
761     evtimer_stop (struct ev_timer *w)
762     {
763 root 1.16 ev_clear ((W)w);
764 root 1.12 if (!ev_is_active (w))
765     return;
766    
767     if (w->active < timercnt--)
768 root 1.1 {
769 root 1.12 timers [w->active - 1] = timers [timercnt];
770     downheap ((WT *)timers, timercnt, w->active - 1);
771     }
772 root 1.4
773 root 1.14 w->at = w->repeat;
774    
775 root 1.12 ev_stop ((W)w);
776     }
777 root 1.4
778 root 1.12 void
779 root 1.14 evtimer_again (struct ev_timer *w)
780     {
781     if (ev_is_active (w))
782     {
783     if (w->repeat)
784     {
785     w->at = now + w->repeat;
786     downheap ((WT *)timers, timercnt, w->active - 1);
787     }
788     else
789     evtimer_stop (w);
790     }
791     else if (w->repeat)
792     evtimer_start (w);
793     }
794    
795     void
796 root 1.12 evperiodic_start (struct ev_periodic *w)
797     {
798     if (ev_is_active (w))
799     return;
800 root 1.1
801 root 1.13 assert (("periodic interval value less than zero not allowed", w->interval >= 0.));
802    
803 root 1.12 /* this formula differs from the one in periodic_reify because we do not always round up */
804     if (w->interval)
805     w->at += ceil ((ev_now - w->at) / w->interval) * w->interval;
806    
807     ev_start ((W)w, ++periodiccnt);
808     array_needsize (periodics, periodicmax, periodiccnt, );
809     periodics [periodiccnt - 1] = w;
810     upheap ((WT *)periodics, periodiccnt - 1);
811 root 1.1 }
812    
813     void
814 root 1.12 evperiodic_stop (struct ev_periodic *w)
815 root 1.1 {
816 root 1.16 ev_clear ((W)w);
817 root 1.1 if (!ev_is_active (w))
818     return;
819    
820 root 1.12 if (w->active < periodiccnt--)
821 root 1.2 {
822 root 1.12 periodics [w->active - 1] = periodics [periodiccnt];
823     downheap ((WT *)periodics, periodiccnt, w->active - 1);
824 root 1.2 }
825    
826 root 1.10 ev_stop ((W)w);
827 root 1.1 }
828    
829     void
830     evsignal_start (struct ev_signal *w)
831     {
832     if (ev_is_active (w))
833     return;
834    
835 root 1.10 ev_start ((W)w, 1);
836 root 1.1 array_needsize (signals, signalmax, w->signum, signals_init);
837 root 1.10 wlist_add ((WL *)&signals [w->signum - 1].head, (WL)w);
838 root 1.7
839     if (!w->next)
840     {
841     struct sigaction sa;
842     sa.sa_handler = sighandler;
843     sigfillset (&sa.sa_mask);
844     sa.sa_flags = 0;
845     sigaction (w->signum, &sa, 0);
846     }
847 root 1.1 }
848    
849     void
850     evsignal_stop (struct ev_signal *w)
851     {
852 root 1.16 ev_clear ((W)w);
853 root 1.1 if (!ev_is_active (w))
854     return;
855    
856 root 1.10 wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w);
857     ev_stop ((W)w);
858 root 1.7
859     if (!signals [w->signum - 1].head)
860     signal (w->signum, SIG_DFL);
861 root 1.1 }
862    
863 root 1.9 void evidle_start (struct ev_idle *w)
864     {
865     if (ev_is_active (w))
866     return;
867    
868 root 1.10 ev_start ((W)w, ++idlecnt);
869 root 1.9 array_needsize (idles, idlemax, idlecnt, );
870     idles [idlecnt - 1] = w;
871     }
872    
873     void evidle_stop (struct ev_idle *w)
874     {
875 root 1.16 ev_clear ((W)w);
876     if (ev_is_active (w))
877     return;
878    
879 root 1.9 idles [w->active - 1] = idles [--idlecnt];
880 root 1.10 ev_stop ((W)w);
881 root 1.9 }
882    
883 root 1.20 void evprepare_start (struct ev_prepare *w)
884     {
885     if (ev_is_active (w))
886     return;
887    
888     ev_start ((W)w, ++preparecnt);
889     array_needsize (prepares, preparemax, preparecnt, );
890     prepares [preparecnt - 1] = w;
891     }
892    
893     void evprepare_stop (struct ev_prepare *w)
894     {
895     ev_clear ((W)w);
896     if (ev_is_active (w))
897     return;
898    
899     prepares [w->active - 1] = prepares [--preparecnt];
900     ev_stop ((W)w);
901     }
902    
903 root 1.9 void evcheck_start (struct ev_check *w)
904     {
905     if (ev_is_active (w))
906     return;
907    
908 root 1.10 ev_start ((W)w, ++checkcnt);
909 root 1.9 array_needsize (checks, checkmax, checkcnt, );
910     checks [checkcnt - 1] = w;
911     }
912    
913     void evcheck_stop (struct ev_check *w)
914     {
915 root 1.16 ev_clear ((W)w);
916     if (ev_is_active (w))
917     return;
918    
919 root 1.9 checks [w->active - 1] = checks [--checkcnt];
920 root 1.10 ev_stop ((W)w);
921 root 1.9 }
922    
923 root 1.22 void evchild_start (struct ev_child *w)
924     {
925     if (ev_is_active (w))
926     return;
927    
928     ev_start ((W)w, 1);
929     wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
930     }
931    
932     void evchild_stop (struct ev_child *w)
933     {
934     ev_clear ((W)w);
935     if (ev_is_active (w))
936     return;
937    
938     wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
939     ev_stop ((W)w);
940     }
941    
942 root 1.1 /*****************************************************************************/
943 root 1.10
944 root 1.16 struct ev_once
945     {
946     struct ev_io io;
947     struct ev_timer to;
948     void (*cb)(int revents, void *arg);
949     void *arg;
950     };
951    
952     static void
953     once_cb (struct ev_once *once, int revents)
954     {
955     void (*cb)(int revents, void *arg) = once->cb;
956     void *arg = once->arg;
957    
958     evio_stop (&once->io);
959     evtimer_stop (&once->to);
960     free (once);
961    
962     cb (revents, arg);
963     }
964    
965     static void
966     once_cb_io (struct ev_io *w, int revents)
967     {
968     once_cb ((struct ev_once *)(((char *)w) - offsetof (struct ev_once, io)), revents);
969     }
970    
971     static void
972     once_cb_to (struct ev_timer *w, int revents)
973     {
974     once_cb ((struct ev_once *)(((char *)w) - offsetof (struct ev_once, to)), revents);
975     }
976    
977     void
978     ev_once (int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
979     {
980     struct ev_once *once = malloc (sizeof (struct ev_once));
981    
982     if (!once)
983     cb (EV_ERROR, arg);
984     else
985     {
986     once->cb = cb;
987     once->arg = arg;
988    
989     evw_init (&once->io, once_cb_io);
990    
991     if (fd >= 0)
992     {
993     evio_set (&once->io, fd, events);
994     evio_start (&once->io);
995     }
996    
997     evw_init (&once->to, once_cb_to);
998    
999     if (timeout >= 0.)
1000     {
1001     evtimer_set (&once->to, timeout, 0.);
1002     evtimer_start (&once->to);
1003     }
1004     }
1005     }
1006    
1007     /*****************************************************************************/
1008    
1009 root 1.13 #if 0
1010 root 1.12
1011     struct ev_io wio;
1012 root 1.1
1013     static void
1014     sin_cb (struct ev_io *w, int revents)
1015     {
1016     fprintf (stderr, "sin %d, revents %d\n", w->fd, revents);
1017     }
1018    
1019     static void
1020     ocb (struct ev_timer *w, int revents)
1021     {
1022 root 1.4 //fprintf (stderr, "timer %f,%f (%x) (%f) d%p\n", w->at, w->repeat, revents, w->at - ev_time (), w->data);
1023     evtimer_stop (w);
1024     evtimer_start (w);
1025 root 1.1 }
1026    
1027 root 1.7 static void
1028     scb (struct ev_signal *w, int revents)
1029     {
1030     fprintf (stderr, "signal %x,%d\n", revents, w->signum);
1031 root 1.12 evio_stop (&wio);
1032     evio_start (&wio);
1033 root 1.7 }
1034    
1035 root 1.9 static void
1036     gcb (struct ev_signal *w, int revents)
1037     {
1038     fprintf (stderr, "generic %x\n", revents);
1039 root 1.12
1040 root 1.9 }
1041    
1042 root 1.1 int main (void)
1043     {
1044     ev_init (0);
1045    
1046 root 1.12 evio_init (&wio, sin_cb, 0, EV_READ);
1047     evio_start (&wio);
1048 root 1.1
1049 root 1.4 struct ev_timer t[10000];
1050 root 1.2
1051 root 1.9 #if 0
1052 root 1.2 int i;
1053 root 1.4 for (i = 0; i < 10000; ++i)
1054 root 1.2 {
1055     struct ev_timer *w = t + i;
1056     evw_init (w, ocb, i);
1057 root 1.12 evtimer_init_abs (w, ocb, drand48 (), 0.99775533);
1058 root 1.2 evtimer_start (w);
1059     if (drand48 () < 0.5)
1060     evtimer_stop (w);
1061     }
1062 root 1.4 #endif
1063    
1064     struct ev_timer t1;
1065 root 1.12 evtimer_init (&t1, ocb, 5, 10);
1066 root 1.4 evtimer_start (&t1);
1067 root 1.1
1068 root 1.7 struct ev_signal sig;
1069 root 1.12 evsignal_init (&sig, scb, SIGQUIT);
1070 root 1.7 evsignal_start (&sig);
1071    
1072 root 1.9 struct ev_check cw;
1073 root 1.12 evcheck_init (&cw, gcb);
1074 root 1.9 evcheck_start (&cw);
1075    
1076     struct ev_idle iw;
1077 root 1.12 evidle_init (&iw, gcb);
1078 root 1.9 evidle_start (&iw);
1079    
1080 root 1.1 ev_loop (0);
1081    
1082     return 0;
1083     }
1084    
1085     #endif
1086    
1087    
1088    
1089