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

Comparing libev/ev.c (file contents):
Revision 1.12 by root, Wed Oct 31 09:23:17 2007 UTC vs.
Revision 1.27 by root, Wed Oct 31 22:16:36 2007 UTC

1/*
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
1#include <math.h> 30#include <math.h>
2#include <stdlib.h> 31#include <stdlib.h>
3#include <unistd.h> 32#include <unistd.h>
4#include <fcntl.h> 33#include <fcntl.h>
5#include <signal.h> 34#include <signal.h>
35#include <stddef.h>
6 36
7#include <stdio.h> 37#include <stdio.h>
8 38
9#include <assert.h> 39#include <assert.h>
10#include <errno.h> 40#include <errno.h>
41#include <sys/types.h>
42#include <sys/wait.h>
11#include <sys/time.h> 43#include <sys/time.h>
12#include <time.h> 44#include <time.h>
13
14#define HAVE_EPOLL 1
15 45
16#ifndef HAVE_MONOTONIC 46#ifndef HAVE_MONOTONIC
17# ifdef CLOCK_MONOTONIC 47# ifdef CLOCK_MONOTONIC
18# define HAVE_MONOTONIC 1 48# define HAVE_MONOTONIC 1
19# endif 49# endif
31# define HAVE_REALTIME 1 /* posix requirement, but might be slower */ 61# define HAVE_REALTIME 1 /* posix requirement, but might be slower */
32#endif 62#endif
33 63
34#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ 64#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
35#define MAX_BLOCKTIME 60. 65#define MAX_BLOCKTIME 60.
66#define PID_HASHSIZE 16 /* size of pid hahs table, must be power of two */
36 67
37#include "ev.h" 68#include "ev.h"
38
39struct ev_watcher {
40 EV_WATCHER (ev_watcher);
41};
42
43struct ev_watcher_list {
44 EV_WATCHER_LIST (ev_watcher_list);
45};
46
47struct ev_watcher_time {
48 EV_WATCHER_TIME (ev_watcher_time);
49};
50 69
51typedef struct ev_watcher *W; 70typedef struct ev_watcher *W;
52typedef struct ev_watcher_list *WL; 71typedef struct ev_watcher_list *WL;
53typedef struct ev_watcher_time *WT; 72typedef struct ev_watcher_time *WT;
54 73
94} 113}
95 114
96#define array_needsize(base,cur,cnt,init) \ 115#define array_needsize(base,cur,cnt,init) \
97 if ((cnt) > cur) \ 116 if ((cnt) > cur) \
98 { \ 117 { \
99 int newcnt = cur ? cur << 1 : 16; \ 118 int newcnt = cur; \
100 fprintf (stderr, "resize(" # base ") from %d to %d\n", cur, newcnt);\ 119 do \
120 { \
121 newcnt = (newcnt << 1) | 4 & ~3; \
122 } \
123 while ((cnt) > newcnt); \
124 \
101 base = realloc (base, sizeof (*base) * (newcnt)); \ 125 base = realloc (base, sizeof (*base) * (newcnt)); \
102 init (base + cur, newcnt - cur); \ 126 init (base + cur, newcnt - cur); \
103 cur = newcnt; \ 127 cur = newcnt; \
104 } 128 }
105 129
106/*****************************************************************************/ 130/*****************************************************************************/
107 131
108typedef struct 132typedef struct
109{ 133{
110 struct ev_io *head; 134 struct ev_io *head;
111 unsigned char wev, rev; /* want, received event set */ 135 int events;
112} ANFD; 136} ANFD;
113 137
114static ANFD *anfds; 138static ANFD *anfds;
115static int anfdmax; 139static int anfdmax;
116 140
117static int *fdchanges;
118static int fdchangemax, fdchangecnt;
119
120static void 141static void
121anfds_init (ANFD *base, int count) 142anfds_init (ANFD *base, int count)
122{ 143{
123 while (count--) 144 while (count--)
124 { 145 {
125 base->head = 0; 146 base->head = 0;
126 base->wev = base->rev = EV_NONE; 147 base->events = EV_NONE;
127 ++base; 148 ++base;
128 } 149 }
129} 150}
130 151
131typedef struct 152typedef struct
138static int pendingmax, pendingcnt; 159static int pendingmax, pendingcnt;
139 160
140static void 161static void
141event (W w, int events) 162event (W w, int events)
142{ 163{
164 if (w->active)
165 {
143 w->pending = ++pendingcnt; 166 w->pending = ++pendingcnt;
144 array_needsize (pendings, pendingmax, pendingcnt, ); 167 array_needsize (pendings, pendingmax, pendingcnt, );
145 pendings [pendingcnt - 1].w = w; 168 pendings [pendingcnt - 1].w = w;
146 pendings [pendingcnt - 1].events = events; 169 pendings [pendingcnt - 1].events = events;
170 }
171}
172
173static void
174queue_events (W *events, int eventcnt, int type)
175{
176 int i;
177
178 for (i = 0; i < eventcnt; ++i)
179 event (events [i], type);
147} 180}
148 181
149static void 182static void
150fd_event (int fd, int events) 183fd_event (int fd, int events)
151{ 184{
159 if (ev) 192 if (ev)
160 event ((W)w, ev); 193 event ((W)w, ev);
161 } 194 }
162} 195}
163 196
197/*****************************************************************************/
198
199static int *fdchanges;
200static int fdchangemax, fdchangecnt;
201
164static void 202static void
165queue_events (W *events, int eventcnt, int type) 203fd_reify (void)
166{ 204{
167 int i; 205 int i;
168 206
169 for (i = 0; i < eventcnt; ++i) 207 for (i = 0; i < fdchangecnt; ++i)
170 event (events [i], type); 208 {
209 int fd = fdchanges [i];
210 ANFD *anfd = anfds + fd;
211 struct ev_io *w;
212
213 int events = 0;
214
215 for (w = anfd->head; w; w = w->next)
216 events |= w->events;
217
218 anfd->events &= ~EV_REIFY;
219
220 if (anfd->events != events)
221 {
222 method_modify (fd, anfd->events, events);
223 anfd->events = events;
224 }
225 }
226
227 fdchangecnt = 0;
228}
229
230static void
231fd_change (int fd)
232{
233 if (anfds [fd].events & EV_REIFY)
234 return;
235
236 anfds [fd].events |= EV_REIFY;
237
238 ++fdchangecnt;
239 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
240 fdchanges [fdchangecnt - 1] = fd;
241}
242
243/* called on EBADF to verify fds */
244static void
245fd_recheck (void)
246{
247 int fd;
248
249 for (fd = 0; fd < anfdmax; ++fd)
250 if (anfds [fd].events)
251 if (fcntl (fd, F_GETFD) == -1 && errno == EBADF)
252 while (anfds [fd].head)
253 {
254 event ((W)anfds [fd].head, EV_ERROR);
255 evio_stop (anfds [fd].head);
256 }
171} 257}
172 258
173/*****************************************************************************/ 259/*****************************************************************************/
174 260
175static struct ev_timer **timers; 261static struct ev_timer **timers;
293/*****************************************************************************/ 379/*****************************************************************************/
294 380
295static struct ev_idle **idles; 381static struct ev_idle **idles;
296static int idlemax, idlecnt; 382static int idlemax, idlecnt;
297 383
384static struct ev_prepare **prepares;
385static int preparemax, preparecnt;
386
298static struct ev_check **checks; 387static struct ev_check **checks;
299static int checkmax, checkcnt; 388static int checkmax, checkcnt;
300 389
301/*****************************************************************************/ 390/*****************************************************************************/
302 391
392static struct ev_child *childs [PID_HASHSIZE];
393static struct ev_signal childev;
394
395#ifndef WCONTINUED
396# define WCONTINUED 0
397#endif
398
399static void
400childcb (struct ev_signal *sw, int revents)
401{
402 struct ev_child *w;
403 int pid, status;
404
405 while ((pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED)) != -1)
406 for (w = childs [pid & (PID_HASHSIZE - 1)]; w; w = w->next)
407 if (w->pid == pid || w->pid == -1)
408 {
409 w->status = status;
410 event ((W)w, EV_CHILD);
411 }
412}
413
414/*****************************************************************************/
415
303#if HAVE_EPOLL 416#if HAVE_EPOLL
304# include "ev_epoll.c" 417# include "ev_epoll.c"
305#endif 418#endif
306#if HAVE_SELECT 419#if HAVE_SELECT
307# include "ev_select.c" 420# include "ev_select.c"
308#endif 421#endif
309 422
423int
424ev_version_major (void)
425{
426 return EV_VERSION_MAJOR;
427}
428
429int
430ev_version_minor (void)
431{
432 return EV_VERSION_MINOR;
433}
434
310int ev_init (int flags) 435int ev_init (int flags)
311{ 436{
437 if (!ev_method)
438 {
312#if HAVE_MONOTONIC 439#if HAVE_MONOTONIC
313 { 440 {
314 struct timespec ts; 441 struct timespec ts;
315 if (!clock_gettime (CLOCK_MONOTONIC, &ts)) 442 if (!clock_gettime (CLOCK_MONOTONIC, &ts))
316 have_monotonic = 1; 443 have_monotonic = 1;
317 } 444 }
318#endif 445#endif
319 446
320 ev_now = ev_time (); 447 ev_now = ev_time ();
321 now = get_clock (); 448 now = get_clock ();
322 diff = ev_now - now; 449 diff = ev_now - now;
323 450
324 if (pipe (sigpipe)) 451 if (pipe (sigpipe))
325 return 0; 452 return 0;
326 453
327 ev_method = EVMETHOD_NONE; 454 ev_method = EVMETHOD_NONE;
328#if HAVE_EPOLL 455#if HAVE_EPOLL
329 if (ev_method == EVMETHOD_NONE) epoll_init (flags); 456 if (ev_method == EVMETHOD_NONE) epoll_init (flags);
330#endif 457#endif
331#if HAVE_SELECT 458#if HAVE_SELECT
332 if (ev_method == EVMETHOD_NONE) select_init (flags); 459 if (ev_method == EVMETHOD_NONE) select_init (flags);
333#endif 460#endif
334 461
335 if (ev_method) 462 if (ev_method)
336 { 463 {
337 evw_init (&sigev, sigcb); 464 evw_init (&sigev, sigcb);
338 siginit (); 465 siginit ();
466
467 evsignal_init (&childev, childcb, SIGCHLD);
468 evsignal_start (&childev);
469 }
339 } 470 }
340 471
341 return ev_method; 472 return ev_method;
342} 473}
343 474
344/*****************************************************************************/ 475/*****************************************************************************/
345 476
477void
346void ev_prefork (void) 478ev_prefork (void)
347{ 479{
348 /* nop */ 480 /* nop */
349} 481}
350 482
483void
351void ev_postfork_parent (void) 484ev_postfork_parent (void)
352{ 485{
353 /* nop */ 486 /* nop */
354} 487}
355 488
489void
356void ev_postfork_child (void) 490ev_postfork_child (void)
357{ 491{
358#if HAVE_EPOLL 492#if HAVE_EPOLL
359 if (ev_method == EVMETHOD_EPOLL) 493 if (ev_method == EVMETHOD_EPOLL)
360 epoll_postfork_child (); 494 epoll_postfork_child ();
361#endif 495#endif
368} 502}
369 503
370/*****************************************************************************/ 504/*****************************************************************************/
371 505
372static void 506static void
373fd_reify (void)
374{
375 int i;
376
377 for (i = 0; i < fdchangecnt; ++i)
378 {
379 int fd = fdchanges [i];
380 ANFD *anfd = anfds + fd;
381 struct ev_io *w;
382
383 int wev = 0;
384
385 for (w = anfd->head; w; w = w->next)
386 wev |= w->events;
387
388 if (anfd->wev != wev)
389 {
390 method_modify (fd, anfd->wev, wev);
391 anfd->wev = wev;
392 }
393 }
394
395 fdchangecnt = 0;
396}
397
398static void
399call_pending () 507call_pending (void)
400{ 508{
401 int i; 509 while (pendingcnt)
402
403 for (i = 0; i < pendingcnt; ++i)
404 { 510 {
405 ANPENDING *p = pendings + i; 511 ANPENDING *p = pendings + --pendingcnt;
406 512
407 if (p->w) 513 if (p->w)
408 { 514 {
409 p->w->pending = 0; 515 p->w->pending = 0;
410 p->w->cb (p->w, p->events); 516 p->w->cb (p->w, p->events);
411 } 517 }
412 } 518 }
413
414 pendingcnt = 0;
415} 519}
416 520
417static void 521static void
418timers_reify () 522timers_reify (void)
419{ 523{
420 while (timercnt && timers [0]->at <= now) 524 while (timercnt && timers [0]->at <= now)
421 { 525 {
422 struct ev_timer *w = timers [0]; 526 struct ev_timer *w = timers [0];
527
528 event ((W)w, EV_TIMEOUT);
423 529
424 /* first reschedule or stop timer */ 530 /* first reschedule or stop timer */
425 if (w->repeat) 531 if (w->repeat)
426 { 532 {
427 w->at = now + w->repeat; 533 w->at = now + w->repeat;
428 assert (("timer timeout in the past, negative repeat?", w->at > now)); 534 assert (("timer timeout in the past, negative repeat?", w->at > now));
429 downheap ((WT *)timers, timercnt, 0); 535 downheap ((WT *)timers, timercnt, 0);
430 } 536 }
431 else 537 else
432 evtimer_stop (w); /* nonrepeating: stop timer */ 538 evtimer_stop (w); /* nonrepeating: stop timer */
433
434 event ((W)w, EV_TIMEOUT);
435 } 539 }
436} 540}
437 541
438static void 542static void
439periodics_reify () 543periodics_reify (void)
440{ 544{
441 while (periodiccnt && periodics [0]->at <= ev_now) 545 while (periodiccnt && periodics [0]->at <= ev_now)
442 { 546 {
443 struct ev_periodic *w = periodics [0]; 547 struct ev_periodic *w = periodics [0];
444 548
455 event ((W)w, EV_TIMEOUT); 559 event ((W)w, EV_TIMEOUT);
456 } 560 }
457} 561}
458 562
459static void 563static void
460time_jump (ev_tstamp diff) 564periodics_reschedule (ev_tstamp diff)
461{ 565{
462 int i; 566 int i;
463 567
464 /* adjust periodics */ 568 /* adjust periodics after time jump */
465 for (i = 0; i < periodiccnt; ++i) 569 for (i = 0; i < periodiccnt; ++i)
466 { 570 {
467 struct ev_periodic *w = periodics [i]; 571 struct ev_periodic *w = periodics [i];
468 572
469 if (w->interval) 573 if (w->interval)
477 581
478 i = 0; /* restart loop, inefficient, but time jumps should be rare */ 582 i = 0; /* restart loop, inefficient, but time jumps should be rare */
479 } 583 }
480 } 584 }
481 } 585 }
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} 586}
487 587
488static void 588static void
489time_update () 589time_update (void)
490{ 590{
491 int i; 591 int i;
492 592
493 ev_now = ev_time (); 593 ev_now = ev_time ();
494 594
505 return; /* all is well */ 605 return; /* all is well */
506 606
507 ev_now = ev_time (); 607 ev_now = ev_time ();
508 } 608 }
509 609
510 time_jump (diff - odiff); 610 periodics_reschedule (diff - odiff);
611 /* no timer adjustment, as the monotonic clock doesn't jump */
511 } 612 }
512 else 613 else
513 { 614 {
514 if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP) 615 if (now > ev_now || now < ev_now - MAX_BLOCKTIME - MIN_TIMEJUMP)
515 time_jump (ev_now - now); 616 {
617 periodics_reschedule (ev_now - now);
618
619 /* adjust timers. this is easy, as the offset is the same for all */
620 for (i = 0; i < timercnt; ++i)
621 timers [i]->at += diff;
622 }
516 623
517 now = ev_now; 624 now = ev_now;
518 } 625 }
519} 626}
520 627
521int ev_loop_done; 628int ev_loop_done;
522 629
523void ev_loop (int flags) 630void ev_loop (int flags)
524{ 631{
525 double block; 632 double block;
526 ev_loop_done = flags & EVLOOP_ONESHOT; 633 ev_loop_done = flags & (EVLOOP_ONESHOT | EVLOOP_NONBLOCK) ? 1 : 0;
527
528 if (checkcnt)
529 {
530 queue_events ((W *)checks, checkcnt, EV_CHECK);
531 call_pending ();
532 }
533 634
534 do 635 do
535 { 636 {
637 /* queue check watchers (and execute them) */
638 if (preparecnt)
639 {
640 queue_events ((W *)prepares, preparecnt, EV_PREPARE);
641 call_pending ();
642 }
643
536 /* update fd-related kernel structures */ 644 /* update fd-related kernel structures */
537 fd_reify (); 645 fd_reify ();
538 646
539 /* calculate blocking time */ 647 /* calculate blocking time */
540 648
541 /* we only need this for !monotonic clock, but as we always have timers, we just calculate it every time */ 649 /* we only need this for !monotonic clockor timers, but as we basically
650 always have timers, we just calculate it always */
542 ev_now = ev_time (); 651 ev_now = ev_time ();
543 652
544 if (flags & EVLOOP_NONBLOCK || idlecnt) 653 if (flags & EVLOOP_NONBLOCK || idlecnt)
545 block = 0.; 654 block = 0.;
546 else 655 else
547 { 656 {
548 block = MAX_BLOCKTIME; 657 block = MAX_BLOCKTIME;
549 658
550 if (timercnt) 659 if (timercnt)
551 { 660 {
552 ev_tstamp to = timers [0]->at - get_clock () + method_fudge; 661 ev_tstamp to = timers [0]->at - (have_monotonic ? get_clock () : ev_now) + method_fudge;
553 if (block > to) block = to; 662 if (block > to) block = to;
554 } 663 }
555 664
556 if (periodiccnt) 665 if (periodiccnt)
557 { 666 {
566 675
567 /* update ev_now, do magic */ 676 /* update ev_now, do magic */
568 time_update (); 677 time_update ();
569 678
570 /* queue pending timers and reschedule them */ 679 /* queue pending timers and reschedule them */
680 timers_reify (); /* relative timers called last */
571 periodics_reify (); /* absolute timers first */ 681 periodics_reify (); /* absolute timers called first */
572 timers_reify (); /* relative timers second */
573 682
574 /* queue idle watchers unless io or timers are pending */ 683 /* queue idle watchers unless io or timers are pending */
575 if (!pendingcnt) 684 if (!pendingcnt)
576 queue_events ((W *)idles, idlecnt, EV_IDLE); 685 queue_events ((W *)idles, idlecnt, EV_IDLE);
577 686
578 /* queue check and possibly idle watchers */ 687 /* queue check watchers, to be executed first */
688 if (checkcnt)
579 queue_events ((W *)checks, checkcnt, EV_CHECK); 689 queue_events ((W *)checks, checkcnt, EV_CHECK);
580 690
581 call_pending (); 691 call_pending ();
582 } 692 }
583 while (!ev_loop_done); 693 while (!ev_loop_done);
694
695 if (ev_loop_done != 2)
696 ev_loop_done = 0;
584} 697}
585 698
586/*****************************************************************************/ 699/*****************************************************************************/
587 700
588static void 701static void
606 head = &(*head)->next; 719 head = &(*head)->next;
607 } 720 }
608} 721}
609 722
610static void 723static void
724ev_clear (W w)
725{
726 if (w->pending)
727 {
728 pendings [w->pending - 1].w = 0;
729 w->pending = 0;
730 }
731}
732
733static void
611ev_start (W w, int active) 734ev_start (W w, int active)
612{ 735{
613 w->pending = 0;
614 w->active = active; 736 w->active = active;
615} 737}
616 738
617static void 739static void
618ev_stop (W w) 740ev_stop (W w)
619{ 741{
620 if (w->pending)
621 pendings [w->pending - 1].w = 0;
622
623 w->active = 0; 742 w->active = 0;
624} 743}
625 744
626/*****************************************************************************/ 745/*****************************************************************************/
627 746
635 754
636 ev_start ((W)w, 1); 755 ev_start ((W)w, 1);
637 array_needsize (anfds, anfdmax, fd + 1, anfds_init); 756 array_needsize (anfds, anfdmax, fd + 1, anfds_init);
638 wlist_add ((WL *)&anfds[fd].head, (WL)w); 757 wlist_add ((WL *)&anfds[fd].head, (WL)w);
639 758
640 ++fdchangecnt; 759 fd_change (fd);
641 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
642 fdchanges [fdchangecnt - 1] = fd;
643} 760}
644 761
645void 762void
646evio_stop (struct ev_io *w) 763evio_stop (struct ev_io *w)
647{ 764{
765 ev_clear ((W)w);
648 if (!ev_is_active (w)) 766 if (!ev_is_active (w))
649 return; 767 return;
650 768
651 wlist_del ((WL *)&anfds[w->fd].head, (WL)w); 769 wlist_del ((WL *)&anfds[w->fd].head, (WL)w);
652 ev_stop ((W)w); 770 ev_stop ((W)w);
653 771
654 ++fdchangecnt; 772 fd_change (w->fd);
655 array_needsize (fdchanges, fdchangemax, fdchangecnt, );
656 fdchanges [fdchangecnt - 1] = w->fd;
657} 773}
658
659 774
660void 775void
661evtimer_start (struct ev_timer *w) 776evtimer_start (struct ev_timer *w)
662{ 777{
663 if (ev_is_active (w)) 778 if (ev_is_active (w))
664 return; 779 return;
665 780
666 w->at += now; 781 w->at += now;
782
783 assert (("timer repeat value less than zero not allowed", w->repeat >= 0.));
667 784
668 ev_start ((W)w, ++timercnt); 785 ev_start ((W)w, ++timercnt);
669 array_needsize (timers, timermax, timercnt, ); 786 array_needsize (timers, timermax, timercnt, );
670 timers [timercnt - 1] = w; 787 timers [timercnt - 1] = w;
671 upheap ((WT *)timers, timercnt - 1); 788 upheap ((WT *)timers, timercnt - 1);
672} 789}
673 790
674void 791void
675evtimer_stop (struct ev_timer *w) 792evtimer_stop (struct ev_timer *w)
676{ 793{
794 ev_clear ((W)w);
677 if (!ev_is_active (w)) 795 if (!ev_is_active (w))
678 return; 796 return;
679 797
680 if (w->active < timercnt--) 798 if (w->active < timercnt--)
681 { 799 {
682 timers [w->active - 1] = timers [timercnt]; 800 timers [w->active - 1] = timers [timercnt];
683 downheap ((WT *)timers, timercnt, w->active - 1); 801 downheap ((WT *)timers, timercnt, w->active - 1);
684 } 802 }
685 803
804 w->at = w->repeat;
805
686 ev_stop ((W)w); 806 ev_stop ((W)w);
687} 807}
688 808
689void 809void
810evtimer_again (struct ev_timer *w)
811{
812 if (ev_is_active (w))
813 {
814 if (w->repeat)
815 {
816 w->at = now + w->repeat;
817 downheap ((WT *)timers, timercnt, w->active - 1);
818 }
819 else
820 evtimer_stop (w);
821 }
822 else if (w->repeat)
823 evtimer_start (w);
824}
825
826void
690evperiodic_start (struct ev_periodic *w) 827evperiodic_start (struct ev_periodic *w)
691{ 828{
692 if (ev_is_active (w)) 829 if (ev_is_active (w))
693 return; 830 return;
831
832 assert (("periodic interval value less than zero not allowed", w->interval >= 0.));
694 833
695 /* this formula differs from the one in periodic_reify because we do not always round up */ 834 /* this formula differs from the one in periodic_reify because we do not always round up */
696 if (w->interval) 835 if (w->interval)
697 w->at += ceil ((ev_now - w->at) / w->interval) * w->interval; 836 w->at += ceil ((ev_now - w->at) / w->interval) * w->interval;
698 837
703} 842}
704 843
705void 844void
706evperiodic_stop (struct ev_periodic *w) 845evperiodic_stop (struct ev_periodic *w)
707{ 846{
847 ev_clear ((W)w);
708 if (!ev_is_active (w)) 848 if (!ev_is_active (w))
709 return; 849 return;
710 850
711 if (w->active < periodiccnt--) 851 if (w->active < periodiccnt--)
712 { 852 {
738} 878}
739 879
740void 880void
741evsignal_stop (struct ev_signal *w) 881evsignal_stop (struct ev_signal *w)
742{ 882{
883 ev_clear ((W)w);
743 if (!ev_is_active (w)) 884 if (!ev_is_active (w))
744 return; 885 return;
745 886
746 wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w); 887 wlist_del ((WL *)&signals [w->signum - 1].head, (WL)w);
747 ev_stop ((W)w); 888 ev_stop ((W)w);
760 idles [idlecnt - 1] = w; 901 idles [idlecnt - 1] = w;
761} 902}
762 903
763void evidle_stop (struct ev_idle *w) 904void evidle_stop (struct ev_idle *w)
764{ 905{
906 ev_clear ((W)w);
907 if (ev_is_active (w))
908 return;
909
765 idles [w->active - 1] = idles [--idlecnt]; 910 idles [w->active - 1] = idles [--idlecnt];
911 ev_stop ((W)w);
912}
913
914void evprepare_start (struct ev_prepare *w)
915{
916 if (ev_is_active (w))
917 return;
918
919 ev_start ((W)w, ++preparecnt);
920 array_needsize (prepares, preparemax, preparecnt, );
921 prepares [preparecnt - 1] = w;
922}
923
924void evprepare_stop (struct ev_prepare *w)
925{
926 ev_clear ((W)w);
927 if (ev_is_active (w))
928 return;
929
930 prepares [w->active - 1] = prepares [--preparecnt];
766 ev_stop ((W)w); 931 ev_stop ((W)w);
767} 932}
768 933
769void evcheck_start (struct ev_check *w) 934void evcheck_start (struct ev_check *w)
770{ 935{
776 checks [checkcnt - 1] = w; 941 checks [checkcnt - 1] = w;
777} 942}
778 943
779void evcheck_stop (struct ev_check *w) 944void evcheck_stop (struct ev_check *w)
780{ 945{
946 ev_clear ((W)w);
947 if (ev_is_active (w))
948 return;
949
781 checks [w->active - 1] = checks [--checkcnt]; 950 checks [w->active - 1] = checks [--checkcnt];
782 ev_stop ((W)w); 951 ev_stop ((W)w);
783} 952}
784 953
785/*****************************************************************************/ 954void evchild_start (struct ev_child *w)
955{
956 if (ev_is_active (w))
957 return;
786 958
959 ev_start ((W)w, 1);
960 wlist_add ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
961}
962
963void evchild_stop (struct ev_child *w)
964{
965 ev_clear ((W)w);
966 if (ev_is_active (w))
967 return;
968
969 wlist_del ((WL *)&childs [w->pid & (PID_HASHSIZE - 1)], (WL)w);
970 ev_stop ((W)w);
971}
972
973/*****************************************************************************/
974
975struct ev_once
976{
977 struct ev_io io;
978 struct ev_timer to;
979 void (*cb)(int revents, void *arg);
980 void *arg;
981};
982
983static void
984once_cb (struct ev_once *once, int revents)
985{
986 void (*cb)(int revents, void *arg) = once->cb;
987 void *arg = once->arg;
988
989 evio_stop (&once->io);
990 evtimer_stop (&once->to);
991 free (once);
992
993 cb (revents, arg);
994}
995
996static void
997once_cb_io (struct ev_io *w, int revents)
998{
999 once_cb ((struct ev_once *)(((char *)w) - offsetof (struct ev_once, io)), revents);
1000}
1001
1002static void
1003once_cb_to (struct ev_timer *w, int revents)
1004{
1005 once_cb ((struct ev_once *)(((char *)w) - offsetof (struct ev_once, to)), revents);
1006}
1007
1008void
1009ev_once (int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
1010{
1011 struct ev_once *once = malloc (sizeof (struct ev_once));
1012
1013 if (!once)
1014 cb (EV_ERROR, arg);
1015 else
1016 {
1017 once->cb = cb;
1018 once->arg = arg;
1019
1020 evw_init (&once->io, once_cb_io);
1021
1022 if (fd >= 0)
1023 {
1024 evio_set (&once->io, fd, events);
1025 evio_start (&once->io);
1026 }
1027
1028 evw_init (&once->to, once_cb_to);
1029
1030 if (timeout >= 0.)
1031 {
1032 evtimer_set (&once->to, timeout, 0.);
1033 evtimer_start (&once->to);
1034 }
1035 }
1036}
1037
1038/*****************************************************************************/
1039
787#if 1 1040#if 0
788 1041
789struct ev_io wio; 1042struct ev_io wio;
790 1043
791static void 1044static void
792sin_cb (struct ev_io *w, int revents) 1045sin_cb (struct ev_io *w, int revents)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines