1 module deimos.ev;
2 
3 /*
4  * libev native API header
5  *
6  * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  *   1.  Redistributions of source code must retain the above copyright notice,
13  *       this list of conditions and the following disclaimer.
14  *
15  *   2.  Redistributions in binary form must reproduce the above copyright
16  *       notice, this list of conditions and the following disclaimer in the
17  *       documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
21  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
22  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
23  * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
27  * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Alternatively, the contents of this file may be used under the terms of
31  * the GNU General Public License ("GPL") version 2 or any later version,
32  * in which case the provisions of the GPL are applicable instead of
33  * the above. If you wish to allow the use of your version of this file
34  * only under the terms of the GPL and not to allow others to use your
35  * version of this file under the BSD license, indicate your decision
36  * by deleting the provisions above and replace them with the notice
37  * and other provisions required by the GPL. If you do not delete the
38  * provisions above, a recipient may use your version of this file under
39  * either the BSD or the GPL.
40  */
41 
42 import core.stdc.signal;
43 import core.stdc.config : c_long;
44 
45 extern(C):
46 
47 /*****************************************************************************/
48 
49 //TODO: Better way to define default versions
50 //TODO: EV_FEATURES_* is not working
51 
52 /* pre-4.0 compatibility */
53 /*version = LIBEV3_COMPAT;*/
54 version = LIBEV4;
55 version = EV_MULTIPLICITY;
56 version = EV_PERIODIC_ENABLE;
57 
58 // Unsupported on Windows; don't enable by default
59 version(Windows) {} else version = EV_STAT_ENABLE;
60 
61 version = EV_IDLE_ENABLE;
62 version = EV_FORK_ENABLE;
63 version = EV_EMBED_ENABLE;
64 version = EV_ASYNC_ENABLE;
65 version = EV_SIGNAL_ENABLE;
66 version = EV_CHILD_ENABLE;
67 version = EV_PREPARE_ENABLE;
68 version = EV_CHECK_ENABLE;
69 version = ENABLE_ADDITIONAL_FEATURES;
70 //version = EV_WALK_ENABLE; not yet
71 
72 version(LIBEV4)
73 {
74     version = EV_CLEANUP_ENABLE;
75 }
76 
77 /*****************************************************************************/
78 
79 alias double ev_tstamp;
80 struct ev_loop_t;
81 enum EV_MINIMAL = 0;
82 
83 /* these priorities are inclusive, higher priorities will be invoked earlier */
84 enum EV_MINPRI = -2;
85 enum EV_MAXPRI = 2;
86 
87 alias /*volatile*/ shared sig_atomic_t EV_ATOMIC_T;
88 
89 version(EV_STAT_ENABLE)
90 {
91     version(Windows)
92     {
93         import core.stdc.time;
94         static assert(false, "EV_STAT_ENABLE not supported on windows");
95         //import core.sys.windows.sys.types;
96         //import core.sys.windows.sys.stat;
97     }
98     else version(Posix)
99     {
100         import core.sys.posix.sys.stat;
101     }
102     else
103     {
104         static assert(false, "EV_STAT_ENABLE not supported on this platform");
105     }
106 }
107 /* support multiple event loops? */
108 version(EV_MULTIPLICITY)
109 {
110     /* TODO: These enum string are #defines in the C
111      * header. They're used in function definitions:
112      * void test(EV_P_ int hello)
113      * D string mixins don't work in this case!
114      */
115     enum EV_P = "ev_loop_t* loop";                 /* a loop as sole parameter in a declaration */
116     enum EV_P_ = "ev_loop_t* loop,";               /* a loop as first of multiple parameters */
117     enum EV_A = "loop";                            /* a loop as sole argument to a function call */
118     enum EV_A_ = EV_A;                             /* a loop as first of multiple arguments */
119     enum EV_DEFAULT_UC = "ev_default_loop_uc()";   /* the default loop, if initialised, as sole arg */
120     enum EV_DEFAULT_UC_ = EV_DEFAULT_UC;           /* the default loop as first of multiple arguments */
121     enum EV_DEFAULT = "ev_default_loop(0)";        /* the default loop as sole arg */
122     enum EV_DEFAULT_ = EV_DEFAULT;                 /* the default loop as first of multiple arguments */             
123 }
124 else
125 {
126     static assert(false, "BUG: EV_MULTIPLICITY is required");
127 }
128 
129 /*****************************************************************************/
130 
131 enum EV_VERSION_MAJOR = 4;
132 enum EV_VERSION_MINOR = 4;
133 
134 /* eventmask, revents, events... */
135 enum : uint
136 {
137     EV_UNDEF    = 0xFFFFFFFF, /** guaranteed to be invalid */
138     EV_NONE     =       0x00, /** no events */
139     EV_READ     =       0x01, /** ev_io detected read will not block */
140     EV_WRITE    =       0x02, /** ev_io detected write will not block */
141     EV__IOFDSET =       0x80, /** internal use only */
142     EV_IO       =    EV_READ, /** alias for type-detection */
143     EV_PERIODIC = 0x00000200, /** periodic timer timed out */
144     EV_SIGNAL   = 0x00000400, /** signal was received */
145     EV_CHILD    = 0x00000800, /** child/pid had status change */
146     EV_STAT     = 0x00001000, /** stat data changed */
147     EV_IDLE     = 0x00002000, /** event loop is idling */
148     EV_PREPARE  = 0x00004000, /** event loop about to poll */
149     EV_CHECK    = 0x00008000, /** event loop finished poll */
150     EV_EMBED    = 0x00010000, /** embedded event loop needs sweep */
151     EV_FORK     = 0x00020000, /** event loop resumed in child */
152     EV_ASYNC    = 0x00040000, /** async intra-loop signal */
153     EV_CUSTOM   = 0x01000000, /** for use by user code */
154     EV_ERROR    = 0x80000000, /** sent when an error occurs */
155 }
156 
157 version(LIBEV4)
158 {
159     enum : uint
160     {
161         EV_TIMER    = 0x00000100, /** timer timed out */
162         EV_CLEANUP  = 0x00040000, /** event loop resumed in child */
163     }
164     version(LIBEV3_COMPAT)
165     {
166         enum : uint
167         {
168             EV_TIMEOUT = EV_TIMER,   /** pre 4.0 API compatibility */
169         }
170     }
171 }
172 
173 /* can be used to add custom fields to all watchers, while losing binary compatibility */
174 template EV_COMMON()
175 {
176     void* data; ///
177 }
178 
179 template EV_CB_DECLARE(TYPE)
180 {
181     void function (ev_loop_t*, TYPE*, int) cb; ///
182 }
183 /+
184 #ifndef EV_CB_INVOKE
185 # define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents))
186 #endif+/
187 
188 /* not official, do not use */
189 //#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents)
190 
191 /*
192  * struct member types:
193  * private: you may look at them, but not change them,
194  *          and they might not mean anything to you.
195  * ro: can be read anytime, but only changed when the watcher isn't active.
196  * rw: can be read and modified anytime, even when the watcher is active.
197  *
198  * some internal details that might be helpful for debugging:
199  *
200  * active is either 0, which means the watcher is not active,
201  *           or the array index of the watcher (periodics, timers)
202  *           or the array index + 1 (most other watchers)
203  *           or simply 1 for watchers that aren't in some array.
204  * pending is either 0, in which case the watcher isn't,
205  *           or the array index + 1 in the pendings array.
206  */
207 
208 static if(EV_MINPRI == EV_MAXPRI)
209 {
210     template EV_DECL_PRIORITY()
211     {
212     }
213 }
214 else
215 {
216     template EV_DECL_PRIORITY()
217     {
218         int priority; ///
219     }
220 }
221 
222 /* shared by all watchers */
223 template EV_WATCHER(TYPE)
224 {
225     int active;                 // private
226     int pending;                // private
227     mixin EV_DECL_PRIORITY;     // private
228     mixin EV_COMMON;            // rw
229     mixin EV_CB_DECLARE!(TYPE); // private
230 }
231 
232 template EV_WATCHER_LIST(TYPE)
233 {
234     mixin EV_WATCHER!(TYPE);
235     ev_watcher_list* next;      // private
236 }
237 
238 template EV_WATCHER_TIME(TYPE)
239 {
240     mixin EV_WATCHER!(TYPE);
241     ev_tstamp at;               // private
242 }
243 
244 /* base class, nothing to see here unless you subclass */
245 struct ev_watcher
246 {
247   mixin EV_WATCHER!(ev_watcher);
248 }
249 
250 /* base class, nothing to see here unless you subclass */
251 struct ev_watcher_list
252 {
253   mixin EV_WATCHER_LIST!(ev_watcher_list);
254 }
255 
256 /* base class, nothing to see here unless you subclass */
257 struct ev_watcher_time
258 {
259   mixin EV_WATCHER_TIME!(ev_watcher_time);
260 }
261 
262 /* invoked when fd is either EV_READable or EV_WRITEable */
263 /* revent EV_READ, EV_WRITE */
264 struct ev_io
265 {
266   mixin EV_WATCHER_LIST!(ev_io);
267 
268   int fd;     /* ro */
269   int events; /* ro */
270 }
271 
272 /* invoked after a specific time, repeatable (based on monotonic clock) */
273 /* revent EV_TIMEOUT */
274 struct ev_timer
275 {
276   mixin EV_WATCHER_TIME!(ev_timer);
277 
278   ev_tstamp repeat; /* rw */
279 }
280 
281 version(EV_PERIODIC_ENABLE)
282 {
283     /* invoked at some specific time, possibly repeating at regular intervals (based on UTC)
284      revent EV_PERIODIC */
285     struct ev_periodic
286     {
287       mixin EV_WATCHER_TIME!(ev_periodic);
288     
289       ev_tstamp offset; /* rw */
290       ev_tstamp interval; /* rw */
291       ev_tstamp function(ev_periodic *w, ev_tstamp now) reschedule_cb; /* rw */
292     }
293 }
294 
295 /* invoked when the given signal has been received */
296 /* revent EV_SIGNAL */
297 struct ev_signal
298 {
299   mixin EV_WATCHER_LIST!(ev_signal);
300 
301   int signum; /* ro */
302 }
303 
304 /* invoked when sigchld is received and waitpid indicates the given pid */
305 /* revent EV_CHILD */
306 /* does not support priorities */
307 struct ev_child
308 {
309   mixin EV_WATCHER_LIST!(ev_child);
310 
311   int flags;   /* private */
312   int pid;     /* ro */
313   int rpid;    /* rw, holds the received pid */
314   int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */
315 }
316 
317 version(EV_STAT_ENABLE)
318 {
319     version(Windows)
320     {
321         static assert(false, "EV_STAT_ENABLE not supported on windows");
322         // Maybe this should work? _stati64?
323         //static import stat = std.c.windows.stat;
324         //alias stat.stat_t ev_statdata;
325     }
326     else version(Posix)
327     {
328         static import stat = core.sys.posix.sys.stat;
329         alias stat.stat_t ev_statdata;
330     }
331     else
332     {
333         static assert(false, "EV_STAT_ENABLE not supported on this platform");
334     }
335     
336     /* invoked each time the stat data changes for a given path
337      revent EV_STAT */
338     struct ev_stat
339     {
340       mixin EV_WATCHER_LIST!(ev_stat);
341     
342       ev_timer timer;     /* private */
343       ev_tstamp interval; /* ro */
344       const (char)* path;   /* ro */
345       ev_statdata prev;   /* ro */
346       ev_statdata attr;   /* ro */
347     
348       int wd; /* wd for inotify, fd for kqueue */
349     }
350 }
351 
352 version(EV_IDLE_ENABLE)
353 {
354     /* invoked when the nothing else needs to be done, keeps the process from blocking
355     revent EV_IDLE */
356     struct ev_idle
357     {
358       mixin EV_WATCHER!(ev_idle);
359     }
360 }
361 
362 /* invoked for each run of the mainloop, just before the blocking call */
363 /* you can still change events in any way you like */
364 /* revent EV_PREPARE */
365 struct ev_prepare
366 {
367   mixin EV_WATCHER!(ev_prepare);
368 }
369 
370 /* invoked for each run of the mainloop, just after the blocking call */
371 /* revent EV_CHECK */
372 struct ev_check
373 {
374   mixin EV_WATCHER!(ev_check);
375 }
376 
377 version(EV_FORK_ENABLE)
378 {
379     /* the callback gets invoked before check in the child process when a fork was detected
380      revent EV_FORK */
381     struct ev_fork
382     {
383       mixin EV_WATCHER!(ev_fork);
384     }
385 }
386 
387 version(LIBEV4)
388 {
389     version(EV_CLEANUP_ENABLE)
390     {
391         /* is invoked just before the loop gets destroyed
392          revent EV_CLEANUP */
393         struct ev_cleanup
394         {
395           mixin EV_WATCHER!(ev_cleanup);
396         }
397     }
398 }
399 
400 version(EV_EMBED_ENABLE)
401 {
402     /* used to embed an event loop inside another
403      the callback gets invoked when the event loop has handled events, and can be 0 */
404     struct ev_embed
405     {
406       mixin EV_WATCHER!(ev_embed);
407     
408       ev_loop_t *other; /* ro */
409       ev_io io;              /* private */
410       ev_prepare prepare;    /* private */
411       ev_check check;        /* unused */
412       ev_timer timer;        /* unused */
413       ev_periodic periodic;  /* unused */
414       ev_idle idle;          /* unused */
415       ev_fork fork;          /* private */
416       version(LIBEV4)
417       {
418           version(EV_CLEANUP_ENABLE)
419           {
420               ev_cleanup cleanup; /* unused */
421           }
422       }
423     }
424 }
425 
426 version(EV_ASYNC_ENABLE)
427 {
428     /* invoked when somebody calls ev_async_send on the watcher
429      revent EV_ASYNC */
430     struct ev_async
431     {
432       mixin EV_WATCHER!(ev_async);
433     
434       EV_ATOMIC_T sent; /* private */
435     }
436     //
437     bool ev_async_pending(ev_async* watch)
438     {
439         if(watch.sent)
440             return true;
441         else
442             return false;
443     }
444 }
445 
446 /+ ***************Not supported in D***************** 
447 /* the presence of this union forces similar struct layout */
448 union ev_any_watcher
449 {
450   struct ev_watcher w;
451   struct ev_watcher_list wl;
452 
453   struct ev_io io;
454   struct ev_timer timer;
455   struct ev_periodic periodic;
456   struct ev_signal signal;
457   struct ev_child child;
458 #if EV_STAT_ENABLE
459   struct ev_stat stat;
460 #endif
461 #if EV_IDLE_ENABLE
462   struct ev_idle idle;
463 #endif
464   struct ev_prepare prepare;
465   struct ev_check check;
466 #if EV_FORK_ENABLE
467   struct ev_fork fork;
468 #endif
469 + LIBEV4 only
470 #if EV_CLEANUP_ENABLE
471   struct ev_cleanup cleanup;
472 #endif
473 + End LIBEV4 only
474 #if EV_EMBED_ENABLE
475   struct ev_embed embed;
476 #endif
477 #if EV_ASYNC_ENABLE
478   struct ev_async async;
479 #endif
480 };
481 +/
482 
483 enum : uint
484 {
485     /* flag bits for ev_default_loop and ev_loop_t_new
486      the default */
487     EVFLAG_AUTO       = 0x00000000U, /* not quite a mask */
488     /* flag bits */
489     EVFLAG_NOENV      = 0x01000000U, /* do NOT consult environment */
490     EVFLAG_FORKCHECK  = 0x02000000U, /* check for a fork in each iteration */
491     /* debugging/feature disable */
492     EVFLAG_NOINOTIFY  = 0x00100000U, /* do not attempt to use inotify */
493     EVFLAG_SIGNALFD   = 0x00200000U, /* attempt to use signalfd */
494     /* method bits to be ored together */
495     EVBACKEND_SELECT  = 0x00000001U, /* about anywhere */
496     EVBACKEND_POLL    = 0x00000002U, /* !win */
497     EVBACKEND_EPOLL   = 0x00000004U, /* linux */
498     EVBACKEND_KQUEUE  = 0x00000008U, /* bsd */
499     EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /** NYI */
500     EVBACKEND_PORT    = 0x00000020U, /* solaris 10 */
501     EVBACKEND_ALL     = 0x0000003FU  /* all known backends */
502 }
503 
504 version(LIBEV4)
505 {
506     enum : uint
507     {
508         EVFLAG_NOSIGMASK = 0x00400000U,  /* avoid modifying the signal mask */
509         EVBACKEND_MASK    = 0x0000FFFFU  /* all future backends */
510     }
511     version(LIBEV3_COMPAT)
512     {
513         enum : uint
514         {
515             EVFLAG_NOSIGFD    = 0 /* compatibility to pre-3.9 */
516         }
517     }
518 }
519 else
520 {
521     enum : uint
522     {
523         EVFLAG_NOSIGFD    = 0 /* compatibility to pre-3.9 */
524     }
525 }
526 
527 int ev_version_major ();
528 int ev_version_minor ();
529 
530 uint ev_supported_backends();
531 uint ev_recommended_backends();
532 uint ev_embeddable_backends();
533 
534 ev_tstamp ev_time();
535 void ev_sleep (ev_tstamp delay); /* sleep for a while */
536 
537 /* Sets the allocation function to use, works like realloc.
538  * It is used to allocate and free memory.
539  * If it returns zero when memory needs to be allocated, the library might abort
540  * or take some potentially destructive action.
541  * The default is your system realloc function.
542  */
543 void ev_set_allocator(void* function(void* ptr, c_long size));
544 
545 /* set the callback function to call on a
546  * retryable syscall error
547  * (such as failed select, poll, epoll_wait)
548  */
549 void ev_set_syserr_cb(void function(const (char*) msg));
550 
551 version(EV_MULTIPLICITY)
552 {
553     __gshared extern ev_loop_t* ev_default_loop_ptr;
554     ev_loop_t* ev_default_loop_uc()
555     {
556       return ev_default_loop_ptr;
557     }
558 
559     version(LIBEV4)
560     {
561         ev_loop_t *ev_default_loop(uint flags);
562     }
563     else
564     {
565         ev_loop_t* ev_default_loop_init(uint flags);
566         /* the default loop is the only one that handles signals and child watchers 
567          you can call this as often as you like */
568         ev_loop_t *ev_default_loop(uint flags)
569         {
570           ev_loop_t* loop = ev_default_loop_uc();
571         
572           if (!loop)
573             {
574               loop = ev_default_loop_init(flags);
575             }
576         
577           return loop;
578         }
579     }
580     
581     /* create and destroy alternative loops that don't handle signals */
582     ev_loop_t* ev_loop_new (uint flags);
583     version(LIBEV4){}
584     else
585     {
586         void ev_loop_destroy (/*mixin(EV_P)*/ ev_loop_t* loop);
587         void ev_loop_fork (/*mixin(EV_P)*/ ev_loop_t* loop);
588     }
589     
590     ev_tstamp ev_now (/*mixin(EV_P)*/ ev_loop_t* loop); /* time w.r.t. timers and the eventloop, updated after each poll */
591 }
592 else
593 {
594     //This part should work, but it's not tested:
595     static assert(false, "BUG: EV_MULTIPLICITY is required");
596 
597     int ev_default_loop(uint flags); /* returns true when successful */
598     __gshared ev_tstamp ev_rt_now;
599     ev_tstamp ev_now() //
600     {
601       return ev_rt_now;
602     }
603 }
604 
605 int ev_is_default_loop(/*mixin(EV_P)*/ ev_loop_t* loop) ///
606 {
607     version(EV_MULTIPLICITY)
608     {
609       return !!(mixin(EV_A) == ev_default_loop_ptr);
610     }
611     else
612       return 1;
613 }
614 
615 version(LIBEV4)
616 {
617     /* destroy event loops, also works for the default loop */
618     void ev_loop_destroy (/*mixin(EV_P)*/ ev_loop_t* loop);
619 
620     /* this needs to be called after fork, to duplicate the loop
621      when you want to re-use it in the child
622      you can call it in either the parent or the child
623      you can actually call it at any time, anywhere :) */
624     void ev_loop_fork (/*mixin(EV_P)*/ ev_loop_t* loop);
625 }
626 else
627 {
628     void ev_default_destroy(); /* destroy the default loop */
629     
630     /* this needs to be called after fork, to duplicate the default loop
631     * if you create alternative loops you have to call ev_loop_t_fork on them
632     * you can call it in either the parent or the child
633     * you can actually call it at any time, anywhere :) */
634     void ev_default_fork ();
635 }
636 
637 uint ev_backend(/*mixin(EV_P)*/ ev_loop_t* loop); /* backend in use by loop */
638 
639 void ev_now_update(/*mixin(EV_P)*/ ev_loop_t* loop); /* update event loop time */
640 
641 version(EV_WALK_ENABLE)
642 {
643     /* walk (almost) all watchers in the loop of a given type, invoking the
644     * callback on every such watcher. The callback might stop the watcher,
645     * but do nothing else with the loop */
646     void ev_walk (/*mixin(EV_P_)*/ ev_loop_t* loop, int types, void function(/*mixin(EV_P_)*/ ev_loop_t* loop, int type, void* w));
647 }
648 
649 version(LIBEV4)
650 {
651     /* ev_run flags values */
652     enum {
653       EVRUN_NOWAIT = 1, /** do not block/wait */
654       EVRUN_ONCE   = 2  /** block *once* only */
655     }
656     
657     /* ev_break how values */
658     enum {
659       EVBREAK_CANCEL = 0, /** undo unloop */
660       EVBREAK_ONE    = 1, /** unloop once */
661       EVBREAK_ALL    = 2  /** unloop all loops */
662     }
663 }
664 else
665 {
666     enum
667     {
668         EVLOOP_NONBLOCK =1, /* do not block/wait */
669         EVLOOP_ONESHOT = 2 /* block *once* only */
670     }
671     enum
672     {
673         EVUNLOOP_CANCEL = 0, /* undo unloop */
674         EVUNLOOP_ONE    = 1, /* unloop once */
675         EVUNLOOP_ALL    = 2 /* unloop all loops */
676     }
677 }
678 
679 version(LIBEV4)
680 {
681     void ev_run (/*mixin(EV_P_)*/ ev_loop_t* loop, int flags);
682     void ev_break (/*mixin(EV_P_)*/ ev_loop_t* loop, int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */
683 }
684 else
685 {
686     void ev_loop (/*mixin(EV_P_)*/ ev_loop_t* loop, int flags);
687     void ev_unloop (/*mixin(EV_P_)*/ ev_loop_t* loop, int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */
688 }
689 
690 /*
691  * ref/unref can be used to add or remove a refcount on the mainloop. every watcher
692  * keeps one reference. if you have a long-running watcher you never unregister that
693  * should not keep ev_loop from running, unref() after starting, and ref() before stopping.
694  */
695 void ev_ref   (/*mixin(EV_P)*/ ev_loop_t* loop);
696 void ev_unref (/*mixin(EV_P)*/ ev_loop_t* loop);
697 
698 /*
699  * convenience function, wait for a single event, without registering an event watcher
700  * if timeout is < 0, do wait indefinitely
701  */
702 void ev_once (/*mixin(EV_P_)*/ ev_loop_t* loop, int fd, int events, ev_tstamp timeout, void function(int revents, void* arg), void *arg);
703 
704 version(ENABLE_ADDITIONAL_FEATURES)
705 {
706     version(LIBEV4)
707     {
708         uint ev_iteration (/*mixin(EV_P)*/ ev_loop_t* loop); /* number of loop iterations */
709         uint ev_depth     (/*mixin(EV_P)*/ ev_loop_t* loop); /* #ev_loop enters - #ev_loop leaves */
710         void ev_verify    (/*mixin(EV_P)*/ ev_loop_t* loop); /* abort if loop data corrupted */
711     }
712     else
713     {
714         uint ev_loop_count  (/*mixin(EV_P)*/ ev_loop_t* loop); /* number of loop iterations */
715         uint ev_loop_depth  (/*mixin(EV_P)*/ ev_loop_t* loop); /* #ev_loop_t enters - #ev_loop_t leaves */
716         void ev_loop_verify (/*mixin(EV_P)*/ ev_loop_t* loop); /* abort if loop data corrupted */
717     }
718     
719     void ev_set_io_collect_interval (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_tstamp interval); /* sleep at least this time, default 0 */
720     void ev_set_timeout_collect_interval (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_tstamp interval); /* sleep at least this time, default 0 */
721     
722     /* advanced stuff for threading etc. support, see docs */
723     void ev_set_userdata (/*mixin(EV_P_)*/ ev_loop_t* loop, void *data);
724     void *ev_userdata (/*mixin(EV_P)*/ ev_loop_t* loop);
725     void ev_set_invoke_pending_cb (/*mixin(EV_P_)*/ ev_loop_t* loop, void function(/*mixin(EV_P)*/ ev_loop_t* loop) invoke_pending_cb);
726     void ev_set_loop_release_cb (/*mixin(EV_P_)*/ ev_loop_t* loop, void function(/*mixin(EV_P)*/ ev_loop_t* loop) release, void function(/*mixin(EV_P)*/ ev_loop_t* loop) acquire);
727     
728     uint ev_pending_count (/*mixin(EV_P)*/ ev_loop_t* loop); /* number of pending events, if any */
729     void ev_invoke_pending (/*mixin(EV_P)*/ ev_loop_t* loop); /* invoke all pending watchers */
730     
731     /*
732      * stop/start the timer handling.
733      */
734     void ev_suspend (/*mixin(EV_P)*/ ev_loop_t* loop);
735     void ev_resume  (/*mixin(EV_P)*/ ev_loop_t* loop);
736 }
737 
738 /* these may evaluate ev multiple times, and the other arguments at most once */
739 /* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */
740 void ev_init(TYPE)(TYPE* w, void function(ev_loop_t*, TYPE*, int) cb)
741 {
742     w.active = 0;
743     w.pending = 0;
744     ev_set_priority(w, 0);
745     ev_set_cb(w, cb);
746 }
747 void ev_io_set(ev_io* w, int fd, int events)
748 {
749         w.fd = fd;
750         w.events = events | EV__IOFDSET;
751 }
752 void ev_timer_set(ev_timer* w, ev_tstamp after, ev_tstamp repeat)
753 {
754         w.at = after;
755         w.repeat = repeat;
756 }
757 void ev_periodic_set(ev_periodic* w, ev_tstamp ofs, ev_tstamp ival,
758                 ev_tstamp function(ev_periodic *w, ev_tstamp now) res)
759 {
760         w.offset = ofs;
761         w.interval = ival;
762         w.reschedule_cb = res;
763 }
764 void ev_signal_set(ev_signal* w, int signum)
765 {
766         w.signum = signum;
767 }
768 void ev_child_set(ev_child* w, int pid, int trace)
769 {
770         w.pid = pid;
771         w.flags = !!trace;
772 }
773 version(EV_STAT_ENABLE) void ev_stat_set(ev_stat* w, char* path, ev_tstamp interval)
774 {
775         w.path = path;
776         w.interval = interval;
777         w.wd = -2;
778 }
779 void ev_idle_set(ev_idle* w) /* nop, yes, this is a serious in-joke */
780 {
781 }
782 void ev_prepare_set(ev_prepare* w) /* nop, yes, this is a serious in-joke */
783 {
784 }
785 void ev_check_set(ev_check* w) /* nop, yes, this is a serious in-joke */
786 {
787 }
788 void ev_embed_set(ev_embed* w, ev_loop_t* other)
789 {
790         w.other = other;
791 }
792 void ev_fork_set(ev_fork* w) /* nop, yes, this is a serious in-joke */
793 {
794 }
795 version(LIBEV4)
796 {
797     version(EV_CLEANUP_ENABLE)
798     {
799         void ev_cleanup_set(ev_cleanup* w){}; /* nop, yes, this is a serious in-joke */
800     }            
801 }
802 void ev_async_set(ev_async* w) /* nop, yes, this is a serious in-joke */
803 {
804 }
805 void ev_io_init(ev_io* w, void function(ev_loop_t*, ev_io*, int) cb, int fd,
806         int events)
807 {
808     ev_init(w, cb);
809     ev_io_set(w, fd, events);
810 }
811 void ev_timer_init(ev_timer* w, void function(ev_loop_t*, ev_timer*, int) cb,
812         ev_tstamp after, ev_tstamp repeat)
813 {
814     ev_init(w, cb);
815     ev_timer_set(w, after, repeat);
816 }
817 void ev_periodic_init(ev_periodic* w,
818         void function(ev_loop_t*, ev_periodic*, int) cb,
819         ev_tstamp ofs, ev_tstamp ival,
820         ev_tstamp function(ev_periodic *w, ev_tstamp now) res)
821 {
822     ev_init(w, cb);
823     ev_periodic_set(w, ofs, ival, res);
824 }
825 void ev_signal_init(ev_signal* w, void function(ev_loop_t*, ev_signal*, int) cb,
826         int signum)
827 {
828     ev_init(w, cb);
829     ev_signal_set(w, signum);
830 }
831 void ev_child_init(ev_child* w, void function(ev_loop_t*, ev_child*, int) cb,
832         int pid, int trace)
833 {
834     ev_init(w, cb);
835     ev_child_set(w, pid, trace);
836 }
837 version(EV_STAT_ENABLE) void ev_stat_init(ev_stat* w, void function(ev_loop_t*, ev_stat*, int) cb,
838         char* path, ev_tstamp interval)
839 {
840     ev_init(w, cb);
841     ev_stat_set(w, path, interval);
842 }
843 void ev_idle_init(ev_idle* w, void function(ev_loop_t*, ev_idle*, int) cb)
844 {
845     ev_init(w, cb);
846     ev_idle_set(w);
847 }
848 void ev_prepare_init(ev_prepare* w,
849         void function(ev_loop_t*, ev_prepare*, int) cb)
850 {
851     ev_init(w, cb);
852     ev_prepare_set(w);
853 }
854 void ev_check_init(ev_check* w, void function(ev_loop_t*, ev_check*, int) cb)
855 {
856     ev_init(w, cb);
857     ev_check_set(w);
858 }
859 void ev_embed_init(ev_embed* w, void function(ev_loop_t*, ev_embed*, int) cb,
860         ev_loop_t* other)
861 {
862     ev_init(w, cb);
863     ev_embed_set(w, other);
864 }
865 void ev_fork_init(ev_fork* w, void function(ev_loop_t*, ev_fork*, int) cb)
866 {
867     ev_init(w, cb);
868     ev_fork_set(w);
869 }
870 version(LIBEV4)
871 {
872     version(EV_CLEANUP_ENABLE)
873     {
874         void ev_cleanup_init(ev_cleanup* w, void function(ev_loop_t*, ev_cleanup*, int) cb)
875         {
876             ev_init(w, cb);
877             ev_cleanup_set(w);
878         }
879     }
880 }
881 void ev_async_init(ev_async* w, void function(ev_loop_t*, ev_async*, int) cb)
882 {
883     ev_init(w, cb);
884     ev_async_set(w);
885 }
886 bool ev_is_pending(TYPE)(TYPE* w)
887 {
888     return cast (bool) w.pending;
889 }
890 bool ev_is_active(TYPE)(TYPE* w)
891 {
892     return cast (bool) w.active;
893 }
894 void function(ev_loop_t*, TYPE*, int) ev_cb(TYPE)(TYPE* w)
895 {
896     return w.cb;
897 }
898 
899 static if(EV_MINPRI == EV_MAXPRI)
900 {
901     int ev_priority(TYPE)(TYPE* w)
902     {
903         return EV_MINPRI;
904     }
905     void ev_set_priority(TYPE)(TYPE* w, int pri)
906     {
907     }
908 }
909 else
910 {
911     int ev_priority(TYPE)(TYPE* w)
912     {
913         return w.priority;
914     }
915     void ev_set_priority(TYPE)(TYPE* w, int pri)
916     {
917         static if(__traits(compiles, w.priority))
918             w.priority = pri;
919     }
920 }
921 ev_tstamp ev_periodic_at(ev_watcher_time* ev)
922 {
923     return ev.at;
924 }
925 
926 void ev_set_cb(TYPE)(TYPE* w,
927         void function(ev_loop_t*, TYPE*, int) cb)
928 {
929     w.cb = cb;
930 }
931 
932 /* feeds an event into a watcher as if the event actually occured */
933 /* accepts any ev_watcher type */
934 void ev_feed_event     (/*mixin(EV_P_)*/ ev_loop_t* loop, void *w, int revents);
935 void ev_feed_fd_event  (/*mixin(EV_P_)*/ ev_loop_t* loop, int fd, int revents);
936 version(EV_SIGNAL_ENABLE)
937 {
938     version(LIBEV4)
939     {
940         void ev_feed_signal    (int signum);
941     }
942     void ev_feed_signal_event (/*mixin(EV_P_)*/ ev_loop_t* loop, int signum);
943 }
944 void ev_invoke         (/*mixin(EV_P_)*/ ev_loop_t* loop, void *w, int revents);
945 int  ev_clear_pending  (/*mixin(EV_P_)*/ ev_loop_t* loop, void *w);
946 
947 void ev_io_start       (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_io *w);
948 void ev_io_stop        (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_io *w);
949 
950 void ev_timer_start    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_timer *w);
951 void ev_timer_stop     (/*mixin(EV_P_)*/ ev_loop_t* loop,ev_timer *w);
952 /* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */
953 void ev_timer_again    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_timer *w);
954 /* return remaining time */
955 ev_tstamp ev_timer_remaining (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_timer *w);
956 
957 version(EV_PERIODIC_ENABLE)
958 {
959     void ev_periodic_start (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_periodic *w);
960     void ev_periodic_stop  (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_periodic *w);
961     void ev_periodic_again (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_periodic *w);
962 }
963 
964 version(EV_SIGNAL_ENABLE)
965 {
966     /* only supported in the default loop */
967     void ev_signal_start   (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_signal *w);
968     void ev_signal_stop    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_signal *w);
969 }
970 version(EV_CHILD_ENABLE)
971 {
972     /* only supported in the default loop */
973     void ev_child_start    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_child *w);
974     void ev_child_stop     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_child *w);
975 }
976 version(EV_STAT_ENABLE)
977 {
978     void ev_stat_start     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_stat *w);
979     void ev_stat_stop      (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_stat *w);
980     void ev_stat_stat      (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_stat *w);
981 }
982 
983 version(EV_IDLE_ENABLE)
984 {
985     void ev_idle_start     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_idle *w);
986     void ev_idle_stop      (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_idle *w);
987 }
988 version(EV_PREPARE_ENABLE)
989 {
990     void ev_prepare_start  (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_prepare *w);
991     void ev_prepare_stop   (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_prepare *w);
992 }
993 version(EV_CHECK_ENABLE)
994 {
995     void ev_check_start    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_check *w);
996     void ev_check_stop     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_check *w);
997 }
998 version(EV_FORK_ENABLE)
999 {
1000     void ev_fork_start     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_fork *w);
1001     void ev_fork_stop      (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_fork *w);
1002 }
1003 
1004 version(LIBEV4)
1005 {
1006     version(EV_CLEANUP_ENABLE)
1007     {
1008         void ev_cleanup_start  (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_cleanup *w);
1009         void ev_cleanup_stop   (/*mixin(EV_P_)*/ ev_loop_t* loop,ev_cleanup *w);
1010     }
1011 }
1012 
1013 version(EV_EMBED_ENABLE)
1014 {
1015     /* only supported when loop to be embedded is in fact embeddable */
1016     void ev_embed_start    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_embed *w);
1017     void ev_embed_stop     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_embed *w);
1018     void ev_embed_sweep    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_embed *w);
1019 }
1020 
1021 version(EV_ASYNC_ENABLE)
1022 {
1023     void ev_async_start    (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_async *w);
1024     void ev_async_stop     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_async *w);
1025     void ev_async_send     (/*mixin(EV_P_)*/ ev_loop_t* loop, ev_async *w);
1026 }
1027 
1028 version(LIBEV4)
1029 {
1030     version(LIBEV3_COMPAT)
1031     {
1032         alias EVRUN_NOWAIT EVLOOP_NONBLOCK; 
1033         alias EVRUN_ONCE EVLOOP_ONESHOT;
1034         alias EVBREAK_CANCEL EVUNLOOP_CANCEL;
1035         alias EVBREAK_ONE EVUNLOOP_ONE;
1036         alias EVBREAK_ALL EVUNLOOP_ALL;
1037         alias ev_run ev_loop;
1038         alias ev_break ev_unloop;
1039         alias ev_loop_destroy ev_default_destroy;
1040         alias ev_loop_fork ev_default_fork;
1041         version(ENABLE_ADDITIONAL_FEATURES)
1042         {
1043             alias ev_iteration ev_loop_count;
1044             alias ev_depth ev_loop_depth;
1045             alias ev_verify ev_loop_verify;
1046         }
1047     }
1048 }