--- AnyEvent/lib/AnyEvent.pm 2007/11/02 19:12:02 1.30 +++ AnyEvent/lib/AnyEvent.pm 2008/04/16 14:04:45 1.50 @@ -2,7 +2,7 @@ AnyEvent - provide framework for multiple event loops -Event, Coro, Glib, Tk, Perl - various supported event loops +EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl - various supported event loops =head1 SYNOPSIS @@ -20,6 +20,51 @@ $w->wait; # enters "main loop" till $condvar gets ->broadcast $w->broadcast; # wake up current and all future wait's +=head1 WHY YOU SHOULD USE THIS MODULE (OR NOT) + +Glib, POE, IO::Async, Event... CPAN offers event models by the dozen +nowadays. So what is different about AnyEvent? + +Executive Summary: AnyEvent is I, AnyEvent is I and AnyEvent is I. + +First and foremost, I itself, it only +interfaces to whatever event model the main program happens to use in a +pragmatic way. For event models and certain classes of immortals alike, +the statement "there can only be one" is a bitter reality, and AnyEvent +helps hiding the differences. + +The goal of AnyEvent is to offer module authors the ability to do event +programming (waiting for I/O or timer events) without subscribing to a +religion, a way of living, and most importantly: without forcing your +module users into the same thing by forcing them to use the same event +model you use. + +For modules like POE or IO::Async (which is actually doing all I/O +I...), using them in your module is like joining a +cult: After you joined, you are dependent on them and you cannot use +anything else, as it is simply incompatible to everything that isn't +itself. + +AnyEvent + POE works fine. AnyEvent + Glib works fine. AnyEvent + Tk +works fine etc. etc. but none of these work together with the rest: POE ++ IO::Async? no go. Tk + Event? no go. If your module uses one of +those, every user of your module has to use it, too. If your module +uses AnyEvent, it works transparently with all event models it supports +(including stuff like POE and IO::Async). + +In addition of being free of having to use I, AnyEvent also is free of bloat and policy: with POE or similar +modules, you get an enourmous amount of code and strict rules you have +to follow. AnyEvent, on the other hand, is lean and to the point by only +offering the functionality that is useful, in as thin as a wrapper as +technically possible. + +Of course, if you want lots of policy (this can arguably be somewhat +useful) and you want to force your users to use the one and only event +model, you should I use this module. + + =head1 DESCRIPTION L provides an identical interface to multiple event loops. This @@ -32,11 +77,11 @@ On the first call of any method, the module tries to detect the currently loaded event loop by probing wether any of the following modules is -loaded: L, L, L, L. The first one found is -used. If none is found, the module tries to load these modules in the -order given. The first one that could be successfully loaded will be -used. If still none could be found, AnyEvent will fall back to a pure-perl -event loop, which is also not very efficient. +loaded: L, L, L, L, L, L. The +first one found is used. If none are found, the module tries to load these +modules in the order given. The first one that could be successfully +loaded will be used. If still none could be found, AnyEvent will fall back +to a pure-perl event loop, which is also not very efficient. Because AnyEvent first checks for modules that are already loaded, loading an Event model explicitly before first using AnyEvent will likely make @@ -72,13 +117,9 @@ C the Perl I (not filedescriptor) to watch for events. C must be a string that is either C or C, that creates -a watcher waiting for "r"eadable or "w"ritable events. C teh callback +a watcher waiting for "r"eadable or "w"ritable events. C the callback to invoke everytime the filehandle becomes ready. -Only one io watcher per C and C combination is allowed (i.e. on -a socket you can have one r + one w, not any more (limitation comes from -Tk - if you are sure you are not using Tk this limitation is gone). - Filehandles will be kept alive, so as long as the watcher exists, the filehandle exists, too. @@ -111,7 +152,7 @@ }); # to cancel the timer: - undef $w + undef $w; =head2 CONDITION WATCHERS @@ -121,6 +162,12 @@ A condition watcher watches for a condition - precisely that the C<< ->broadcast >> method has been called. +Note that condition watchers recurse into the event loop - if you have +two watchers that call C<< ->wait >> in a round-robbin fashion, you +lose. Therefore, condition watchers are good to export to your caller, but +you should avoid making a blocking wait, at least in callbacks, as this +usually asks for trouble. + The watcher has only two methods: =over 4 @@ -130,16 +177,24 @@ Wait (blocking if necessary) until the C<< ->broadcast >> method has been called on c<$cv>, while servicing other watchers normally. -Not all event models support a blocking wait - some die in that case, so -if you are using this from a module, never require a blocking wait, but -let the caller decide wether the call will block or not (for example, -by coupling condition variables with some kind of request results and -supporting callbacks so the caller knows that getting the result will not -block, while still suppporting blockign waits if the caller so desires). - You can only wait once on a condition - additional calls will return immediately. +Not all event models support a blocking wait - some die in that case +(programs might want to do that so they stay interactive), so I, but let the +caller decide wether the call will block or not (for example, by coupling +condition variables with some kind of request results and supporting +callbacks so the caller knows that getting the result will not block, +while still suppporting blocking waits if the caller so desires). + +Another reason I to C<< ->wait >> in a module is that you cannot +sensibly have two C<< ->wait >>'s in parallel, as that would require +multiple interpreters or coroutines/threads, none of which C +can supply (the coroutine-aware backends C and C +explicitly support concurrent C<< ->wait >>'s from different coroutines, +however). + =item $cv->broadcast Flag the condition as ready - a running C<< ->wait >> and all further @@ -176,8 +231,10 @@ =head2 CHILD PROCESS WATCHERS You can also listen for the status of a child process specified by the -C argument. The watcher will only trigger once. This works by -installing a signal handler for C. +C argument (or any child if the pid argument is 0). The watcher will +trigger as often as status change for the child are received. This works +by installing a signal handler for C. The callback will be called with +the pid and exit status (as returned by waitpid). Example: wait for pid 1333 @@ -197,12 +254,13 @@ The known classes so far are: - EV::AnyEvent based on EV (an interface to libev, best choice) - AnyEvent::Impl::Coro based on Coro::Event, second best choice. + AnyEvent::Impl::CoroEV based on Coro::EV, best choice. + AnyEvent::Impl::CoroEvent based on Coro::Event, second best choice. + AnyEvent::Impl::EV based on EV (an interface to libev, also best choice). AnyEvent::Impl::Event based on Event, also second best choice :) - AnyEvent::Impl::Glib based on Glib, second-best choice. + AnyEvent::Impl::Glib based on Glib, third-best choice. AnyEvent::Impl::Tk based on Tk, very bad choice. - AnyEvent::Impl::Perl pure-perl implementation, inefficient. + AnyEvent::Impl::Perl pure-perl implementation, inefficient but portable. =item AnyEvent::detect @@ -251,7 +309,7 @@ use Carp; -our $VERSION = '2.55'; +our $VERSION = '3.0'; our $MODEL; our $AUTOLOAD; @@ -262,8 +320,9 @@ our @REGISTRY; my @models = ( - [Coro::Event:: => AnyEvent::Impl::Coro::], - [EV:: => EV::AnyEvent::], + [Coro::EV:: => AnyEvent::Impl::CoroEV::], + [Coro::Event:: => AnyEvent::Impl::CoroEvent::], + [EV:: => AnyEvent::Impl::EV::], [Event:: => AnyEvent::Impl::Event::], [Glib:: => AnyEvent::Impl::Glib::], [Tk:: => AnyEvent::Impl::Tk::], @@ -303,7 +362,7 @@ } $MODEL - or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: Event (or Coro+Event), Glib or Tk."; + or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV (or Coro+EV), Event (or Coro+Event), Glib or Tk."; } unshift @ISA, $MODEL; @@ -351,7 +410,7 @@ my $signal = uc $arg{signal} or Carp::croak "required option 'signal' is missing"; - $SIG_CB{$signal}{$arg{cb} += 0} = $arg{cb}; + $SIG_CB{$signal}{$arg{cb}} = $arg{cb}; $SIG{$signal} ||= sub { $_->() for values %{ $SIG_CB{$signal} || {} }; }; @@ -371,21 +430,31 @@ our %PID_CB; our $CHLD_W; +our $CHLD_DELAY_W; our $PID_IDLE; our $WNOHANG; sub _child_wait { while (0 < (my $pid = waitpid -1, $WNOHANG)) { - $_->() for values %{ $PID_CB{$pid} || {} }, %{ $PID_CB{0} || {} }; + $_->($pid, $?) for (values %{ $PID_CB{$pid} || {} }), + (values %{ $PID_CB{0} || {} }); } undef $PID_IDLE; } +sub _sigchld { + # make sure we deliver these changes "synchronous" with the event loop. + $CHLD_DELAY_W ||= AnyEvent->timer (after => 0, cb => sub { + undef $CHLD_DELAY_W; + &_child_wait; + }); +} + sub child { my (undef, %arg) = @_; - my $pid = uc $arg{pid} + defined (my $pid = $arg{pid} + 0) or Carp::croak "required option 'pid' is missing"; $PID_CB{$pid}{$arg{cb}} = $arg{cb}; @@ -395,9 +464,9 @@ } unless ($CHLD_W) { - $CHLD_W = AnyEvent->signal (signal => 'CHLD', cb => \&_child_wait); - # child could be a zombie already - $PID_IDLE ||= AnyEvent->timer (after => 0, cb => \&_child_wait); + $CHLD_W = AnyEvent->signal (signal => 'CHLD', cb => \&_sigchld); + # child could be a zombie already, so make at least one round + &_sigchld; } bless [$pid, $arg{cb}], "AnyEvent::Base::Child" @@ -571,7 +640,7 @@ my $data = $fcp->client_get ($url); -2. Blocking, but parallelizing: +2. Blocking, but running in parallel: my @datas = map $_->result, map $fcp->txn_client_get ($_), @@ -580,9 +649,9 @@ Both blocking examples work without the module user having to know anything about events. -3a. Event-based in a main program, using any support Event module: +3a. Event-based in a main program, using any supported event module: - use Event; + use EV; $fcp->txn_client_get ($url)->cb (sub { my $txn = shift; @@ -590,7 +659,7 @@ ... }); - Event::loop; + EV::loop; 3b. The module user could use AnyEvent, too: @@ -607,11 +676,14 @@ =head1 SEE ALSO -Event modules: L, L, L, L, L. +Event modules: L, L, L, L, +L, L, L, L, L, L. -Implementations: L, L, L, L. +Implementations: L, L, +L, L, +L, L, L. -Nontrivial usage example: L. +Nontrivial usage examples: L, L. =head1