X-Git-Url: https://git.llucax.com/software/libev.git/blobdiff_plain/4422091b9b8967efdcfea8f650321595a8d95a98..71b44ee4e9677f9ddc2b7f91f32654cfd1bd2f73:/ev.pod diff --git a/ev.pod b/ev.pod index cc478bd..6d8fe82 100644 --- a/ev.pod +++ b/ev.pod @@ -6,10 +6,56 @@ libev - a high performance full-featured event loop written in C #include +=head2 EXAMPLE PROGRAM + + #include + + ev_io stdin_watcher; + ev_timer timeout_watcher; + + /* called when data readable on stdin */ + static void + stdin_cb (EV_P_ struct ev_io *w, int revents) + { + /* puts ("stdin ready"); */ + ev_io_stop (EV_A_ w); /* just a syntax example */ + ev_unloop (EV_A_ EVUNLOOP_ALL); /* leave all loop calls */ + } + + static void + timeout_cb (EV_P_ struct ev_timer *w, int revents) + { + /* puts ("timeout"); */ + ev_unloop (EV_A_ EVUNLOOP_ONE); /* leave one loop call */ + } + + int + main (void) + { + struct ev_loop *loop = ev_default_loop (0); + + /* initialise an io watcher, then start it */ + ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); + ev_io_start (loop, &stdin_watcher); + + /* simple non-repeating 5.5 second timeout */ + ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); + ev_timer_start (loop, &timeout_watcher); + + /* loop till timeout or data ready */ + ev_loop (loop, 0); + + return 0; + } + =head1 DESCRIPTION +The newest version of this document is also available as a html-formatted +web page you might find easier to navigate when reading it for the first +time: L. + Libev is an event loop: you register interest in certain events (such as a -file descriptor being readable or a timeout occuring), and it will manage +file descriptor being readable or a timeout occurring), and it will manage these event sources and provide your program with events. To do this, it must take more or less complete control over your process @@ -21,35 +67,42 @@ watchers>, which are relatively small C structures you initialise with the details of the event, and then hand it over to libev by I the watcher. -=head1 FEATURES - -Libev supports select, poll, the linux-specific epoll and the bsd-specific -kqueue mechanisms for file descriptor events, relative timers, absolute -timers with customised rescheduling, signal events, process status change -events (related to SIGCHLD), and event watchers dealing with the event -loop mechanism itself (idle, prepare and check watchers). It also is quite -fast (see this L comparing -it to libevent for example). +=head2 FEATURES + +Libev supports C which have a high +overhead for the actual polling but can deliver many events at once. + +By setting a higher I you allow libev to spend more +time collecting I/O events, so you can handle more events per iteration, +at the cost of increasing latency. Timeouts (both C and +C) will be not affected. Setting this to a non-null value will +introduce an additional C call into most loop iterations. + +Likewise, by setting a higher I you allow libev +to spend more time collecting timeouts, at the expense of increased +latency (the watcher callback will be called later). C watchers +will not be affected. Setting this to a non-null value will not introduce +any overhead in libev. + +Many (busy) programs can usually benefit by setting the io collect +interval to a value near C<0.1> or so, which is often enough for +interactive servers (of course not for games), likewise for timeouts. It +usually doesn't make much sense to set it to a lower value than C<0.01>, +as this approsaches the timing granularity of most systems. =back @@ -567,6 +769,15 @@ many watchers as they want, and all of them will be taken into account (for example, a C watcher might start an idle watcher to keep C from blocking). +=item C + +The embedded event loop specified in the C watcher needs attention. + +=item C + +The event loop has been resumed in the child process after fork (see +C). + =item C An unspecified error has occured, the watcher has been stopped. This might @@ -647,10 +858,11 @@ it. Returns a true value iff the watcher is pending, (i.e. it has outstanding events but its callback has not yet been invoked). As long as a watcher is pending (but not active) you must not call an init function on it (but -C is safe) and you must make sure the watcher is available to -libev (e.g. you cnanot C it). +C is safe), you must not change its priority, and you must +make sure the watcher is available to libev (e.g. you cannot C +it). -=item callback = ev_cb (ev_TYPE *watcher) +=item callback ev_cb (ev_TYPE *watcher) Returns the callback currently set on the watcher. @@ -659,6 +871,46 @@ Returns the callback currently set on the watcher. Change the callback. You can change the callback at virtually any time (modulo threads). +=item ev_set_priority (ev_TYPE *watcher, priority) + +=item int ev_priority (ev_TYPE *watcher) + +Set and query the priority of the watcher. The priority is a small +integer between C (default: C<2>) and C +(default: C<-2>). Pending watchers with higher priority will be invoked +before watchers with lower priority, but priority will not keep watchers +from being executed (except for C watchers). + +This means that priorities are I used for ordering callback +invocation after new events have been received. This is useful, for +example, to reduce latency after idling, or more often, to bind two +watchers on the same event and make sure one is called first. + +If you need to suppress invocation when higher priority events are pending +you need to look at C watchers, which provide this functionality. + +You I change the priority of a watcher as long as it is active or +pending. + +The default priority used by watchers when no priority has been set is +always C<0>, which is supposed to not be too high and not be too low :). + +Setting a priority outside the range of C to C is +fine, as long as you do not mind that the priority value you query might +or might not have been adjusted to be within valid range. + +=item ev_invoke (loop, ev_TYPE *watcher, int revents) + +Invoke the C with the given C and C. Neither +C nor C need to be valid as long as the watcher callback +can deal with that fact. + +=item int ev_clear_pending (loop, ev_TYPE *watcher) + +If the watcher is pending, this function returns clears its pending status +and returns its C bitset (as if its callback was invoked). If the +watcher isn't pending it does nothing and returns C<0>. + =back @@ -688,8 +940,37 @@ can cast it back to your own type: ... } -More interesting and less C-conformant ways of catsing your callback type -have been omitted.... +More interesting and less C-conformant ways of casting your callback type +instead have been omitted. + +Another common scenario is having some data structure with multiple +watchers: + + struct my_biggy + { + int some_data; + ev_timer t1; + ev_timer t2; + } + +In this case getting the pointer to C is a bit more complicated, +you need to use C: + + #include + + static void + t1_cb (EV_P_ struct ev_timer *w, int revents) + { + struct my_biggy big = (struct my_biggy * + (((char *)w) - offsetof (struct my_biggy, t1)); + } + + static void + t2_cb (EV_P_ struct ev_timer *w, int revents) + { + struct my_biggy big = (struct my_biggy * + (((char *)w) - offsetof (struct my_biggy, t2)); + } =head1 WATCHER TYPES @@ -723,12 +1004,6 @@ fd as you want (as long as you don't confuse yourself). Setting all file descriptors to non-blocking mode is also usually a good idea (but not required if you know what you are doing). -You have to be careful with dup'ed file descriptors, though. Some backends -(the linux epoll backend is a notable example) cannot handle dup'ed file -descriptors correctly if you register interest in two or more fds pointing -to the same underlying file/socket/etc. description (that is, they share -the same underlying "file open"). - If you must do this, then force the use of a known-to-be-good backend (at the time of this writing, this includes only C and C). @@ -744,10 +1019,56 @@ C is far preferable to a program hanging until some data arrives. If you cannot run the fd in non-blocking mode (for example you should not play around with an Xlib connection), then you have to seperately re-test -wether a file descriptor is really ready with a known-to-be good interface +whether a file descriptor is really ready with a known-to-be good interface such as poll (fortunately in our Xlib example, Xlib already does this on its own, so its quite safe to use). +=head3 The special problem of disappearing file descriptors + +Some backends (e.g. kqueue, epoll) need to be told about closing a file +descriptor (either by calling C explicitly or by any other means, +such as C). The reason is that you register interest in some file +descriptor, but when it goes away, the operating system will silently drop +this interest. If another file descriptor with the same number then is +registered with libev, there is no efficient way to see that this is, in +fact, a different file descriptor. + +To avoid having to explicitly tell libev about such cases, libev follows +the following policy: Each time C is being called, libev +will assume that this is potentially a new file descriptor, otherwise +it is assumed that the file descriptor stays the same. That means that +you I to call C (or C) when you change the +descriptor even if the file descriptor number itself did not change. + +This is how one would do it normally anyway, the important point is that +the libev application should not optimise around libev but should leave +optimisations to libev. + +=head3 The special problem of dup'ed file descriptors + +Some backends (e.g. epoll), cannot register events for file descriptors, +but only events for the underlying file descriptions. That means when you +have C'ed file descriptors or weirder constellations, and register +events for them, only one file descriptor might actually receive events. + +There is no workaround possible except not registering events +for potentially C'ed file descriptors, or to resort to +C or C. + +=head3 The special problem of fork + +Some backends (epoll, kqueue) do not support C at all or exhibit +useless behaviour. Libev fully supports fork, but needs to be told about +it in the child. + +To support fork in your programs, you either have to call +C or C after a fork in the child, +enable C, or resort to C or +C. + + +=head3 Watcher-Specific Functions + =over 4 =item ev_io_init (ev_io *, callback, int fd, int events) @@ -768,9 +1089,11 @@ The events being watched. =back -Example: call C when STDIN_FILENO has become, well +=head3 Examples + +Example: Call C when STDIN_FILENO has become, well readable, but only once. Since it is likely line-buffered, you could -attempt to read a whole line in the callback: +attempt to read a whole line in the callback. static void stdin_readable_cb (struct ev_loop *loop, struct ev_io *w, int revents) @@ -810,6 +1133,8 @@ The callback is guarenteed to be invoked only when its timeout has passed, but if multiple timers become ready during the same loop iteration then order of execution is undefined. +=head3 Watcher-Specific Functions and Data Members + =over 4 =item ev_timer_init (ev_timer *, callback, ev_tstamp after, ev_tstamp repeat) @@ -832,23 +1157,25 @@ timer will not fire more than once per event loop iteration. This will act as if the timer timed out and restart it again if it is repeating. The exact semantics are: -If the timer is started but nonrepeating, stop it. +If the timer is pending, its pending status is cleared. + +If the timer is started but nonrepeating, stop it (as if it timed out). -If the timer is repeating, either start it if necessary (with the repeat -value), or reset the running timer to the repeat value. +If the timer is repeating, either start it if necessary (with the +C value), or reset the running timer to the C value. This sounds a bit complicated, but here is a useful and typical -example: Imagine you have a tcp connection and you want a so-called -idle timeout, that is, you want to be called when there have been, -say, 60 seconds of inactivity on the socket. The easiest way to do -this is to configure an C with C=C=C<60> and calling +example: Imagine you have a tcp connection and you want a so-called idle +timeout, that is, you want to be called when there have been, say, 60 +seconds of inactivity on the socket. The easiest way to do this is to +configure an C with a C value of C<60> and then call C each time you successfully read or write some data. If you go into an idle state where you do not expect data to travel on the -socket, you can stop the timer, and again will automatically restart it if -need be. +socket, you can C the timer, and C will +automatically restart it if need be. -You can also ignore the C value and C altogether -and only ever use the C value: +That means you can ignore the C value and C +altogether and only ever use the C value and C: ev_timer_init (timer, callback, 0., 5.); ev_timer_again (loop, timer); @@ -859,8 +1186,8 @@ and only ever use the C value: timer->again = 10.; ev_timer_again (loop, timer); -This is more efficient then stopping/starting the timer eahc time you want -to modify its timeout value. +This is more slightly efficient then stopping/starting the timer each time +you want to modify its timeout value. =item ev_tstamp repeat [read-write] @@ -870,7 +1197,9 @@ which is also when any modifications are taken into account. =back -Example: create a timer that fires after 60 seconds. +=head3 Examples + +Example: Create a timer that fires after 60 seconds. static void one_minute_cb (struct ev_loop *loop, struct ev_timer *w, int revents) @@ -882,7 +1211,7 @@ Example: create a timer that fires after 60 seconds. ev_timer_init (&mytimer, one_minute_cb, 60., 0.); ev_timer_start (loop, &mytimer); -Example: create a timeout timer that times out after 10 seconds of +Example: Create a timeout timer that times out after 10 seconds of inactivity. static void @@ -912,16 +1241,18 @@ to trigger "at" some specific point in time. For example, if you tell a periodic watcher to trigger in 10 seconds (by specifiying e.g. C) and then reset your system clock to the last year, then it will take a year to trigger the event (unlike an C, which would trigger -roughly 10 seconds later and of course not if you reset your system time -again). +roughly 10 seconds later). They can also be used to implement vastly more complex timers, such as -triggering an event on eahc midnight, local time. +triggering an event on each midnight, local time or other, complicated, +rules. As with timers, the callback is guarenteed to be invoked only when the time (C) has been passed, but if multiple periodic timers become ready during the same loop iteration then order of execution is undefined. +=head3 Watcher-Specific Functions and Data Members + =over 4 =item ev_periodic_init (ev_periodic *, callback, ev_tstamp at, ev_tstamp interval, reschedule_cb) @@ -933,18 +1264,18 @@ operation, and we will explain them from simplest to complex: =over 4 -=item * absolute timer (interval = reschedule_cb = 0) +=item * absolute timer (at = time, interval = reschedule_cb = 0) In this configuration the watcher triggers an event at the wallclock time C and doesn't repeat. It will not adjust when a time jump occurs, that is, if it is to be run at January 1st 2011 then it will run when the system time reaches or surpasses this time. -=item * non-repeating interval timer (interval > 0, reschedule_cb = 0) +=item * non-repeating interval timer (at = offset, interval > 0, reschedule_cb = 0) In this mode the watcher will always be scheduled to time out at the next -C time (for some integer N) and then repeat, regardless -of any time jumps. +C time (for some integer N, which can also be negative) +and then repeat, regardless of any time jumps. This can be used to create timers that do not drift with respect to system time: @@ -960,7 +1291,11 @@ Another way to think about it (for the mathematically inclined) is that C will try to run the callback in this mode at the next possible time where C