--- AnyEvent/lib/AnyEvent.pm 2009/03/26 07:47:42 1.196 +++ AnyEvent/lib/AnyEvent.pm 2009/06/23 12:19:33 1.215 @@ -1,28 +1,36 @@ =head1 NAME -AnyEvent - provide framework for multiple event loops +AnyEvent - provide framework for multiple event loops -EV, Event, Glib, Tk, Perl, Event::Lib, Qt, POE - various supported event loops +EV, Event, Glib, Tk, Perl, Event::Lib, Qt and POE are various supported +event loops. =head1 SYNOPSIS use AnyEvent; - my $w = AnyEvent->io (fh => $fh, poll => "r|w", cb => sub { ... }); + # file descriptor readable + my $w = AnyEvent->io (fh => $fh, poll => "r", cb => sub { ... }); + # one-shot or repeating timers my $w = AnyEvent->timer (after => $seconds, cb => sub { ... }); my $w = AnyEvent->timer (after => $seconds, interval => $seconds, cb => ... print AnyEvent->now; # prints current event loop time print AnyEvent->time; # think Time::HiRes::time or simply CORE::time. + # POSIX signal my $w = AnyEvent->signal (signal => "TERM", cb => sub { ... }); + # child process exit my $w = AnyEvent->child (pid => $pid, cb => sub { my ($pid, $status) = @_; ... }); + # called when event loop idle (if applicable) + my $w = AnyEvent->idle (cb => sub { ... }); + my $w = AnyEvent->condvar; # stores whether a condition was flagged $w->send; # wake up current and all future recv's $w->recv; # enters "main loop" till $condvar gets ->send @@ -170,11 +178,17 @@ You can create an I/O watcher by calling the C<< AnyEvent->io >> method with the following mandatory key-value pairs as arguments: -C the Perl I (I file descriptor) to watch for events -(AnyEvent might or might not keep a reference to this file handle). C -must be a string that is either C or C, which creates a watcher -waiting for "r"eadable or "w"ritable events, respectively. C is the -callback to invoke each time the file handle becomes ready. +C is the Perl I (I file descriptor) to watch +for events (AnyEvent might or might not keep a reference to this file +handle). Note that only file handles pointing to things for which +non-blocking operation makes sense are allowed. This includes sockets, +most character devices, pipes, fifos and so on, but not for example files +or block devices. + +C must be a string that is either C or C, which creates a +watcher waiting for "r"eadable or "w"ritable events, respectively. + +C is the callback to invoke each time the file handle becomes ready. Although the callback might get passed parameters, their value and presence is undefined and you cannot rely on them. Portable AnyEvent @@ -316,6 +330,21 @@ difference between C<< AnyEvent->time >> and C<< AnyEvent->now >> into account. +=item AnyEvent->now_update + +Some event loops (such as L or L) cache +the current time for each loop iteration (see the discussion of L<< +AnyEvent->now >>, above). + +When a callback runs for a long time (or when the process sleeps), then +this "current" time will differ substantially from the real time, which +might affect timers and time-outs. + +When this is the case, you can call this method, which will update the +event loop's idea of "current time". + +Note that updating the time I cause some events to be handled. + =back =head2 SIGNAL WATCHERS @@ -391,6 +420,41 @@ # do something else, then wait for process exit $done->recv; +=head2 IDLE WATCHERS + +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. + +Most event loops unfortunately 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". + +Example: read lines from STDIN, but only process them when the +program is otherwise idle: + + my @lines; # read data + my $idle_w; + my $io_w = AnyEvent->io (fh => \*STDIN, poll => 'r', cb => sub { + push @lines, scalar ; + + # start an idle watcher, if not already done + $idle_w ||= AnyEvent->idle (cb => sub { + # handle only one line, when there are lines left + if (my $line = shift @lines) { + print "handled when idle: $line"; + } else { + # otherwise disable the idle watcher again + undef $idle_w; + } + }); + }); + =head2 CONDITION VARIABLES If you are familiar with some event loops you will know that all of them @@ -869,7 +933,7 @@ use Carp; -our $VERSION = 4.341; +our $VERSION = 4.411; our $MODEL; our $AUTOLOAD; @@ -880,8 +944,11 @@ our $WIN32; BEGIN { - my $win32 = ! ! ($^O =~ /mswin32/i); - eval "sub WIN32(){ $win32 }"; + eval "sub WIN32(){ " . (($^O =~ /mswin32/i)*1) ." }"; + eval "sub TAINT(){ " . (${^TAINT}*1) . " }"; + + delete @ENV{grep /^PERL_ANYEVENT_/, keys %ENV} + if ${^TAINT}; } our $verbose = $ENV{PERL_ANYEVENT_VERBOSE}*1; @@ -911,7 +978,8 @@ [Prima:: => AnyEvent::Impl::POE::], ); -our %method = map +($_ => 1), qw(io timer time now signal child condvar one_event DESTROY); +our %method = map +($_ => 1), + qw(io timer time now now_update signal child idle condvar one_event DESTROY); our @post_detect; @@ -926,12 +994,12 @@ push @post_detect, $cb; defined wantarray - ? bless \$cb, "AnyEvent::Util::PostDetect" + ? bless \$cb, "AnyEvent::Util::postdetect" : () } } -sub AnyEvent::Util::PostDetect::DESTROY { +sub AnyEvent::Util::postdetect::DESTROY { @post_detect = grep $_ != ${$_[0]}, @post_detect; } @@ -978,7 +1046,7 @@ } $MODEL - or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV, Event or Glib."; + or die "No event module selected for AnyEvent and autodetect failed. Install any one of these modules: EV, Event or Glib.\n"; } } @@ -1018,7 +1086,7 @@ : Carp::croak "AnyEvent->io requires poll set to either 'r' or 'w'"; open my $fh2, "$mode&" . fileno $fh - or die "cannot dup() filehandle: $!"; + or die "cannot dup() filehandle: $!,"; # we assume CLOEXEC is already set by perl in all important cases @@ -1027,10 +1095,10 @@ package AnyEvent::Base; -# default implementation for now and time +# default implementations for many methods BEGIN { - if (eval "use Time::HiRes (); time (); 1") { + if (eval "use Time::HiRes (); Time::HiRes::time (); 1") { *_time = \&Time::HiRes::time; # if (eval "use POSIX (); (POSIX::times())... } else { @@ -1040,11 +1108,12 @@ sub time { _time } sub now { _time } +sub now_update { } # default implementation for ->condvar sub condvar { - bless { @_ == 3 ? (_ae_cb => $_[2]) : () }, AnyEvent::CondVar:: + bless { @_ == 3 ? (_ae_cb => $_[2]) : () }, "AnyEvent::CondVar" } # default implementation for ->signal @@ -1052,8 +1121,9 @@ our ($SIGPIPE_R, $SIGPIPE_W, %SIG_CB, %SIG_EV, $SIG_IO); sub _signal_exec { + sysread $SIGPIPE_R, my $dummy, 4; + while (%SIG_EV) { - sysread $SIGPIPE_R, my $dummy, 4; for (keys %SIG_EV) { delete $SIG_EV{$_}; $_->() for values %{ $SIG_CB{$_} || {} }; @@ -1065,15 +1135,22 @@ my (undef, %arg) = @_; unless ($SIGPIPE_R) { + require Fcntl; + if (AnyEvent::WIN32) { + require AnyEvent::Util; + ($SIGPIPE_R, $SIGPIPE_W) = AnyEvent::Util::portable_pipe (); AnyEvent::Util::fh_nonblocking ($SIGPIPE_R) if $SIGPIPE_R; AnyEvent::Util::fh_nonblocking ($SIGPIPE_W) if $SIGPIPE_W; # just in case } else { pipe $SIGPIPE_R, $SIGPIPE_W; - require Fcntl; 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 + + # 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; } $SIGPIPE_R @@ -1087,19 +1164,23 @@ $SIG_CB{$signal}{$arg{cb}} = $arg{cb}; $SIG{$signal} ||= sub { + local $!; syswrite $SIGPIPE_W, "\x00", 1 unless %SIG_EV; undef $SIG_EV{$signal}; }; - bless [$signal, $arg{cb}], "AnyEvent::Base::Signal" + bless [$signal, $arg{cb}], "AnyEvent::Base::signal" } -sub AnyEvent::Base::Signal::DESTROY { +sub AnyEvent::Base::signal::DESTROY { my ($signal, $cb) = @{$_[0]}; delete $SIG_CB{$signal}{$cb}; - delete $SIG{$signal} unless keys %{ $SIG_CB{$signal} }; + # delete doesn't work with older perls - they then + # print weird messages, or just unconditionally exit + # instead of getting the default action. + undef $SIG{$signal} unless keys %{ $SIG_CB{$signal} }; } # default implementation for ->child @@ -1107,24 +1188,13 @@ our %PID_CB; our $CHLD_W; our $CHLD_DELAY_W; -our $PID_IDLE; our $WNOHANG; -sub _child_wait { +sub _sigchld { while (0 < (my $pid = waitpid -1, $WNOHANG)) { $_->($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 { @@ -1135,9 +1205,7 @@ $PID_CB{$pid}{$arg{cb}} = $arg{cb}; - unless ($WNOHANG) { - $WNOHANG = eval { local $SIG{__DIE__}; require POSIX; &POSIX::WNOHANG } || 1; - } + $WNOHANG ||= eval { local $SIG{__DIE__}; require POSIX; &POSIX::WNOHANG } || 1; unless ($CHLD_W) { $CHLD_W = AnyEvent->signal (signal => 'CHLD', cb => \&_sigchld); @@ -1145,10 +1213,10 @@ &_sigchld; } - bless [$pid, $arg{cb}], "AnyEvent::Base::Child" + bless [$pid, $arg{cb}], "AnyEvent::Base::child" } -sub AnyEvent::Base::Child::DESTROY { +sub AnyEvent::Base::child::DESTROY { my ($pid, $cb) = @{$_[0]}; delete $PID_CB{$pid}{$cb}; @@ -1157,6 +1225,42 @@ undef $CHLD_W unless keys %PID_CB; } +# 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) = @_; + + 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; + + $w = AnyEvent->timer (after => $w, cb => $rcb); + } else { + # clean up... + undef $w; + undef $rcb; + } + }; + + $w = AnyEvent->timer (after => 0.05, cb => $rcb); + + bless \\$cb, "AnyEvent::Base::idle" +} + +sub AnyEvent::Base::idle::DESTROY { + undef $${$_[0]}; +} + package AnyEvent::CondVar; our @ISA = AnyEvent::CondVar::Base::; @@ -1238,7 +1342,11 @@ =head1 ENVIRONMENT VARIABLES The following environment variables are used by this module or its -submodules: +submodules. + +Note that AnyEvent will remove I environment variables starting with +C from C<%ENV> when it is loaded while taint mode is +enabled. =over 4 @@ -1788,6 +1896,58 @@ =back +=head2 THE IO::Lambda BENCHMARK + +Recently I was told about the benchmark in the IO::Lambda manpage, which +could be misinterpreted to make AnyEvent look bad. In fact, the benchmark +simply compares IO::Lambda with POE, and IO::Lambda looks better (which +shouldn't come as a surprise to anybody). As such, the benchmark is +fine, and shows that the AnyEvent backend from IO::Lambda isn't very +optimal. But how would AnyEvent compare when used without the extra +baggage? To explore this, I wrote the equivalent benchmark for AnyEvent. + +The benchmark itself creates an echo-server, and then, for 500 times, +connects to the echo server, sends a line, waits for the reply, and then +creates the next connection. This is a rather bad benchmark, as it doesn't +test the efficiency of the framework, but it is a benchmark nevertheless. + + name runtime + Lambda/select 0.330 sec + + optimized 0.122 sec + Lambda/AnyEvent 0.327 sec + + optimized 0.138 sec + Raw sockets/select 0.077 sec + POE/select, components 0.662 sec + POE/select, raw sockets 0.226 sec + POE/select, optimized 0.404 sec + + AnyEvent/select/nb 0.085 sec + AnyEvent/EV/nb 0.068 sec + +state machine 0.134 sec + +The benchmark is also a bit unfair (my fault) - the IO::Lambda +benchmarks actually make blocking connects and use 100% blocking I/O, +defeating the purpose of an event-based solution. All of the newly +written AnyEvent benchmarks use 100% non-blocking connects (using +AnyEvent::Socket::tcp_connect and the asynchronous pure perl DNS +resolver), so AnyEvent is at a disadvantage here as non-blocking connects +generally require a lot more bookkeeping and event handling than blocking +connects (which involve a single syscall only). + +The last AnyEvent benchmark additionally uses L, which +offers similar expressive power as POE and IO::Lambda (using conventional +Perl syntax), which means both the echo server and the client are 100% +non-blocking w.r.t. I/O, further placing it at a disadvantage. + +As you can see, AnyEvent + EV even beats the hand-optimised "raw sockets +benchmark", while AnyEvent + its pure perl backend easily beats +IO::Lambda and POE. + +And even the 100% non-blocking version written using the high-level (and +slow :) L abstraction beats both POE and IO::Lambda, +even thought it does all of DNS, tcp-connect and socket I/O in a +non-blocking way. + =head1 SIGNALS @@ -1854,7 +2014,7 @@ 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), and -$ENV{PERL_ANYEGENT_STRICT}. +$ENV{PERL_ANYEVENT_STRICT}. =head1 BUGS @@ -1862,7 +2022,7 @@ Perl 5.8 has numerous memleaks that sometimes hit this module and are hard to work around. If you suffer from memleaks, first upgrade to Perl 5.10 and check wether the leaks still show up. (Perl 5.10.0 has other annoying -mamleaks, such as leaking on C and C but it is usually not as +memleaks, such as leaking on C and C but it is usually not as pronounced).