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