--- cvsroot/EV/EV.pm 2007/11/01 17:20:25 1.21 +++ cvsroot/EV/EV.pm 2007/11/12 07:58:52 1.37 @@ -12,20 +12,20 @@ warn "is called after 2s"; }; - my $w = EV::timer 2, 1, sub { - warn "is called roughly every 2s (repeat = 1)"; + my $w = EV::timer 2, 2, sub { + warn "is called roughly every 2s (repeat = 2)"; }; undef $w; # destroy event watcher again - my $w = EV::periodic 0, 60, sub { + my $w = EV::periodic 0, 60, 0, sub { warn "is called every minute, on the minute, exactly"; }; # IO my $w = EV::io *STDIN, EV::READ, sub { - my ($w, $revents) = @_; # all callbacks get the watcher object and event mask + my ($w, $revents) = @_; # all callbacks receive the watcher and event mask warn "stdin is readable, you entered: ", ; }; @@ -35,18 +35,15 @@ warn "sigquit received\n"; }; - my $w = EV::signal 3, sub { - warn "sigquit received (this is GNU/Linux, right?)\n"; - }; - # CHILD/PID STATUS CHANGES my $w = EV::child 666, sub { - my ($w, $revents, $status) = @_; + my ($w, $revents) = @_; + my $status = $w->rstatus; }; # MAINLOOP - EV::loop; # loop until EV::loop_done is called + EV::loop; # loop until EV::loop_done is called or all watchers stop EV::loop EV::LOOP_ONESHOT; # block until at least one event could be handled EV::loop EV::LOOP_NONBLOCK; # try to handle same events, but do not block @@ -62,7 +59,7 @@ use strict; BEGIN { - our $VERSION = '0.1'; + our $VERSION = '0.8'; use XSLoader; XSLoader::load "EV", $VERSION; } @@ -152,9 +149,13 @@ its name, e.g. EV::io has a non-starting variant EV::io_ns and so on. Please note that a watcher will automatically be stopped when the watcher -object is returned, so you I to keep the watcher objects returned by +object is destroyed, so you I to keep the watcher objects returned by the constructors. +Also, all methods changing some aspect of a watcher (->set, ->priority, +->fh and so on) automatically stop and start it again if it is active, +which means pending events get lost. + =head2 WATCHER TYPES Now lets move to the existing watcher types and asociated methods. @@ -182,12 +183,36 @@ Returns true if the watcher is active, false otherwise. +=item $current_data = $w->data + +=item $old_data = $w->data ($new_data) + +Queries a freely usable data scalar on the watcher and optionally changes +it. This is a way to associate custom data with a watcher: + + my $w = EV::timer 60, 0, sub { + warn $_[0]->data; + }; + $w->data ("print me!"); + =item $current_cb = $w->cb =item $old_cb = $w->cb ($new_cb) -Queries the callback on the watcher and optionally changes it. You cna do -this at any time. +Queries the callback on the watcher and optionally changes it. You can do +this at any time without the watcher restarting. + +=item $current_priority = $w->priority + +=item $old_priority = $w->priority ($new_priority) + +Queries the priority on the watcher and optionally changes it. Pending +watchers with higher priority will be invoked first. The valid range of +priorities lies between EV::MAXPRI (default 2) and EV::MINPRI (default +-2). If the priority is outside this range it will automatically be +normalised to the nearest valid priority. + +The default priority of any newly-created weatcher is 0. =item $w->trigger ($revents) @@ -269,40 +294,93 @@ on the timeout. -=item $w = EV::periodic $at, $interval, $callback +=item $w = EV::periodic $at, $interval, $reschedule_cb, $callback + +=item $w = EV::periodic_ns $at, $interval, $reschedule_cb, $callback + +Similar to EV::timer, but is not based on relative timeouts but on +absolute times. Apart from creating "simple" timers that trigger "at" the +specified time, it can also be used for non-drifting absolute timers and +more complex, cron-like, setups that are not adversely affected by time +jumps (i.e. when the system clock is changed by explicit date -s or other +means such as ntpd). It is also the most complex watcher type in EV. + +It has three distinct "modes": + +=over 4 + +=item * absolute timer ($interval = $reschedule_cb = 0) -=item $w = EV::periodic_ns $at, $interval, $callback +This time simply fires at the wallclock time C<$at> 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. -Similar to EV::timer, but the time is given as an absolute point in time -(C<$at>), plus an optional C<$interval>. +=item * non-repeating interval timer ($interval > 0, $reschedule_cb = 0) -If the C<$interval> is zero, then the callback will be called at the time -C<$at> if that is in the future, or as soon as possible if it is in the -past. It will not automatically repeat. +In this mode the watcher will always be scheduled to time out at the +next C<$at + N * $interval> time (for some integer N) and then repeat, +regardless of any time jumps. -If the C<$interval> is nonzero, then the watcher will always be scheduled -to time out at the next C<$at + N * $interval> time. +This can be used to create timers that do not drift with respect to system +time: -This can be used to schedule a callback to run at very regular intervals, -as long as the processing time is less then the interval (otherwise -obviously events will be skipped). + my $hourly = EV::periodic 0, 3600, 0, sub { print "once/hour\n" }; + +That doesn't mean there will always be 3600 seconds in between triggers, +but only that the the clalback will be called when the system time shows a +full hour (UTC). Another way to think about it (for the mathematically inclined) is that -EV::periodic will try to run the callback at the next possible time where -C<$time = $at (mod $interval)>, regardless of any time jumps. +EV::periodic will try to run the callback in this mode at the next +possible time where C<$time = $at (mod $interval)>, regardless of any time +jumps. + +=item * manual reschedule mode ($reschedule_cb = coderef) + +In this mode $interval and $at are both being ignored. Instead, each +time the periodic watcher gets scheduled, the reschedule callback +($reschedule_cb) will be called with the watcher as first, and the current +time as second argument. + +I. If you need to stop it, return 1e30 and stop it +afterwards. + +It must return the next time to trigger, based on the passed time value +(that is, the lowest time value larger than to the second argument). It +will usually be called just before the callback will be triggered, but +might be called at other times, too. + +This can be used to create very complex timers, such as a timer that +triggers on each midnight, local time (actually 24 hours after the last +midnight, to keep the example simple. If you know a way to do it correctly +in about the same space (without requiring elaborate modules), drop me a +note :): + + my $daily = EV::periodic 0, 0, sub { + my ($w, $now) = @_; + + use Time::Local (); + my (undef, undef, undef, $d, $m, $y) = localtime $now; + 86400 + Time::Local::timelocal 0, 0, 0, $d, $m, $y + }, sub { + print "it's midnight or likely shortly after, now\n"; + }; -This periodic timer is based on "wallclock time", that is, if the clock -changes (C, C etc.), then the timer will nevertheless run at -the specified time. This means it will never drift (it might jitter, but -it will not drift). +=back The C variant doesn't start (activate) the newly created watcher. -=item $w->set ($at, $interval) +=item $w->set ($at, $interval, $reschedule_cb) Reconfigures the watcher, see the constructor above for details. Can be at any time. +=item $w->again + +Simply stops and starts the watcher again. + =item $w = EV::signal $signal, $callback @@ -325,6 +403,13 @@ Reconfigures the watcher, see the constructor above for details. Can be at any time. +=item $current_signum = $w->signal + +=item $old_signum = $w->signal ($new_signal) + +Returns the previously set signal (always as a number not name) and +optionally set a new one. + =item $w = EV::child $pid, $callback @@ -335,9 +420,8 @@ receives a SIGCHLD, EV will fetch the outstanding exit/wait status for all changed/zombie children and call the callback. -Unlike all other callbacks, this callback will be called with an -additional third argument which is the exit status. See the C -function for details. +You can access both status and pid by using the C and C +methods on the watcher object. You can have as many pid watchers per pid as you want. @@ -348,6 +432,22 @@ Reconfigures the watcher, see the constructor above for details. Can be at any time. +=item $current_pid = $w->pid + +=item $old_pid = $w->pid ($new_pid) + +Returns the previously set process id and optionally set a new one. + +=item $exit_status = $w->rstatus + +Return the exit/wait status (as returned by waitpid, see the waitpid entry +in perlfunc). + +=item $pid = $w->rpid + +Return the pid of the awaited child (useful when you have installed a +watcher for all pids). + =item $w = EV::idle $callback @@ -437,9 +537,8 @@ warn "EV: error in callback (ignoring): $@"; }; -init; - -push @AnyEvent::REGISTRY, [EV => "EV::AnyEvent"]; +default_loop + or die 'EV: cannot initialise libev backend. bad $ENV{LIBEV_METHODS}?'; 1;