--- AnyEvent/lib/AnyEvent.pm 2009/07/31 20:16:29 1.269 +++ AnyEvent/lib/AnyEvent.pm 2009/08/25 12:05:30 1.287 @@ -594,7 +594,7 @@ ); # this "blocks" (while handling events) till the callback - # calls -send $result_ready->recv; Example: wait for a timer, but take advantage of the fact that condition @@ -668,9 +668,10 @@ Every call to C<< ->begin >> will increment a counter, and every call to C<< ->end >> will decrement it. If the counter reaches C<0> in C<< ->end ->>, the (last) callback passed to C will be executed. That callback -is I to call C<< ->send >>, but that is not required. If no -callback was set, C will be called without any arguments. +>>, the (last) callback passed to C will be executed, passing the +condvar as first argument. That callback is I to call C<< ->send +>>, but that is not required. If no group callback was set, C will +be called without any arguments. You can think of C<< $cv->send >> giving you an OR condition (one call sends), while C<< $cv->begin >> and C<< $cv->end >> giving you an AND @@ -707,7 +708,7 @@ my $cv = AnyEvent->condvar; my %result; - $cv->begin (sub { $cv->send (\%result) }); + $cv->begin (sub { shift->send (\%result) }); for my $host (@list_of_hosts) { $cv->begin; @@ -808,12 +809,11 @@ =item Backends that are autoprobed when no other event loop can be found. EV is the preferred backend when no other event loop seems to be in -use. If EV is not installed, then AnyEvent will try Event, and, failing -that, will fall back to its own pure-perl implementation, which is -available everywhere as it comes with AnyEvent itself. +use. If EV is not installed, then AnyEvent will fall back to its own +pure-perl implementation, which is available everywhere as it comes with +AnyEvent itself. AnyEvent::Impl::EV based on EV (interface to libev, best choice). - AnyEvent::Impl::Event based on Event, very stable, few glitches. AnyEvent::Impl::Perl pure-perl implementation, fast and portable. =item Backends that are transparently being picked up when they are used. @@ -824,6 +824,7 @@ when the main program loads an event module before anything starts to create watchers. Nothing special needs to be done by the main program. + AnyEvent::Impl::Event based on Event, very stable, few glitches. AnyEvent::Impl::Glib based on Glib, slow but very stable. AnyEvent::Impl::Tk based on Tk, very broken. AnyEvent::Impl::EventLib based on Event::Lib, leaks memory and worse. @@ -1117,7 +1118,7 @@ use Carp (); -our $VERSION = 4.9; +our $VERSION = '5.112'; our $MODEL; our $AUTOLOAD; @@ -1153,11 +1154,11 @@ my @models = ( [EV:: => AnyEvent::Impl::EV:: , 1], - [Event:: => AnyEvent::Impl::Event::, 1], [AnyEvent::Impl::Perl:: => AnyEvent::Impl::Perl:: , 1], # everything below here will not (normally) be autoprobed # as the pureperl backend should work everywhere # and is usually faster + [Event:: => AnyEvent::Impl::Event::, 1], [Glib:: => AnyEvent::Impl::Glib:: , 1], # becomes extremely slow with many watchers [Event::Lib:: => AnyEvent::Impl::EventLib::], # too buggy [Irssi:: => AnyEvent::Impl::Irssi::], # Irssi has a bogus "Event" package @@ -1170,9 +1171,10 @@ # byzantine signal and broken child handling, among others. # IO::Async is rather hard to detect, as it doesn't have any # obvious default class. -# [0, IO::Async:: => AnyEvent::Impl::IOAsync::], # requires special main program -# [0, IO::Async::Loop:: => AnyEvent::Impl::IOAsync::], # requires special main program -# [0, IO::Async::Notifier:: => AnyEvent::Impl::IOAsync::], # requires special main program + [IO::Async:: => AnyEvent::Impl::IOAsync::], # requires special main program + [IO::Async::Loop:: => AnyEvent::Impl::IOAsync::], # requires special main program + [IO::Async::Notifier:: => AnyEvent::Impl::IOAsync::], # requires special main program + [AnyEvent::Impl::IOAsync:: => AnyEvent::Impl::IOAsync::], # requires special main program ); our %method = map +($_ => 1), @@ -1289,6 +1291,56 @@ ($fh2, $rw) } +=head1 SIMPLIFIED AE API + +Starting with version 5.0, AnyEvent officially supports a second, much +simpler, API that is designed to reduce the calling, typing and memory +overhead. + +See the L manpage for details. + +=cut + +package AE; + +our $VERSION = $AnyEvent::VERSION; + +sub io($$$) { + AnyEvent->io (fh => $_[0], poll => $_[1] ? "w" : "r", cb => $_[2]) +} + +sub timer($$$) { + AnyEvent->timer (after => $_[0], interval => $_[1], cb => $_[2]) +} + +sub signal($$) { + AnyEvent->signal (signal => $_[0], cb => $_[1]) +} + +sub child($$) { + AnyEvent->child (pid => $_[0], cb => $_[1]) +} + +sub idle($) { + AnyEvent->idle (cb => $_[0]) +} + +sub cv(;&) { + AnyEvent->condvar (@_ ? (cb => $_[0]) : ()) +} + +sub now() { + AnyEvent->now +} + +sub now_update() { + AnyEvent->now_update +} + +sub time() { + AnyEvent->time +} + package AnyEvent::Base; # default implementations for many methods @@ -1350,13 +1402,13 @@ sub _sig_add() { unless ($SIG_COUNT++) { # try to align timer on a full-second boundary, if possible - my $NOW = AnyEvent->now; + my $NOW = AE::now; - $SIG_TW = AnyEvent->timer ( - after => $MAX_SIGNAL_LATENCY - ($NOW - int $NOW), - interval => $MAX_SIGNAL_LATENCY, - cb => sub { }, # just for the PERL_ASYNC_CHECK - ); + $SIG_TW = AE::timer + $MAX_SIGNAL_LATENCY - ($NOW - int $NOW), + $MAX_SIGNAL_LATENCY, + sub { } # just for the PERL_ASYNC_CHECK + ; } } @@ -1403,7 +1455,7 @@ warn "AnyEvent: using Async::Interrupt for race-free signal handling.\n" if $VERBOSE >= 8; $SIGPIPE_R = new Async::Interrupt::EventPipe; - $SIG_IO = AnyEvent->io (fh => $SIGPIPE_R->fileno, poll => "r", cb => \&_signal_exec); + $SIG_IO = AE::io $SIGPIPE_R->fileno, 0, \&_signal_exec; } else { warn "AnyEvent: using emulated perl signal handling with latency timer.\n" if $VERBOSE >= 8; @@ -1429,7 +1481,7 @@ $SIGPIPE_R or Carp::croak "AnyEvent: unable to create a signal reporting pipe: $!\n"; - $SIG_IO = AnyEvent->io (fh => $SIGPIPE_R, poll => "r", cb => \&_signal_exec); + $SIG_IO = AE::io $SIGPIPE_R, 0, \&_signal_exec; } *signal = sub { @@ -1528,7 +1580,7 @@ : eval { local $SIG{__DIE__}; require POSIX; &POSIX::WNOHANG } || 1; unless ($CHLD_W) { - $CHLD_W = AnyEvent->signal (signal => 'CHLD', cb => \&_sigchld); + $CHLD_W = AE::signal CHLD => \&_sigchld; # child could be a zombie already, so make at least one round &_sigchld; } @@ -1564,7 +1616,7 @@ $w = 0.0001 if $w < 0.0001; $w = 5 if $w > 5; - $w = AnyEvent->timer (after => $w, cb => $rcb); + $w = AE::timer $w, 0, $rcb; } else { # clean up... undef $w; @@ -1572,7 +1624,7 @@ } }; - $w = AnyEvent->timer (after => 0.05, cb => $rcb); + $w = AE::timer 0.05, 0, $rcb; bless \\$cb, "AnyEvent::Base::idle" } @@ -1642,6 +1694,7 @@ and $cv->{_ae_cb} = shift and $cv->{_ae_sent} and (delete $cv->{_ae_cb})->($cv); + $cv->{_ae_cb} } @@ -1659,48 +1712,6 @@ *broadcast = \&send; *wait = \&_wait; -############################################################################# -# "new" API, currently only emulation of it -############################################################################# - -package AE; - -sub io($$$) { - AnyEvent->io (fh => $_[0], poll => $_[1] ? "w" : "r", cb => $_[2]) -} - -sub timer($$$) { - AnyEvent->timer (after => $_[0], interval => $_[1], cb => $_[2]); -} - -sub signal($$) { - AnyEvent->signal (signal => $_[0], cb => $_[1]); -} - -sub child($$) { - AnyEvent->child (pid => $_[0], cb => $_[1]); -} - -sub idle($) { - AnyEvent->idle (cb => $_[0]); -} - -sub cv() { - AnyEvent->condvar -} - -sub now() { - AnyEvent->now -} - -sub now_update() { - AnyEvent->now_update -} - -sub time() { - AnyEvent->time -} - =head1 ERROR AND EXCEPTION HANDLING In general, AnyEvent does not do any error handling - it relies on the @@ -1903,16 +1914,9 @@ }, ); - my $time_watcher; # can only be used once - - sub new_timer { - $timer = AnyEvent->timer (after => 1, cb => sub { - warn "timeout\n"; # print 'timeout' about every second - &new_timer; # and restart the time - }); - } - - new_timer; # create first timer + my $time_watcher = AnyEvent->timer (after => 1, interval => 1, cb => sub { + warn "timeout\n"; # print 'timeout' at most every second + }); $cv->recv; # wait until user enters /^q/i @@ -2053,7 +2057,8 @@ which it is), lets them fire exactly once and destroys them again. Source code for this benchmark is found as F in the AnyEvent -distribution. +distribution. It uses the L interface, which makes a real difference +for the EV and Perl backends only. =head3 Explanation of the columns @@ -2084,18 +2089,18 @@ =head3 Results name watchers bytes create invoke destroy comment - EV/EV 400000 224 0.47 0.35 0.27 EV native interface - EV/Any 100000 224 2.88 0.34 0.27 EV + AnyEvent watchers - CoroEV/Any 100000 224 2.85 0.35 0.28 coroutines + Coro::Signal - Perl/Any 100000 452 4.13 0.73 0.95 pure perl implementation - Event/Event 16000 517 32.20 31.80 0.81 Event native interface - Event/Any 16000 590 35.85 31.55 1.06 Event + AnyEvent watchers - IOAsync/Any 16000 989 38.10 32.77 11.13 via IO::Async::Loop::IO_Poll - IOAsync/Any 16000 990 37.59 29.50 10.61 via IO::Async::Loop::Epoll - Glib/Any 16000 1357 102.33 12.31 51.00 quadratic behaviour - Tk/Any 2000 1860 27.20 66.31 14.00 SEGV with >> 2000 watchers - POE/Event 2000 6328 109.99 751.67 14.02 via POE::Loop::Event - POE/Select 2000 6027 94.54 809.13 579.80 via POE::Loop::Select + EV/EV 100000 223 0.47 0.43 0.27 EV native interface + EV/Any 100000 223 0.48 0.42 0.26 EV + AnyEvent watchers + Coro::EV/Any 100000 223 0.47 0.42 0.26 coroutines + Coro::Signal + Perl/Any 100000 431 2.70 0.74 0.92 pure perl implementation + Event/Event 16000 516 31.16 31.84 0.82 Event native interface + Event/Any 16000 1203 42.61 34.79 1.80 Event + AnyEvent watchers + IOAsync/Any 16000 1911 41.92 27.45 16.81 via IO::Async::Loop::IO_Poll + IOAsync/Any 16000 1726 40.69 26.37 15.25 via IO::Async::Loop::Epoll + Glib/Any 16000 1118 89.00 12.57 51.17 quadratic behaviour + Tk/Any 2000 1346 20.96 10.75 8.00 SEGV with >> 2000 watchers + POE/Any 2000 6951 108.97 795.32 14.24 via POE::Loop::Event + POE/Any 2000 6648 94.79 774.40 575.51 via POE::Loop::Select =head3 Discussion @@ -2117,9 +2122,10 @@ cycles with POE. C is the sole leader regarding speed and memory use, which are both -maximal/minimal, respectively. Even when going through AnyEvent, it uses -far less memory than any other event loop and is still faster than Event -natively. +maximal/minimal, respectively. When using the L API there is zero +overhead (when going through the AnyEvent API create is about 5-6 times +slower, with other times being equal, so still uses far less memory than +any other event loop and is still faster than Event natively). The pure perl implementation is hit in a few sweet spots (both the constant timeout and the use of a single fd hit optimisations in the perl @@ -2203,7 +2209,8 @@ connections, most of which are idle at any one point in time. Source code for this benchmark is found as F in the AnyEvent -distribution. +distribution. It uses the L interface, which makes a real difference +for the EV and Perl backends only. =head3 Explanation of the columns @@ -2221,13 +2228,13 @@ =head3 Results name sockets create request - EV 20000 69.01 11.16 - Perl 20000 73.32 35.87 - IOAsync 20000 157.00 98.14 epoll - IOAsync 20000 159.31 616.06 poll - Event 20000 212.62 257.32 - Glib 20000 651.16 1896.30 - POE 20000 349.67 12317.24 uses POE::Loop::Event + EV 20000 62.66 7.99 + Perl 20000 68.32 32.64 + IOAsync 20000 174.06 101.15 epoll + IOAsync 20000 174.67 610.84 poll + Event 20000 202.69 242.91 + Glib 20000 557.01 1689.52 + POE 20000 341.54 12086.32 uses POE::Loop::Event =head3 Discussion