--- AnyEvent/lib/AnyEvent.pm 2011/08/25 03:08:48 1.373 +++ AnyEvent/lib/AnyEvent.pm 2011/09/05 07:21:54 1.384 @@ -880,7 +880,7 @@ AnyEvent::Impl::Irssi used when running within irssi. AnyEvent::Impl::IOAsync based on IO::Async. AnyEvent::Impl::Cocoa based on Cocoa::EventLoop. - AnyEvent::Impl::FLTK2 based on FLTK (fltk 2 binding). + AnyEvent::Impl::FLTK based on FLTK (fltk 2 binding). =item Backends with special needs. @@ -1055,11 +1055,19 @@ Log the given C<$msg> at the given C<$level>. -Loads AnyEvent::Log on first use and calls C - -consequently, look at the L documentation for details. +If L is not loaded then this function makes a simple test +to see whether the message will be logged. If the test succeeds it will +load AnyEvent::Log and call C - consequently, look at +the L documentation for details. + +If the test fails it will simply return. Right now this happens when a +numerical loglevel is used and it is larger than the level specified via +C<$ENV{PERL_ANYEVENT_VERBOSE}>. If you want to sprinkle loads of logging calls around your code, consider -creating a logger callback with the C function. +creating a logger callback with the C function, +which can reduce typing, codesize and can reduce the logging overhead +enourmously. =back @@ -1162,35 +1170,31 @@ the curious, IGS is the International Go Server and FCP is the Freenet Client Protocol). -=item L +=item L + +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. -Here be danger! +=item L -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 -its 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. +AnyEvent is good for non-blocking stuff, but it can't detect file or +path changes (e.g. "watch this directory for new files", "watch this +file for changes"). The L module promises to +do just that in a portbale fashion, supporting inotify on GNU/Linux and +some weird, without doubt broken, stuff on OS X to monitor files. It can +fall back to blocking scans at regular intervals transparently on other +platforms, so it's about as portable as it gets. + +(I haven't used it myself, but I haven't heard anybody complaining about +it yet). =item L Executes L requests asynchronously in a proxy process for you, notifying you in an event-based way when the operation is finished. -=item L - -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 A simple embedded webserver. @@ -1201,7 +1205,19 @@ =item L -Has special support for AnyEvent via L. +Has special support for AnyEvent via L, which allows you +to simply invert the flow control - don't call us, we will call you: + + async { + Coro::AnyEvent::sleep 5; # creates a 5s timer and waits for it + print "5 seconds later!\n"; + + Coro::AnyEvent::readable *STDIN; # uses an I/O watcher + my $line = ; # works for ttys + + AnyEvent::HTTP::http_get "url", Coro::rouse_cb; + my ($body, $hdr) = Coro::rouse_wait; + }; =back @@ -1221,14 +1237,13 @@ use Carp (); -our $VERSION = '6.01'; +our $VERSION = '6.02'; our $MODEL; - our @ISA; - our @REGISTRY; - our $VERBOSE; +our $MAX_SIGNAL_LATENCY = 10; +our %PROTOCOL; # (ipv4|ipv6) => (1|2), higher numbers are preferred BEGIN { require "AnyEvent/constants.pl"; @@ -1244,14 +1259,10 @@ @ENV{grep /^PERL_ANYEVENT_/, keys %ENV} = () if ${^TAINT}; - $VERBOSE = $ENV{PERL_ANYEVENT_VERBOSE}*1; -} - -our $MAX_SIGNAL_LATENCY = 10; + # $ENV{PERL_ANYEVENT_xxx} now valid -our %PROTOCOL; # (ipv4|ipv6) => (1|2), higher numbers are preferred + $VERBOSE = length $ENV{PERL_ANYEVENT_VERBOSE} ? $ENV{PERL_ANYEVENT_VERBOSE}*1 : 4; -{ my $idx; $PROTOCOL{$_} = ++$idx for reverse split /\s*,\s*/, @@ -1293,12 +1304,44 @@ } sub log($$;@) { - # only load the bug bloated module when we actually are about to log something - if ($_[0] <= $VERBOSE) { - require AnyEvent::Log; + # only load the big bloated module when we actually are about to log something + if ($_[0] <= ($VERBOSE || 1)) { # also catches non-numeric levels(!) and fatal + require AnyEvent::Log; # among other things, sets $VERBOSE to 9 # AnyEvent::Log overwrites this function goto &log; } + + 0 # not logged +} + +sub logger($;$) { + package AnyEvent::Log; + + my ($level, $renabled) = @_; + + $$renabled = $level <= $VERBOSE; + + my $pkg = (caller)[0]; + + my $logger = [$pkg, $level, $renabled]; + + our %LOGGER; + $LOGGER{$logger+0} = $logger; + + require AnyEvent::Util; + my $guard = AnyEvent::Util::guard (sub { + # "clean up" + delete $LOGGER{$logger+0}; + }); + + sub { + return 0 unless $$renabled; + + $guard if 0; # keep guard alive, but don't cause runtime overhead + require AnyEvent::Log unless $AnyEvent::Log::VERSION; + package AnyEvent::Log; + _log ($logger->[0], $level, @_) # logger->[0] has been converted at load time + } } if (length $ENV{PERL_ANYEVENT_LOG}) { @@ -1322,7 +1365,7 @@ [Prima:: => AnyEvent::Impl::POE::], [IO::Async::Loop:: => AnyEvent::Impl::IOAsync::], # a bitch to autodetect [Cocoa::EventLoop:: => AnyEvent::Impl::Cocoa::], - [FLTK:: => AnyEvent::Impl::FLTK2::], + [FLTK:: => AnyEvent::Impl::FLTK::], ); our @isa_hook; @@ -1373,7 +1416,7 @@ AnyEvent::log 7 => "loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it."; $MODEL = $model; } else { - AnyEvent::log warn => "unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@"; + AnyEvent::log 4 => "unable to load model '$model' (from \$ENV{PERL_ANYEVENT_MODEL}):\n$@"; } } @@ -1407,7 +1450,7 @@ } $MODEL - or die "AnyEvent: backend autodetection failed - did you properly install AnyEvent?"; + or AnyEvent::log fatal => "AnyEvent: backend autodetection failed - did you properly install AnyEvent?"; } } @@ -1561,18 +1604,17 @@ eval q{ # poor man's autoloading {} # probe for availability of Time::HiRes if (eval "use Time::HiRes (); Time::HiRes::time (); 1") { - AnyEvent::log 8 => "AnyEvent: using Time::HiRes for sub-second timing accuracy." - if $AnyEvent::VERBOSE >= 8; *time = sub { Time::HiRes::time () }; *AE::time = \& Time::HiRes::time ; + *now = \&time; + AnyEvent::log 8 => "AnyEvent: using Time::HiRes for sub-second timing accuracy."; # if (eval "use POSIX (); (POSIX::times())... } else { - AnyEvent::log critical => "using built-in time(), WARNING, no sub-second resolution!"; *time = sub { CORE::time }; *AE::time = sub (){ CORE::time }; + *now = \&time; + AnyEvent::log 3 => "using built-in time(), WARNING, no sub-second resolution!"; } - - *now = \&time; }; die if $@; @@ -1675,15 +1717,13 @@ eval q{ # poor man's autoloading {} # probe for availability of Async::Interrupt if (_have_async_interrupt) { - AnyEvent::log 8 => "using Async::Interrupt for race-free signal handling." - if $AnyEvent::VERBOSE >= 8; + AnyEvent::log 8 => "using Async::Interrupt for race-free signal handling."; $SIGPIPE_R = new Async::Interrupt::EventPipe; $SIG_IO = AE::io $SIGPIPE_R->fileno, 0, \&_signal_exec; } else { - AnyEvent::log 8 => "using emulated perl signal handling with latency timer." - if $AnyEvent::VERBOSE >= 8; + AnyEvent::log 8 => "using emulated perl signal handling with latency timer."; if (AnyEvent::WIN32) { require AnyEvent::Util; @@ -2029,20 +2069,27 @@ =item C -By default, AnyEvent will be completely silent except in fatal -conditions. You can set this environment variable to make AnyEvent more -talkative. If you want to do more than just set the global logging level +By default, AnyEvent will only log messages with loglevel C<3> +(C) or higher (see L). You can set this +environment variable to a numerical loglevel to make AnyEvent more (or +less) talkative. + +If you want to do more than just set the global logging level you should have a look at C, which allows much more complex specifications. -When set to C<5> or higher, causes AnyEvent to warn about unexpected -conditions, such as not being able to load the event model specified by -C. +When set to C<0> (C), then no messages whatsoever will be logged with +the default logging settings. + +When set to C<5> or higher (C), causes AnyEvent to warn about +unexpected conditions, such as not being able to load the event model +specified by C, or a guard callback throwing an +exception - this is the minimum recommended level. -When set to C<7> or higher, cause AnyEvent to report to STDERR which event -model it chooses. +When set to C<7> or higher (info), cause AnyEvent to report which event model it +chooses. -When set to C<8> or higher, then AnyEvent will report extra information on +When set to C<8> or higher (debug), then AnyEvent will report extra information on which optional modules it loads and how it implements certain features. =item C @@ -2055,6 +2102,9 @@ For the rather extensive details, see L. +This variable is evaluated when AnyEvent (or L) is loaded, +so will take effect even before AnyEvent has initialised itself. + Note that specifying this environment variable causes the L module to be loaded, while C does not, so only using the latter saves a few hundred kB of memory until the first message @@ -2077,20 +2127,26 @@ =item C -If this env variable is set, then its contents will be interpreted by -C (after replacing every occurance of -C<$$> by the process pid) and an C is bound on -that port. The shell object is saved in C<$AnyEvent::Debug::SHELL>. +If this env variable is nonempty, then its contents will be interpreted by +C and C (after +replacing every occurance of C<$$> by the process pid). The shell object +is saved in C<$AnyEvent::Debug::SHELL>. -This takes place when the first watcher is created. +This happens when the first watcher is created. For example, to bind a debug shell on a unix domain socket in F<< /tmp/debug.sock >>, you could use this: PERL_ANYEVENT_DEBUG_SHELL=/tmp/debug\$\$.sock perlprog + # connect with e.g.: socat readline /tmp/debug123.sock + +Or to bind to tcp port 4545 on localhost: + + PERL_ANYEVENT_DEBUG_SHELL=127.0.0.1:4545 perlprog + # connect with e.g.: telnet localhost 4545 -Note that creating sockets in F is very unsafe on multiuser -systems. +Note that creating sockets in F or on localhost is very unsafe on +multiuser systems. =item C