--- AnyEvent/lib/AnyEvent.pm 2009/12/25 07:39:41 1.308 +++ AnyEvent/lib/AnyEvent.pm 2010/05/20 21:22:20 1.323 @@ -9,7 +9,10 @@ use AnyEvent; - # file descriptor readable + # if you prefer function calls, look at the AE manpage for + # an alternative API. + + # file handle or descriptor readable my $w = AnyEvent->io (fh => $fh, poll => "r", cb => sub { ... }); # one-shot or repeating timers @@ -505,16 +508,19 @@ $w = AnyEvent->idle (cb => ); -Sometimes there is a need to do something, but it is not so important -to do it instantly, but only when there is nothing better to do. This -"nothing better to do" is usually defined to be "no other events need -attention by the event loop". - -Idle watchers ideally get invoked when the event loop has nothing -better to do, just before it would block the process to wait for new -events. Instead of blocking, the idle watcher is invoked. +Repeatedly invoke the callback after the process becomes idle, until +either the watcher is destroyed or new events have been detected. + +Idle watchers are useful when there is a need to do something, but it +is not so important (or wise) to do it instantly. The callback will be +invoked only when there is "nothing better to do", which is usually +defined as "all outstanding events have been handled and no new events +have been detected". That means that idle watchers ideally get invoked +when the event loop has just polled for new events but none have been +detected. Instead of blocking to wait for more events, the idle watchers +will be invoked. -Most event loops unfortunately do not really support idle watchers (only +Unfortunately, most event loops do not really support idle watchers (only EV, Event and Glib do it in a usable fashion) - for the rest, AnyEvent will simply call the callback "from time to time". @@ -605,21 +611,21 @@ Example: wait for a timer. - # wait till the result is ready - my $result_ready = AnyEvent->condvar; + # condition: "wait till the timer is fired" + my $timer_fired = AnyEvent->condvar; - # do something such as adding a timer - # or socket watcher the calls $result_ready->send - # when the "result" is ready. + # create the timer - we could wait for, say + # a handle becomign ready, or even an + # AnyEvent::HTTP request to finish, but # in this case, we simply use a timer: my $w = AnyEvent->timer ( after => 1, - cb => sub { $result_ready->send }, + cb => sub { $timer_fired->send }, ); # this "blocks" (while handling events) till the callback # calls ->send - $result_ready->recv; + $timer_fired->recv; Example: wait for a timer, but take advantage of the fact that condition variables are also callable directly. @@ -1078,60 +1084,48 @@ Provides rich asynchronous DNS resolver capabilities. -=item L - -A simple-to-use HTTP library that is capable of making a lot of concurrent -HTTP requests. - -=item L - -Provides a simple web application server framework. +=item L, L, L, L, L, L -=item L - -The fastest ping in the west. +Implement event-based interfaces to the protocols of the same name (for +the curious, IGS is the International Go Server and FCP is the Freenet +Client Protocol). + +=item L + +Here be danger! + +As Pauli would put it, "Not only is it not right, it's not even wrong!" - +there are so many things wrong with AnyEvent::Handle::UDP, most notably +it's use of a stream-based API with a protocol that isn't streamable, that +the only way to improve it is to delete it. + +It features data corruption (but typically only under load) and general +confusion. On top, the author is not only clueless about UDP but also +fact-resistant - some gems of his understanding: "connect doesn't work +with UDP", "UDP packets are not IP packets", "UDP only has datagrams, not +packets", "I don't need to implement proper error checking as UDP doesn't +support error checking" and so on - he doesn't even understand what's +wrong with his module when it is explained to him. =item L -Executes L requests asynchronously in a proxy process. +Executes L requests asynchronously in a proxy process for you, +notifying you in an event-bnased way when the operation is finished. =item L -Truly asynchronous I/O, should be in the toolbox of every event -programmer. AnyEvent::AIO transparently fuses L and AnyEvent -together. - -=item L - -Truly asynchronous Berkeley DB access. AnyEvent::BDB transparently fuses -L and AnyEvent together. - -=item L - -A non-blocking interface to gpsd, a daemon delivering GPS information. - -=item L - -AnyEvent based IRC client module family (replacing the older Net::IRC3). +Truly asynchronous (as opposed to non-blocking) I/O, should be in the +toolbox of every event programmer. AnyEvent::AIO transparently fuses +L and AnyEvent together, giving AnyEvent access to event-based +file I/O, and much more. -=item L - -AnyEvent based XMPP (Jabber protocol) module family (replacing the older -Net::XMPP2>. - -=item L - -A non-blocking interface to the Internet Go Server protocol (used by -L). - -=item L +=item L -AnyEvent-based implementation of the Freenet Client Protocol, birthplace -of AnyEvent. +A simple embedded webserver. -=item L +=item L -High level API for event-based execution flow control. +The fastest ping in the west. =item L @@ -1155,7 +1149,7 @@ use Carp (); -our $VERSION = '5.23'; +our $VERSION = '5.261'; our $MODEL; our $AUTOLOAD; @@ -1166,8 +1160,9 @@ our $VERBOSE; BEGIN { - eval "sub WIN32(){ " . (($^O =~ /mswin32/i)*1) ." }"; - eval "sub TAINT(){ " . (${^TAINT}*1) . " }"; + require "AnyEvent/constants.pl"; + + eval "sub TAINT (){" . (${^TAINT}*1) . "}"; delete @ENV{grep /^PERL_ANYEVENT_/, keys %ENV} if ${^TAINT}; @@ -1220,17 +1215,11 @@ sub post_detect(&) { my ($cb) = @_; - if ($MODEL) { - $cb->(); + push @post_detect, $cb; - undef - } else { - push @post_detect, $cb; - - defined wantarray - ? bless \$cb, "AnyEvent::Util::postdetect" - : () - } + defined wantarray + ? bless \$cb, "AnyEvent::Util::postdetect" + : () } sub AnyEvent::Util::postdetect::DESTROY { @@ -1238,62 +1227,78 @@ } sub detect() { - unless ($MODEL) { - local $SIG{__DIE__}; + # free some memory + *detect = sub () { $MODEL }; - if ($ENV{PERL_ANYEVENT_MODEL} =~ /^([a-zA-Z]+)$/) { - my $model = "AnyEvent::Impl::$1"; - if (eval "require $model") { - $MODEL = $model; - warn "AnyEvent: loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it.\n" if $VERBOSE >= 2; - } else { - warn "AnyEvent: unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@" if $VERBOSE; + local $!; # for good measure + local $SIG{__DIE__}; + + if ($ENV{PERL_ANYEVENT_MODEL} =~ /^([a-zA-Z]+)$/) { + my $model = "AnyEvent::Impl::$1"; + if (eval "require $model") { + $MODEL = $model; + warn "AnyEvent: loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it.\n" if $VERBOSE >= 2; + } else { + warn "AnyEvent: unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@" if $VERBOSE; + } + } + + # check for already loaded models + unless ($MODEL) { + for (@REGISTRY, @models) { + my ($package, $model) = @$_; + if (${"$package\::VERSION"} > 0) { + if (eval "require $model") { + $MODEL = $model; + warn "AnyEvent: autodetected model '$model', using it.\n" if $VERBOSE >= 2; + last; + } } } - # check for already loaded models unless ($MODEL) { + # try to autoload a model for (@REGISTRY, @models) { - my ($package, $model) = @$_; - if (${"$package\::VERSION"} > 0) { - if (eval "require $model") { - $MODEL = $model; - warn "AnyEvent: autodetected model '$model', using it.\n" if $VERBOSE >= 2; - last; - } + my ($package, $model, $autoload) = @$_; + if ( + $autoload + and eval "require $package" + and ${"$package\::VERSION"} > 0 + and eval "require $model" + ) { + $MODEL = $model; + warn "AnyEvent: autoloaded model '$model', using it.\n" if $VERBOSE >= 2; + last; } } - unless ($MODEL) { - # try to autoload a model - for (@REGISTRY, @models) { - my ($package, $model, $autoload) = @$_; - if ( - $autoload - and eval "require $package" - and ${"$package\::VERSION"} > 0 - and eval "require $model" - ) { - $MODEL = $model; - warn "AnyEvent: autoloaded model '$model', using it.\n" if $VERBOSE >= 2; - last; - } - } - - $MODEL - or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV, Event or Glib.\n"; - } + $MODEL + or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV, Event or Glib.\n"; } + } - push @{"$MODEL\::ISA"}, "AnyEvent::Base"; - - unshift @ISA, $MODEL; + @models = (); # free probe data - require AnyEvent::Strict if $ENV{PERL_ANYEVENT_STRICT}; + push @{"$MODEL\::ISA"}, "AnyEvent::Base"; + unshift @ISA, $MODEL; - (shift @post_detect)->() while @post_detect; + # now nuke some methods that are overriden by the backend. + # SUPER is not allowed. + for (qw(time signal child idle)) { + undef &{"AnyEvent::Base::$_"} + if defined &{"$MODEL\::$_"}; } + require AnyEvent::Strict if $ENV{PERL_ANYEVENT_STRICT}; + + (shift @post_detect)->() while @post_detect; + + *post_detect = sub(&) { + shift->(); + + undef + }; + $MODEL } @@ -1301,9 +1306,9 @@ (my $func = $AUTOLOAD) =~ s/.*://; $method{$func} - or Carp::croak "$func: not a valid method for AnyEvent objects"; + or Carp::croak "$func: not a valid AnyEvent class method"; - detect unless $MODEL; + detect; my $class = shift; $class->$func (@_); @@ -1330,7 +1335,7 @@ Starting with version 5.0, AnyEvent officially supports a second, much simpler, API that is designed to reduce the calling, typing and memory -overhead. +overhead by using function call syntax and a fixed number of parameters. See the L manpage for details. @@ -1340,6 +1345,9 @@ our $VERSION = $AnyEvent::VERSION; +# fall back to the main API by default - backends and AnyEvent::Base +# implementations can overwrite these. + sub io($$$) { AnyEvent->io (fh => $_[0], poll => $_[1] ? "w" : "r", cb => $_[2]) } @@ -1380,28 +1388,44 @@ # default implementations for many methods -sub _time() { - # probe for availability of Time::HiRes - if (eval "use Time::HiRes (); Time::HiRes::time (); 1") { - warn "AnyEvent: using Time::HiRes for sub-second timing accuracy.\n" if $VERBOSE >= 8; - *_time = \&Time::HiRes::time; - # if (eval "use POSIX (); (POSIX::times())... - } else { - warn "AnyEvent: using built-in time(), WARNING, no sub-second resolution!\n" if $VERBOSE; - *_time = sub { time }; # epic fail - } +sub time { + eval q{ # poor man's autoloading {} + # probe for availability of Time::HiRes + if (eval "use Time::HiRes (); Time::HiRes::time (); 1") { + warn "AnyEvent: using Time::HiRes for sub-second timing accuracy.\n" if $VERBOSE >= 8; + *AE::time = \&Time::HiRes::time; + # if (eval "use POSIX (); (POSIX::times())... + } else { + warn "AnyEvent: using built-in time(), WARNING, no sub-second resolution!\n" if $VERBOSE; + *AE::time = sub (){ time }; # epic fail + } + + *time = sub { AE::time }; # different prototypes + }; + die if $@; - &_time + &time } -sub time { _time } -sub now { _time } +*now = \&time; + sub now_update { } # default implementation for ->condvar sub condvar { - bless { @_ == 3 ? (_ae_cb => $_[2]) : () }, "AnyEvent::CondVar" + eval q{ # poor man's autoloading {} + *condvar = sub { + bless { @_ == 3 ? (_ae_cb => $_[2]) : () }, "AnyEvent::CondVar" + }; + + *AE::cv = sub (;&) { + bless { @_ ? (_ae_cb => shift) : () }, "AnyEvent::CondVar" + }; + }; + die if $@; + + &condvar } # default implementation for ->signal @@ -1420,20 +1444,8 @@ our (%SIG_ASY, %SIG_ASY_W); our ($SIG_COUNT, $SIG_TW); -sub _signal_exec { - $HAVE_ASYNC_INTERRUPT - ? $SIGPIPE_R->drain - : sysread $SIGPIPE_R, (my $dummy), 9; - - while (%SIG_EV) { - for (keys %SIG_EV) { - delete $SIG_EV{$_}; - $_->() for values %{ $SIG_CB{$_} || {} }; - } - } -} - # install a dummy wakeup watcher to reduce signal catching latency +# used by Impls sub _sig_add() { unless ($SIG_COUNT++) { # try to align timer on a full-second boundary, if possible @@ -1453,7 +1465,7 @@ } our $_sig_name_init; $_sig_name_init = sub { - eval q{ # poor man's autoloading + eval q{ # poor man's autoloading {} undef $_sig_name_init; if (_have_async_interrupt) { @@ -1495,8 +1507,6 @@ } else { warn "AnyEvent: using emulated perl signal handling with latency timer.\n" if $VERBOSE >= 8; - require Fcntl; - if (AnyEvent::WIN32) { require AnyEvent::Util; @@ -1505,12 +1515,12 @@ AnyEvent::Util::fh_nonblocking ($SIGPIPE_W, 1) if $SIGPIPE_W; # just in case } else { pipe $SIGPIPE_R, $SIGPIPE_W; - fcntl $SIGPIPE_R, &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK if $SIGPIPE_R; - fcntl $SIGPIPE_W, &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK if $SIGPIPE_W; # just in case + fcntl $SIGPIPE_R, AnyEvent::F_SETFL, AnyEvent::O_NONBLOCK if $SIGPIPE_R; + fcntl $SIGPIPE_W, AnyEvent::F_SETFL, AnyEvent::O_NONBLOCK if $SIGPIPE_W; # just in case # not strictly required, as $^F is normally 2, but let's make sure... - fcntl $SIGPIPE_R, &Fcntl::F_SETFD, &Fcntl::FD_CLOEXEC; - fcntl $SIGPIPE_W, &Fcntl::F_SETFD, &Fcntl::FD_CLOEXEC; + fcntl $SIGPIPE_R, AnyEvent::F_SETFD, AnyEvent::FD_CLOEXEC; + fcntl $SIGPIPE_W, AnyEvent::F_SETFD, AnyEvent::FD_CLOEXEC; } $SIGPIPE_R @@ -1519,45 +1529,43 @@ $SIG_IO = AE::io $SIGPIPE_R, 0, \&_signal_exec; } - *signal = sub { - my (undef, %arg) = @_; - - my $signal = uc $arg{signal} - or Carp::croak "required option 'signal' is missing"; + *signal = $HAVE_ASYNC_INTERRUPT + ? sub { + my (undef, %arg) = @_; + + # async::interrupt + my $signal = sig2num $arg{signal}; + $SIG_CB{$signal}{$arg{cb}} = $arg{cb}; + + $SIG_ASY{$signal} ||= new Async::Interrupt + cb => sub { undef $SIG_EV{$signal} }, + signal => $signal, + pipe => [$SIGPIPE_R->filenos], + pipe_autodrain => 0, + ; + + bless [$signal, $arg{cb}], "AnyEvent::Base::signal" + } + : sub { + my (undef, %arg) = @_; + + # pure perl + my $signal = sig2name $arg{signal}; + $SIG_CB{$signal}{$arg{cb}} = $arg{cb}; + + $SIG{$signal} ||= sub { + local $!; + syswrite $SIGPIPE_W, "\x00", 1 unless %SIG_EV; + undef $SIG_EV{$signal}; + }; + + # can't do signal processing without introducing races in pure perl, + # so limit the signal latency. + _sig_add; - if ($HAVE_ASYNC_INTERRUPT) { - # async::interrupt - - $signal = sig2num $signal; - $SIG_CB{$signal}{$arg{cb}} = $arg{cb}; - - $SIG_ASY{$signal} ||= new Async::Interrupt - cb => sub { undef $SIG_EV{$signal} }, - signal => $signal, - pipe => [$SIGPIPE_R->filenos], - pipe_autodrain => 0, - ; - - } else { - # pure perl - - # AE::Util has been loaded in signal - $signal = sig2name $signal; - $SIG_CB{$signal}{$arg{cb}} = $arg{cb}; - - $SIG{$signal} ||= sub { - local $!; - syswrite $SIGPIPE_W, "\x00", 1 unless %SIG_EV; - undef $SIG_EV{$signal}; - }; - - # can't do signal processing without introducing races in pure perl, - # so limit the signal latency. - _sig_add; - } - - bless [$signal, $arg{cb}], "AnyEvent::Base::signal" - }; + bless [$signal, $arg{cb}], "AnyEvent::Base::signal" + } + ; *AnyEvent::Base::signal::DESTROY = sub { my ($signal, $cb) = @{$_[0]}; @@ -1574,8 +1582,22 @@ undef $SIG{$signal} unless keys %{ $SIG_CB{$signal} }; }; + + *_signal_exec = sub { + $HAVE_ASYNC_INTERRUPT + ? $SIGPIPE_R->drain + : sysread $SIGPIPE_R, (my $dummy), 9; + + while (%SIG_EV) { + for (keys %SIG_EV) { + delete $SIG_EV{$_}; + $_->() for values %{ $SIG_CB{$_} || {} }; + } + } + }; }; die if $@; + &signal } @@ -1586,6 +1608,7 @@ our $CHLD_DELAY_W; our $WNOHANG; +# used by many Impl's sub _emit_childstatus($$) { my (undef, $rpid, $rstatus) = @_; @@ -1594,78 +1617,92 @@ values %{ $PID_CB{0} || {} }; } -sub _sigchld { - my $pid; +sub child { + eval q{ # poor man's autoloading {} + *_sigchld = sub { + my $pid; - AnyEvent->_emit_childstatus ($pid, $?) - while ($pid = waitpid -1, $WNOHANG) > 0; -} + AnyEvent->_emit_childstatus ($pid, $?) + while ($pid = waitpid -1, $WNOHANG) > 0; + }; -sub child { - my (undef, %arg) = @_; + *child = sub { + my (undef, %arg) = @_; - defined (my $pid = $arg{pid} + 0) - or Carp::croak "required option 'pid' is missing"; + defined (my $pid = $arg{pid} + 0) + or Carp::croak "required option 'pid' is missing"; - $PID_CB{$pid}{$arg{cb}} = $arg{cb}; + $PID_CB{$pid}{$arg{cb}} = $arg{cb}; - # WNOHANG is almost cetrainly 1 everywhere - $WNOHANG ||= $^O =~ /^(?:openbsd|netbsd|linux|freebsd|cygwin|MSWin32)$/ - ? 1 - : eval { local $SIG{__DIE__}; require POSIX; &POSIX::WNOHANG } || 1; - - unless ($CHLD_W) { - $CHLD_W = AE::signal CHLD => \&_sigchld; - # child could be a zombie already, so make at least one round - &_sigchld; - } + # WNOHANG is almost cetrainly 1 everywhere + $WNOHANG ||= $^O =~ /^(?:openbsd|netbsd|linux|freebsd|cygwin|MSWin32)$/ + ? 1 + : eval { local $SIG{__DIE__}; require POSIX; &POSIX::WNOHANG } || 1; + + unless ($CHLD_W) { + $CHLD_W = AE::signal CHLD => \&_sigchld; + # child could be a zombie already, so make at least one round + &_sigchld; + } - bless [$pid, $arg{cb}], "AnyEvent::Base::child" -} + bless [$pid, $arg{cb}], "AnyEvent::Base::child" + }; + + *AnyEvent::Base::child::DESTROY = sub { + my ($pid, $cb) = @{$_[0]}; -sub AnyEvent::Base::child::DESTROY { - my ($pid, $cb) = @{$_[0]}; + delete $PID_CB{$pid}{$cb}; + delete $PID_CB{$pid} unless keys %{ $PID_CB{$pid} }; - delete $PID_CB{$pid}{$cb}; - delete $PID_CB{$pid} unless keys %{ $PID_CB{$pid} }; + undef $CHLD_W unless keys %PID_CB; + }; + }; + die if $@; - undef $CHLD_W unless keys %PID_CB; + &child } # idle emulation is done by simply using a timer, regardless # of whether the process is idle or not, and not letting # the callback use more than 50% of the time. sub idle { - my (undef, %arg) = @_; + eval q{ # poor man's autoloading {} + *idle = sub { + my (undef, %arg) = @_; - my ($cb, $w, $rcb) = $arg{cb}; + my ($cb, $w, $rcb) = $arg{cb}; - $rcb = sub { - if ($cb) { - $w = _time; - &$cb; - $w = _time - $w; - - # never use more then 50% of the time for the idle watcher, - # within some limits - $w = 0.0001 if $w < 0.0001; - $w = 5 if $w > 5; + $rcb = sub { + if ($cb) { + $w = _time; + &$cb; + $w = _time - $w; + + # never use more then 50% of the time for the idle watcher, + # within some limits + $w = 0.0001 if $w < 0.0001; + $w = 5 if $w > 5; + + $w = AE::timer $w, 0, $rcb; + } else { + # clean up... + undef $w; + undef $rcb; + } + }; - $w = AE::timer $w, 0, $rcb; - } else { - # clean up... - undef $w; - undef $rcb; - } - }; + $w = AE::timer 0.05, 0, $rcb; - $w = AE::timer 0.05, 0, $rcb; + bless \\$cb, "AnyEvent::Base::idle" + }; - bless \\$cb, "AnyEvent::Base::idle" -} + *AnyEvent::Base::idle::DESTROY = sub { + undef $${$_[0]}; + }; + }; + die if $@; -sub AnyEvent::Base::idle::DESTROY { - undef $${$_[0]}; + &idle } package AnyEvent::CondVar; @@ -2034,7 +2071,7 @@ that occurred during request processing. The C method detects whether an exception as thrown (it is stored inside the $txn object) and just throws the exception, which means connection errors and other -problems get reported tot he code that tries to use the result, not in a +problems get reported to the code that tries to use the result, not in a random callback. All of this enables the following usage styles: @@ -2501,6 +2538,9 @@ C, and is the fastest backend I. You can even embed L/L in it (or vice versa, see L and L). +If you only use backends that rely on another event loop (e.g. C), +then this module will do nothing for you. + =item L The guard module, when used, will be used to implement @@ -2511,12 +2551,9 @@ =item L and L One of these modules is required when you want to read or write JSON data -via L. It is also written in pure-perl, but can take +via L. L is also written in pure-perl, but can take advantage of the ultra-high-speed L module when it is installed. -In fact, L will use L by default if it is -installed. - =item L Implementing TLS/SSL in Perl is certainly interesting, but not very