--- AnyEvent/lib/AnyEvent.pm 2008/05/01 13:45:22 1.106 +++ AnyEvent/lib/AnyEvent.pm 2008/05/17 19:39:33 1.119 @@ -2,7 +2,7 @@ AnyEvent - provide framework for multiple event loops -EV, Event, Coro::EV, Coro::Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event loops +EV, Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event loops =head1 SYNOPSIS @@ -17,8 +17,8 @@ }); my $w = AnyEvent->condvar; # stores whether a condition was flagged - $w->wait; # enters "main loop" till $condvar gets ->send - $w->send; # wake up current and all future wait's + $w->send; # wake up current and all future recv's + $w->recv; # enters "main loop" till $condvar gets ->send =head1 WHY YOU SHOULD USE THIS MODULE (OR NOT) @@ -80,7 +80,7 @@ During the first call of any watcher-creation method, the module tries to detect the currently loaded event loop by probing whether one of the -following modules is already loaded: L, L, L, +following modules is already loaded: L, L, L, L, L, L, L, L. The first one found is used. If none are found, the module tries to load these modules (excluding Tk, Event::Lib, Qt and POE as the pure perl @@ -281,8 +281,6 @@ my $done = AnyEvent->condvar; - AnyEvent::detect; # force event module to be initialised - my $pid = fork or exit 5; my $w = AnyEvent->child ( @@ -295,7 +293,7 @@ ); # do something else, then wait for process exit - $done->wait; + $done->recv; =head2 CONDITION VARIABLES @@ -328,15 +326,15 @@ for example, if you write a module that does asynchronous http requests, then a condition variable would be the ideal candidate to signal the availability of results. The user can either act when the callback is -called or can synchronously C<< ->wait >> for the results. +called or can synchronously C<< ->recv >> for the results. You can also use them to simulate traditional event loops - for example, you can block your main program until an event occurs - for example, you -could C<< ->wait >> in your main program until the user clicks the Quit +could C<< ->recv >> in your main program until the user clicks the Quit button of your app, which would C<< ->send >> the "quit" event. Note that condition variables recurse into the event loop - if you have -two pieces of code that call C<< ->wait >> in a round-robbin fashion, you +two pieces of code that call C<< ->recv >> in a round-robbin fashion, you lose. Therefore, condition variables are good to export to your caller, but you should avoid making a blocking wait yourself, at least in callbacks, as this asks for trouble. @@ -367,7 +365,7 @@ # this "blocks" (while handling events) till the callback # calls send - $result_ready->wait; + $result_ready->recv; =head3 METHODS FOR PRODUCERS @@ -380,19 +378,19 @@ =item $cv->send (...) -Flag the condition as ready - a running C<< ->wait >> and all further -calls to C will (eventually) return after this method has been +Flag the condition as ready - a running C<< ->recv >> and all further +calls to C will (eventually) return after this method has been called. If nobody is waiting the send will be remembered. If a callback has been set on the condition variable, it is called immediately from within send. Any arguments passed to the C call will be returned by all -future C<< ->wait >> calls. +future C<< ->recv >> calls. =item $cv->croak ($error) -Similar to send, but causes all call's wait C<< ->wait >> to invoke +Similar to send, but causes all call's to C<< ->recv >> to invoke C with the given error message/object/scalar. This can be used to signal any errors to the condition variable @@ -402,6 +400,8 @@ =item $cv->end +These two methods are EXPERIMENTAL and MIGHT CHANGE. + These two methods can be used to combine many transactions/events into one. For example, a function that pings many hosts in parallel might want to use a condition variable for the whole process. @@ -456,7 +456,7 @@ =over 4 -=item $cv->wait +=item $cv->recv Wait (blocking if necessary) until the C<< ->send >> or C<< ->croak >> methods have been called on c<$cv>, while servicing other watchers @@ -479,15 +479,19 @@ 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 +Another reason I to C<< ->recv >> in a module is that you cannot +sensibly have two C<< ->recv >>'s in parallel, as that would require multiple interpreters or coroutines/threads, none of which C -can supply (the coroutine-aware backends L and -L explicitly support concurrent C<< ->wait >>'s -from different coroutines, however). +can supply. -You can ensure that C<< -wait >> never blocks by setting a callback and -only calling C<< ->wait >> from within that callback (or at a later +The L module, however, I and I supply coroutines and, in +fact, L replaces AnyEvent's condvars by coroutine-safe +versions and also integrates coroutines into AnyEvent, making blocking +C<< ->recv >> calls perfectly safe as long as they are done from another +coroutine (one that doesn't run the event loop). + +You can ensure that C<< -recv >> never blocks by setting a callback and +only calling C<< ->recv >> from within that callback (or at a later time). This will work even when the event loop does not support blocking waits otherwise. @@ -502,7 +506,7 @@ replaces it before doing so. The callback will be called when the condition becomes "true", i.e. when -C or C are called. Calling C inside the callback +C or C are called. Calling C inside the callback or at any later time is guaranteed not to block. =back @@ -521,8 +525,6 @@ The known classes so far are: - 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, best choice). AnyEvent::Impl::Event based on Event, second best choice. AnyEvent::Impl::Perl pure-perl implementation, fast and portable. @@ -549,6 +551,27 @@ have created an AnyEvent watcher anyway, that is, as late as possible at runtime. +=item $guard = AnyEvent::post_detect { BLOCK } + +Arranges for the code block to be executed as soon as the event model is +autodetected (or immediately if this has already happened). + +If called in scalar or list context, then it creates and returns an object +that automatically removes the callback again when it is destroyed. See +L for a case where this is useful. + +=item @AnyEvent::post_detect + +If there are any code references in this array (you can C to it +before or after loading AnyEvent), then they will called directly after +the event loop has been chosen. + +You should check C<$AnyEvent::MODEL> before adding to this array, though: +if it contains a true value then the event loop has already been detected, +and the array will be ignored. + +Best use C instead. + =back =head1 WHAT TO DO IN A MODULE @@ -561,14 +584,14 @@ by calling AnyEvent in your module body you force the user of your module to load the event module first. -Never call C<< ->wait >> on a condition variable unless you I that +Never call C<< ->recv >> on a condition variable unless you I that the C<< ->send >> method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive. -It is fine, however, to call C<< ->wait >> when the user of your module +It is fine, however, to call C<< ->recv >> when the user of your module requests it (i.e. if you create a http request object ad have a method -called C that returns the results, it should call C<< ->wait >> +called C that returns the results, it should call C<< ->recv >> freely, as the user of your module knows what she is doing. always). =head1 WHAT TO DO IN THE MAIN PROGRAM @@ -610,10 +633,6 @@ Provide read and write buffers and manages watchers for reads and writes. -=item L - -Provides a means to do non-blocking connects, accepts etc. - =item L Provides a simple web application server framework. @@ -646,21 +665,22 @@ =item L -Has special support for AnyEvent. +Has special support for AnyEvent via L. -=item L +=item L, L -The lambda approach to I/O - don't ask, look there. Can use AnyEvent. +Truly asynchronous I/O, should be in the toolbox of every event +programmer. AnyEvent::AIO transparently fuses IO::AIO and AnyEvent +together. -=item L +=item L, L -Truly asynchronous I/O, should be in the toolbox of every event -programmer. Can be trivially made to use AnyEvent. +Truly asynchronous Berkeley DB access. AnyEvent::AIO transparently fuses +IO::AIO and AnyEvent together. -=item L +=item L -Truly asynchronous Berkeley DB access. Can be trivially made to use -AnyEvent. +The lambda approach to I/O - don't ask, look there. Can use AnyEvent. =back @@ -673,7 +693,7 @@ use Carp; -our $VERSION = '3.3'; +our $VERSION = '3.41'; our $MODEL; our $AUTOLOAD; @@ -684,8 +704,6 @@ our @REGISTRY; my @models = ( - [Coro::EV:: => AnyEvent::Impl::CoroEV::], - [Coro::Event:: => AnyEvent::Impl::CoroEvent::], [EV:: => AnyEvent::Impl::EV::], [Event:: => AnyEvent::Impl::Event::], [Tk:: => AnyEvent::Impl::Tk::], @@ -701,6 +719,28 @@ our %method = map +($_ => 1), qw(io timer signal child condvar one_event DESTROY); +our @post_detect; + +sub post_detect(&) { + my ($cb) = @_; + + if ($MODEL) { + $cb->(); + + 1 + } else { + push @post_detect, $cb; + + defined wantarray + ? bless \$cb, "AnyEvent::Util::PostDetect" + : () + } +} + +sub AnyEvent::Util::PostDetect::DESTROY { + @post_detect = grep $_ != ${$_[0]}, @post_detect; +} + sub detect() { unless ($MODEL) { no strict 'refs'; @@ -743,12 +783,14 @@ } $MODEL - 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) or Glib."; + or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV, Event or Glib."; } } unshift @ISA, $MODEL; push @{"$MODEL\::ISA"}, "AnyEvent::Base"; + + (shift @post_detect)->() while @post_detect; } $MODEL @@ -768,18 +810,10 @@ package AnyEvent::Base; -# default implementation for ->condvar, ->wait, ->broadcast +# default implementation for ->condvar sub condvar { - bless \my $flag, "AnyEvent::Base::CondVar" -} - -sub AnyEvent::Base::CondVar::broadcast { - ${$_[0]}++; -} - -sub AnyEvent::Base::CondVar::wait { - AnyEvent->one_event while !${$_[0]}; + bless {}, AnyEvent::CondVar:: } # default implementation for ->signal @@ -863,6 +897,62 @@ undef $CHLD_W unless keys %PID_CB; } +package AnyEvent::CondVar; + +our @ISA = AnyEvent::CondVar::Base::; + +package AnyEvent::CondVar::Base; + +sub _send { + # nop +} + +sub send { + my $cv = shift; + $cv->{_ae_sent} = [@_]; + (delete $cv->{_ae_cb})->($cv) if $cv->{_ae_cb}; + $cv->_send; +} + +sub croak { + $_[0]{_ae_croak} = $_[1]; + $_[0]->send; +} + +sub ready { + $_[0]{_ae_sent} +} + +sub _wait { + AnyEvent->one_event while !$_[0]{_ae_sent}; +} + +sub recv { + $_[0]->_wait; + + Carp::croak $_[0]{_ae_croak} if $_[0]{_ae_croak}; + wantarray ? @{ $_[0]{_ae_sent} } : $_[0]{_ae_sent}[0] +} + +sub cb { + $_[0]{_ae_cb} = $_[1] if @_ > 1; + $_[0]{_ae_cb} +} + +sub begin { + ++$_[0]{_ae_counter}; + $_[0]{_ae_end_cb} = $_[1] if @_ > 1; +} + +sub end { + return if --$_[0]{_ae_counter}; + &{ $_[0]{_ae_end_cb} } if $_[0]{_ae_end_cb}; +} + +# undocumented/compatibility with pre-3.4 +*broadcast = \&send; +*wait = \&_wait; + =head1 SUPPLYING YOUR OWN EVENT MODEL INTERFACE This is an advanced topic that you do not normally need to use AnyEvent in @@ -960,7 +1050,7 @@ warn "io event <$_[0]>\n"; # will always output chomp (my $input = ); # read a line warn "read: $input\n"; # output what has been read - $cv->broadcast if $input =~ /^q/i; # quit program if /^q/i + $cv->send if $input =~ /^q/i; # quit program if /^q/i }, ); @@ -975,7 +1065,7 @@ new_timer; # create first timer - $cv->wait; # wait until user enters /^q/i + $cv->recv; # wait until user enters /^q/i =head1 REAL-WORLD EXAMPLE @@ -1041,7 +1131,7 @@ if (end-of-file or data complete) { $txn->{result} = $txn->{buf}; - $txn->{finished}->broadcast; + $txn->{finished}->send; $txb->{cb}->($txn) of $txn->{cb}; # also call callback } @@ -1049,7 +1139,7 @@ request was already finished, it doesn't wait, of course, and returns the data: - $txn->{finished}->wait; + $txn->{finished}->recv; return $txn->{result}; The actual code goes further and collects all errors (Cs, exceptions) @@ -1094,10 +1184,10 @@ $fcp->txn_client_get ($url)->cb (sub { ... - $quit->broadcast; + $quit->send; }); - $quit->wait; + $quit->recv; =head1 BENCHMARKS @@ -1136,7 +1226,7 @@ I is the time, in microseconds, used to invoke a simple callback. The callback simply counts down a Perl variable and after it was -invoked "watcher" times, it would C<< ->broadcast >> a condvar once to +invoked "watcher" times, it would C<< ->send >> a condvar once to signal the end of this phase. I is the time, in microseconds, that it takes to destroy a single @@ -1392,17 +1482,22 @@ use AnyEvent; +Similar considerations apply to $ENV{PERL_ANYEVENT_VERBOSE}, as that can +be used to probe what backend is used and gain other information (which is +probably even less useful to an attacker than PERL_ANYEVENT_MODEL). + =head1 SEE ALSO -Event modules: L, L, L, L, -L, L, L, L, L, L, -L, L, L. - -Implementations: L, L, -L, L, L, -L, L, L, -L, L. +Event modules: L, L, L, L, L, +L, L, L, L, L. + +Implementations: L, L, +L, L, L, +L, L, +L. + +Coroutine support: L, L, L, L, Nontrivial usage examples: L, L.