ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev.c
Revision: 1.22
Committed: Wed Oct 31 19:07:43 2007 UTC (16 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.21: +49 -0 lines
Log Message:
include child watcher

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