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 }