--- libev/ev.pod 2008/05/20 23:49:41 1.157 +++ libev/ev.pod 2010/10/24 20:05:43 1.327 @@ -4,70 +4,84 @@ =head1 SYNOPSIS - #include + #include =head2 EXAMPLE PROGRAM - // a single header file is required - #include + // a single header file is required + #include - // every watcher type has its own typedef'd struct - // with the name ev_ - ev_io stdin_watcher; - ev_timer timeout_watcher; - - // all watcher callbacks have a similar signature - // this callback is called when data is readable on stdin - static void - stdin_cb (EV_P_ struct ev_io *w, int revents) - { - puts ("stdin ready"); - // for one-shot events, one must manually stop the watcher - // with its corresponding stop function. - ev_io_stop (EV_A_ w); - - // this causes all nested ev_loop's to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ALL); - } - - // another callback, this time for a time-out - static void - timeout_cb (EV_P_ struct ev_timer *w, int revents) - { - puts ("timeout"); - // this causes the innermost ev_loop to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ONE); - } - - int - main (void) - { - // use the default event loop unless you have special needs - struct ev_loop *loop = ev_default_loop (0); - - // initialise an io watcher, then start it - // this one will watch for stdin to become readable - ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); - ev_io_start (loop, &stdin_watcher); - - // initialise a timer watcher, then start it - // simple non-repeating 5.5 second timeout - ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); - ev_timer_start (loop, &timeout_watcher); - - // now wait for events to arrive - ev_loop (loop, 0); - - // unloop was called, so exit - return 0; - } + #include // for puts -=head1 DESCRIPTION + // every watcher type has its own typedef'd struct + // with the name ev_TYPE + ev_io stdin_watcher; + ev_timer timeout_watcher; + + // all watcher callbacks have a similar signature + // this callback is called when data is readable on stdin + static void + stdin_cb (EV_P_ ev_io *w, int revents) + { + puts ("stdin ready"); + // for one-shot events, one must manually stop the watcher + // with its corresponding stop function. + ev_io_stop (EV_A_ w); + + // this causes all nested ev_run's to stop iterating + ev_break (EV_A_ EVBREAK_ALL); + } + + // another callback, this time for a time-out + static void + timeout_cb (EV_P_ ev_timer *w, int revents) + { + puts ("timeout"); + // this causes the innermost ev_run to stop iterating + ev_break (EV_A_ EVBREAK_ONE); + } + + int + main (void) + { + // use the default event loop unless you have special needs + struct ev_loop *loop = EV_DEFAULT; + + // initialise an io watcher, then start it + // this one will watch for stdin to become readable + ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); + ev_io_start (loop, &stdin_watcher); + + // initialise a timer watcher, then start it + // simple non-repeating 5.5 second timeout + ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); + ev_timer_start (loop, &timeout_watcher); + + // now wait for events to arrive + ev_run (loop, 0); + + // unloop was called, so exit + return 0; + } + +=head1 ABOUT THIS DOCUMENT + +This document documents the libev software package. The newest version of this document is also available as an html-formatted web page you might find easier to navigate when reading it for the first time: L. +While this document tries to be as complete as possible in documenting +libev, its usage and the rationale behind its design, it is not a tutorial +on event-based programming, nor will it introduce event-based programming +with libev. + +Familiarity with event based programming techniques in general is assumed +throughout this document. + +=head1 ABOUT LIBEV + Libev is an event loop: you register interest in certain events (such as a file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events. @@ -86,13 +100,14 @@ Libev supports C (files, many character devices...). While stopping, setting and starting an I/O watcher in the same iteration -will result in some caching, there is still a syscall per such incident -(because the fd could point to a different file description now), so its -best to avoid that. Also, C'ed file descriptors might not work -very well if you register events for both fds. - -Please note that epoll sometimes generates spurious notifications, so you -need to use non-blocking I/O or other means to avoid blocking when no data -(or space) is available. +will result in some caching, there is still a system call per such +incident (because the same I could point to a different +I now), so its best to avoid that. Also, C'ed +file descriptors might not work very well if you register events for both +file descriptors. Best performance from this backend is achieved by not unregistering all -watchers for a file descriptor until it has been closed, if possible, i.e. -keep at least one watcher active per fd at all times. +watchers for a file descriptor until it has been closed, if possible, +i.e. keep at least one watcher active per fd at all times. Stopping and +starting a watcher (without re-setting it) also usually doesn't cause +extra overhead. A fork can both result in spurious notifications as well +as in libev having to destroy and recreate the epoll object, which can +take considerable time and thus should be avoided. + +All this means that, in practice, C can be as fast or +faster than epoll for maybe up to a hundred file descriptors, depending on +the usage. So sad. -While nominally embeddeble in other event loops, this feature is broken in +While nominally embeddable in other event loops, this feature is broken in all kernel versions tested so far. +This backend maps C and C in the same way as +C. + =item C (value 8, most BSD clones) Kqueue deserves special mention, as at the time of this writing, it was broken on all BSDs except NetBSD (usually it doesn't work reliably with anything but sockets and pipes, except on Darwin, where of course -it's completely useless). For this reason it's not being "autodetected" -unless you explicitly specify it explicitly in the flags (i.e. using +it's completely useless). Unlike epoll, however, whose brokenness +is by design, these kqueue bugs can (and eventually will) be fixed +without API changes to existing programs. For this reason it's not being +"auto-detected" unless you explicitly specify it in the flags (i.e. using C) or libev was compiled on a known-to-be-good (-enough) system like NetBSD. @@ -393,9 +517,10 @@ It scales in the same way as the epoll backend, but the interface to the kernel is more efficient (which says nothing about its actual speed, of course). While stopping, setting and starting an I/O watcher does never -cause an extra syscall as with C, it still adds up to -two event changes per incident, support for C is very bad and it -drops fds silently in similarly hard-to-detect cases. +cause an extra system call as with C, it still adds up to +two event changes per incident. Support for C is very bad (but +sane, unlike epoll) and it drops fds silently in similarly hard-to-detect +cases This backend usually performs well under most conditions. @@ -403,8 +528,12 @@ everywhere, so you might need to test for this. And since it is broken almost everywhere, you should only use it when you have a lot of sockets (for which it usually works), by embedding it into another event loop -(e.g. C or C) and using it only for -sockets. +(e.g. C or C (but C is of course +also broken on OS X)) and, did I mention it, using it only for sockets. + +This backend maps C into an C kevent with +C, and C into an C kevent with +C. =item C (value 16, Solaris 8) @@ -418,7 +547,7 @@ This uses the Solaris 10 event port mechanism. As with everything on Solaris, it's really slow, but it still scales very well (O(active_fds)). -Please note that solaris event ports can deliver a lot of spurious +Please note that Solaris event ports can deliver a lot of spurious notifications, so you need to use non-blocking I/O or other means to avoid blocking when no data (or space) is available. @@ -427,9 +556,13 @@ descriptors a "slow" C or C backend might perform better. -On the positive side, ignoring the spurious readiness notifications, this -backend actually performed to specification in all tests and is fully -embeddable, which is a rare feat among the OS-specific backends. +On the positive side, with the exception of the spurious readiness +notifications, this backend actually performed fully to specification +in all tests and is fully embeddable, which is a rare feat among the +OS-specific backends (I vastly prefer correctness over speed hacks). + +This backend maps C and C in the same way as +C. =item C @@ -441,105 +574,108 @@ =back -If one or more of these are ored into the flags value, then only these -backends will be tried (in the reverse order as listed here). If none are -specified, all backends in C will be tried. - -The most typical usage is like this: - - if (!ev_default_loop (0)) - fatal ("could not initialise libev, bad $LIBEV_FLAGS in environment?"); - -Restrict libev to the select and poll backends, and do not allow -environment settings to be taken into account: - - ev_default_loop (EVBACKEND_POLL | EVBACKEND_SELECT | EVFLAG_NOENV); - -Use whatever libev has to offer, but make sure that kqueue is used if -available (warning, breaks stuff, best use only with your own private -event loop and only if you know the OS supports your types of fds): - - ev_default_loop (ev_recommended_backends () | EVBACKEND_KQUEUE); - -=item struct ev_loop *ev_loop_new (unsigned int flags) +If one or more of the backend flags are or'ed into the flags value, +then only these backends will be tried (in the reverse order as listed +here). If none are specified, all backends in C will be tried. -Similar to C, but always creates a new event loop that is -always distinct from the default loop. Unlike the default loop, it cannot -handle signal and child watchers, and attempts to do so will be greeted by -undefined behaviour (or a failed assertion if assertions are enabled). +Example: Try to create a event loop that uses epoll and nothing else. -Note that this function I thread-safe, and the recommended way to use -libev with threads is indeed to create one loop per thread, and using the -default loop in the "main" or "initial" thread. + struct ev_loop *epoller = ev_loop_new (EVBACKEND_EPOLL | EVFLAG_NOENV); + if (!epoller) + fatal ("no epoll found here, maybe it hides under your chair"); -Example: Try to create a event loop that uses epoll and nothing else. +Example: Use whatever libev has to offer, but make sure that kqueue is +used if available. - struct ev_loop *epoller = ev_loop_new (EVBACKEND_EPOLL | EVFLAG_NOENV); - if (!epoller) - fatal ("no epoll found here, maybe it hides under your chair"); + struct ev_loop *loop = ev_loop_new (ev_recommended_backends () | EVBACKEND_KQUEUE); -=item ev_default_destroy () +=item ev_loop_destroy (loop) -Destroys the default loop again (frees all memory and kernel state +Destroys an event loop object (frees all memory and kernel state etc.). None of the active event watchers will be stopped in the normal sense, so e.g. C might still return true. It is your -responsibility to either stop all watchers cleanly yoursef I +responsibility to either stop all watchers cleanly yourself I calling this function, or cope with the fact afterwards (which is usually the easiest thing, you can just ignore the watchers and/or C them for example). -Note that certain global state, such as signal state, will not be freed by -this function, and related watchers (such as signal and child watchers) -would need to be stopped manually. - -In general it is not advisable to call this function except in the -rare occasion where you really need to free e.g. the signal handling -pipe fds. If you need dynamically allocated loops it is better to use -C and C). - -=item ev_loop_destroy (loop) +Note that certain global state, such as signal state (and installed signal +handlers), will not be freed by this function, and related watchers (such +as signal and child watchers) would need to be stopped manually. + +This function is normally used on loop objects allocated by +C, but it can also be used on the default loop returned by +C, in which case it is not thread-safe. + +Note that it is not advisable to call this function on the default loop +except in the rare occasion where you really need to free it's resources. +If you need dynamically allocated loops it is better to use C +and C. -Like C, but destroys an event loop created by an -earlier call to C. - -=item ev_default_fork () +=item ev_loop_fork (loop) -This function sets a flag that causes subsequent C iterations -to reinitialise the kernel state for backends that have one. Despite the +This function sets a flag that causes subsequent C iterations to +reinitialise the kernel state for backends that have one. Despite the name, you can call it anytime, but it makes most sense after forking, in -the child process (or both child and parent, but that again makes little -sense). You I call it in the child before using any of the libev -functions, and it will only take effect at the next C iteration. +the child process. You I call it (or use C) in the +child before resuming or calling C. + +Again, you I to call it on I loop that you want to re-use after +a fork, I. This is +because some kernel interfaces *cough* I *cough* do funny things +during fork. On the other hand, you only need to call this function in the child -process if and only if you want to use the event library in the child. If -you just fork+exec, you don't have to call it at all. +process if and only if you want to use the event loop in the child. If +you just fork+exec or create a new loop in the child, you don't have to +call it at all (in fact, C is so badly broken that it makes a +difference, but libev will usually detect this case on its own and do a +costly reset of the backend). The function itself is quite fast and it's usually not a problem to call -it just in case after a fork. To make this easy, the function will fit in -quite nicely into a call to C: +it just in case after a fork. - pthread_atfork (0, 0, ev_default_fork); +Example: Automate calling C on the default loop when +using pthreads. -=item ev_loop_fork (loop) + static void + post_fork_child (void) + { + ev_loop_fork (EV_DEFAULT); + } -Like C, but acts on an event loop created by -C. Yes, you have to call this on every allocated event loop -after fork, and how you do this is entirely your own problem. + ... + pthread_atfork (0, 0, post_fork_child); =item int ev_is_default_loop (loop) -Returns true when the given loop actually is the default loop, false otherwise. +Returns true when the given loop is, in fact, the default loop, and false +otherwise. -=item unsigned int ev_loop_count (loop) +=item unsigned int ev_iteration (loop) -Returns the count of loop iterations for the loop, which is identical to -the number of times libev did poll for new events. It starts at C<0> and -happily wraps around with enough iterations. +Returns the current iteration count for the event loop, which is identical +to the number of times libev did poll for new events. It starts at C<0> +and happily wraps around with enough iterations. This value can sometimes be useful as a generation counter of sorts (it "ticks" the number of loop iterations), as it roughly corresponds with -C and C calls. +C and C calls - and is incremented between the +prepare and check phases. + +=item unsigned int ev_depth (loop) + +Returns the number of times C was entered minus the number of +times C was exited, in other words, the recursion depth. + +Outside C, this number is zero. In a callback, this number is +C<1>, unless C was invoked recursively (or from another thread), +in which case it is higher. + +Leaving C abnormally (setjmp/longjmp, cancelling the thread +etc.), doesn't count as "exit" - consider this as a hint to avoid such +ungentleman-like behaviour unless it's really convenient. =item unsigned int ev_backend (loop) @@ -554,76 +690,136 @@ time used for relative timers. You can treat it as the timestamp of the event occurring (or more correctly, libev finding out about it). -=item ev_loop (loop, int flags) +=item ev_now_update (loop) + +Establishes the current time by querying the kernel, updating the time +returned by C in the progress. This is a costly operation and +is usually done automatically within C. + +This function is rarely useful, but when some event callback runs for a +very long time without entering the event loop, updating libev's idea of +the current time is a good idea. + +See also L in the C section. + +=item ev_suspend (loop) + +=item ev_resume (loop) + +These two functions suspend and resume an event loop, for use when the +loop is not used for a while and timeouts should not be processed. + +A typical use case would be an interactive program such as a game: When +the user presses C<^Z> to suspend the game and resumes it an hour later it +would be best to handle timeouts as if no time had actually passed while +the program was suspended. This can be achieved by calling C +in your C handler, sending yourself a C and calling +C directly afterwards to resume timer processing. + +Effectively, all C watchers will be delayed by the time spend +between C and C, and all C watchers +will be rescheduled (that is, they will lose any events that would have +occurred while suspended). + +After calling C you B call I function on the +given loop other than C, and you B call C +without a previous call to C. + +Calling C/C has the side effect of updating the +event loop time (see C). + +=item ev_run (loop, int flags) Finally, this is it, the event handler. This function usually is called -after you initialised all your watchers and you want to start handling -events. +after you have initialised all your watchers and you want to start +handling events. It will ask the operating system for any new events, call +the watcher callbacks, an then repeat the whole process indefinitely: This +is why event loops are called I. -If the flags argument is specified as C<0>, it will not return until -either no event watchers are active anymore or C was called. +If the flags argument is specified as C<0>, it will keep handling events +until either no event watchers are active anymore or C was +called. -Please note that an explicit C is usually better than +Please note that an explicit C is usually better than relying on all watchers to be stopped when deciding when a program has -finished (especially in interactive programs), but having a program that -automatically loops as long as it has to and no longer by virtue of -relying on its watchers stopping correctly is a thing of beauty. - -A flags value of C will look for new events, will handle -those events and any outstanding ones, but will not block your process in -case there are no events and will return after one iteration of the loop. - -A flags value of C will look for new events (waiting if -neccessary) and will handle those and any outstanding ones. It will block -your process until at least one new event arrives, and will return after -one iteration of the loop. This is useful if you are waiting for some -external event in conjunction with something not expressible using other -libev watchers. However, a pair of C/C watchers is +finished (especially in interactive programs), but having a program +that automatically loops as long as it has to and no longer by virtue +of relying on its watchers stopping correctly, that is truly a thing of +beauty. + +A flags value of C will look for new events, will handle +those events and any already outstanding ones, but will not wait and +block your process in case there are no events and will return after one +iteration of the loop. This is sometimes useful to poll and handle new +events while doing lengthy calculations, to keep the program responsive. + +A flags value of C will look for new events (waiting if +necessary) and will handle those and any already outstanding ones. It +will block your process until at least one new event arrives (which could +be an event internal to libev itself, so there is no guarantee that a +user-registered callback will be called), and will return after one +iteration of the loop. + +This is useful if you are waiting for some external event in conjunction +with something not expressible using other libev watchers (i.e. "roll your +own C"). However, a pair of C/C watchers is usually a better approach for this kind of thing. -Here are the gory details of what C does: +Here are the gory details of what C does: + - Increment loop depth. + - Reset the ev_break status. - Before the first iteration, call any pending watchers. - * If EVFLAG_FORKCHECK was used, check for a fork. - - If a fork was detected, queue and call all fork watchers. + LOOP: + - If EVFLAG_FORKCHECK was used, check for a fork. + - If a fork was detected (by any means), queue and call all fork watchers. - Queue and call all prepare watchers. - - If we have been forked, recreate the kernel state. + - If ev_break was called, goto FINISH. + - If we have been forked, detach and recreate the kernel state + as to not disturb the other process. - Update the kernel state with all outstanding changes. - - Update the "event loop time". + - Update the "event loop time" (ev_now ()). - Calculate for how long to sleep or block, if at all - (active idle watchers, EVLOOP_NONBLOCK or not having + (active idle watchers, EVRUN_NOWAIT or not having any active watchers at all will result in not sleeping). - Sleep if the I/O and timer collect interval say so. + - Increment loop iteration counter. - Block the process, waiting for any events. - Queue all outstanding I/O (fd) events. - - Update the "event loop time" and do time jump handling. - - Queue all outstanding timers. - - Queue all outstanding periodics. - - If no events are pending now, queue all idle watchers. + - Update the "event loop time" (ev_now ()), and do time jump adjustments. + - Queue all expired timers. + - Queue all expired periodics. + - Queue all idle watchers with priority higher than that of pending events. - Queue all check watchers. - Call all queued watchers in reverse order (i.e. check watchers first). Signals and child watchers are implemented as I/O watchers, and will be handled here by queueing them when their watcher gets executed. - - If ev_unloop has been called, or EVLOOP_ONESHOT or EVLOOP_NONBLOCK - were used, or there are no active watchers, return, otherwise - continue with step *. + - If ev_break has been called, or EVRUN_ONCE or EVRUN_NOWAIT + were used, or there are no active watchers, goto FINISH, otherwise + continue with step LOOP. + FINISH: + - Reset the ev_break status iff it was EVBREAK_ONE. + - Decrement the loop depth. + - Return. Example: Queue some jobs and then loop until no events are outstanding anymore. ... queue jobs here, make sure they register event watchers as long ... as they still have work to do (even an idle watcher will do..) - ev_loop (my_loop, 0); - ... jobs done. yeah! + ev_run (my_loop, 0); + ... jobs done or somebody called unloop. yeah! -=item ev_unloop (loop, how) +=item ev_break (loop, how) -Can be used to make a call to C return early (but only after it +Can be used to make a call to C return early (but only after it has processed all outstanding events). The C argument must be either -C, which will make the innermost C call return, or -C, which will make all nested C calls return. +C, which will make the innermost C call return, or +C, which will make all nested C calls return. -This "unloop state" will be cleared when entering C again. +This "unloop state" will be cleared when entering C again. + +It is safe to call C from outside any C calls. ##TODO## =item ev_ref (loop) @@ -631,45 +827,53 @@ Ref/unref can be used to add or remove a reference count on the event loop: Every watcher keeps one reference, and as long as the reference -count is nonzero, C will not return on its own. If you have -a watcher you never unregister that should not keep C from -returning, ev_unref() after starting, and ev_ref() before stopping it. For -example, libev itself uses this for its internal signal pipe: It is not -visible to the libev user and should not keep C from exiting if -no event watchers registered by it are active. It is also an excellent -way to do this for generic recurring timers or from within third-party -libraries. Just remember to I and I -(but only if the watcher wasn't active before, or was active before, -respectively). +count is nonzero, C will not return on its own. + +This is useful when you have a watcher that you never intend to +unregister, but that nevertheless should not keep C from +returning. In such a case, call C after starting, and C +before stopping it. + +As an example, libev itself uses this for its internal signal pipe: It +is not visible to the libev user and should not keep C from +exiting if no event watchers registered by it are active. It is also an +excellent way to do this for generic recurring timers or from within +third-party libraries. Just remember to I and I (but only if the watcher wasn't active before, or was active +before, respectively. Note also that libev might stop watchers itself +(e.g. non-repeating timers) in which case you have to C +in the callback). -Example: Create a signal watcher, but keep it from keeping C +Example: Create a signal watcher, but keep it from keeping C running when nothing else is active. - struct ev_signal exitsig; - ev_signal_init (&exitsig, sig_cb, SIGINT); - ev_signal_start (loop, &exitsig); - evf_unref (loop); + ev_signal exitsig; + ev_signal_init (&exitsig, sig_cb, SIGINT); + ev_signal_start (loop, &exitsig); + evf_unref (loop); Example: For some weird reason, unregister the above signal handler again. - ev_ref (loop); - ev_signal_stop (loop, &exitsig); + ev_ref (loop); + ev_signal_stop (loop, &exitsig); =item ev_set_io_collect_interval (loop, ev_tstamp interval) =item ev_set_timeout_collect_interval (loop, ev_tstamp interval) These advanced functions influence the time that libev will spend waiting -for events. Both are by default C<0>, meaning that libev will try to -invoke timer/periodic callbacks and I/O callbacks with minimum latency. +for events. Both time intervals are by default C<0>, meaning that libev +will try to invoke timer/periodic callbacks and I/O callbacks with minimum +latency. Setting these to a higher value (the C I be >= C<0>) -allows libev to delay invocation of I/O and timer/periodic callbacks to -increase efficiency of loop iterations. - -The background is that sometimes your program runs just fast enough to -handle one (or very few) event(s) per loop iteration. While this makes -the program responsive, it also wastes a lot of CPU time to poll for new +allows libev to delay invocation of I/O and timer/periodic callbacks +to increase efficiency of loop iterations (or to increase power-saving +opportunities). + +The idea is that sometimes your program runs just fast enough to handle +one (or very few) event(s) per loop iteration. While this makes the +program responsive, it also wastes a lot of CPU time to poll for new events, especially with backends like C(2) backend. No attempt at autodetection will be done: if no +C is buggy + +All that's left is C actively limits the number of file +descriptors you can pass in to 1024 - your program suddenly crashes when +you use more. + +There is an undocumented "workaround" for this - defining +C<_DARWIN_UNLIMITED_SELECT>, which libev tries to use, so select I +work on OS/X. + +=head2 SOLARIS PROBLEMS AND WORKAROUNDS + +=head3 C reentrancy + +The default compile environment on Solaris is unfortunately so +thread-unsafe that you can't even use components/libraries compiled +without C<-D_REENTRANT> in a threaded program, which, of course, isn't +defined by default. A valid, if stupid, implementation choice. + +If you want to use libev in threaded environments you have to make sure +it's compiled with C<_REENTRANT> defined. + +=head3 Event port backend + +The scalable event interface for Solaris is called "event +ports". Unfortunately, this mechanism is very buggy in all major +releases. If you run into high CPU usage, your program freezes or you get +a large number of spurious wakeups, make sure you have all the relevant +and latest kernel patches applied. No, I don't know which ones, but there +are multiple ones to apply, and afterwards, event ports actually work +great. + +If you can't get it to work, you can try running the program by setting +the environment variable C to only allow C and +C works fine +with large bitsets on AIX, and AIX is dead anyway. + +=head2 WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS + +=head3 General issues Win32 doesn't support any of the standards (e.g. POSIX) that libev requires, and its I/O model is fundamentally incompatible with the POSIX model. Libev still offers limited functionality on this platform in the form of the C backend, and only supports socket descriptors. This only applies when using Win32 natively, not when using -e.g. cygwin. +e.g. cygwin. Actually, it only applies to the microsofts own compilers, +as every compielr comes with a slightly differently broken/incompatible +environment. Lifting these limitations would basically require the full -re-implementation of the I/O system. If you are into these kinds of -things, then note that glib does exactly that for you in a very portable -way (note also that glib is the slowest event library known to man). +re-implementation of the I/O system. If you are into this kind of thing, +then note that glib does exactly that for you in a very portable way (note +also that glib is the slowest event library known to man). There is no supported compilation method available on windows except embedding it into other applications. +Sensible signal handling is officially unsupported by Microsoft - libev +tries its best, but under most conditions, signals will simply not work. + +Not a libev limitation but worth mentioning: windows apparently doesn't +accept large writes: instead of resulting in a partial write, windows will +either accept everything or return C if the buffer is too large, +so make sure you only write small amounts into your sockets (less than a +megabyte seems safe, but this apparently depends on the amount of memory +available). + Due to the many, low, and arbitrary limits on the win32 platform and the abysmal performance of winsockets, using a large number of sockets is not recommended (and not reasonable). If your program needs to use more than a hundred or so sockets, then likely it needs to use a totally different implementation for windows, as libev offers the POSIX readiness notification model, which cannot be implemented efficiently on windows -(microsoft monopoly games). +(due to Microsoft monopoly games). -=over 4 +A typical way to use libev under windows is to embed it (see the embedding +section for details) and use the following F header file instead +of F: + + #define EV_STANDALONE /* keeps ev from requiring config.h */ + #define EV_SELECT_IS_WINSOCKET 1 /* configure libev for windows select */ + + #include "ev.h" + +And compile the following F file into your project (make sure +you do I compile the F or any other embedded source files!): -=item The winsocket select function + #include "evwrap.h" + #include "ev.c" -The winsocket C function -The configuration for a "naked" win32 using the microsoft runtime +The winsocket C