--- AnyEvent/lib/AnyEvent.pm 2011/08/04 09:14:01 1.352 +++ AnyEvent/lib/AnyEvent.pm 2011/08/14 01:57:18 1.362 @@ -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::FLTK based on FLTK. + AnyEvent::Impl::FLTK2 based on FLTK (fltk 2 binding). =item Backends with special needs. @@ -936,6 +936,10 @@ have created an AnyEvent watcher anyway, that is, as late as possible at runtime, and not e.g. during initialisation of your module. +The effect of calling this function is as if a watcher had been created +(specifically, actions that happen "when the first watcher is created" +happen when calling detetc as well). + If you need to do some initialisation before AnyEvent watchers are created, use C. @@ -1007,6 +1011,46 @@ push @AnyEvent::post_detect, sub { require Coro::AnyEvent }; } +=item AnyEvent::postpone { BLOCK } + +Arranges for the block to be executed as soon as possible, but not before +the call itself returns. In practise, the block will be executed just +before the event loop polls for new events, or shortly afterwards. + +This function never returns anything (to make the C idiom more useful. + +To understand the usefulness of this function, consider a function that +asynchronously does something for you and returns some transaction +object or guard to let you cancel the operation. For example, +C: + + # start a conenction attempt unless one is active + $self->{connect_guard} ||= AnyEvent::Socket::tcp_connect "www.example.net", 80, sub { + delete $self->{connect_guard}; + ... + }; + +Imagine that this function could instantly call the callback, for +example, because it detects an obvious error such as a negative port +number. Invoking the callback before the function returns causes problems +however: the callback will be called and will try to delete the guard +object. But since the function hasn't returned yet, there is nothing to +delete. When the function eventually returns it will assign the guard +object to C<< $self->{connect_guard} >>, where it will likely never be +deleted, so the program thinks it is still trying to connect. + +This is where C should be used. Instead of calling the +callback directly on error: + + $cb->(undef), return # signal error to callback, BAD! + if $some_error_condition; + +It should use C: + + AnyEvent::postpone { $cb->(undef) }, return # signal error to callback, later + if $some_error_condition; + =back =head1 WHAT TO DO IN A MODULE @@ -1164,10 +1208,9 @@ use Carp (); -our $VERSION = '5.34'; +our $VERSION = '6.01'; our $MODEL; -our $AUTOLOAD; our @ISA; our @REGISTRY; @@ -1197,7 +1240,41 @@ $ENV{PERL_ANYEVENT_PROTOCOLS} || "ipv4,ipv6"; } -my @models = ( +our @post_detect; + +sub post_detect(&) { + my ($cb) = @_; + + push @post_detect, $cb; + + defined wantarray + ? bless \$cb, "AnyEvent::Util::postdetect" + : () +} + +sub AnyEvent::Util::postdetect::DESTROY { + @post_detect = grep $_ != ${$_[0]}, @post_detect; +} + +our $POSTPONE_W; +our @POSTPONE; + +sub _postpone_exec { + undef $POSTPONE_W; + + &{ shift @POSTPONE } + while @POSTPONE; +} + +sub postpone(&) { + push @POSTPONE, shift; + + $POSTPONE_W ||= AE::timer (0, 0, \&_postpone_exec); + + () +} + +our @models = ( [EV:: => AnyEvent::Impl::EV:: , 1], [AnyEvent::Loop:: => AnyEvent::Impl::Perl:: , 1], # everything below here will not (normally) be autoprobed @@ -1212,39 +1289,53 @@ [POE::Kernel:: => AnyEvent::Impl::POE::], # lasciate ogni speranza [Wx:: => AnyEvent::Impl::POE::], [Prima:: => AnyEvent::Impl::POE::], - [IO::Async::Loop:: => AnyEvent::Impl::IOAsync::], + [IO::Async::Loop:: => AnyEvent::Impl::IOAsync::], # a bitch to autodetect [Cocoa::EventLoop:: => AnyEvent::Impl::Cocoa::], - [FLTK:: => AnyEvent::Impl::FLTK::], + [FLTK:: => AnyEvent::Impl::FLTK2::], ); -our %method = map +($_ => 1), - qw(io timer time now now_update signal child idle condvar DESTROY); +our @isa_hook; -our @post_detect; +sub _isa_set { + my @pkg = ("AnyEvent", (map $_->[0], grep defined, @isa_hook), $MODEL); -sub post_detect(&) { - my ($cb) = @_; + @{"$pkg[$_-1]::ISA"} = $pkg[$_] + for 1 .. $#pkg; - push @post_detect, $cb; - - defined wantarray - ? bless \$cb, "AnyEvent::Util::postdetect" - : () + grep $_ && $_->[1], @isa_hook + and AE::_reset (); } -sub AnyEvent::Util::postdetect::DESTROY { - @post_detect = grep $_ != ${$_[0]}, @post_detect; +# used for hooking AnyEvent::Strict and AnyEvent::Debug::Wrap into the class hierarchy +sub _isa_hook($$;$) { + my ($i, $pkg, $reset_ae) = @_; + + $isa_hook[$i] = $pkg ? [$pkg, $reset_ae] : undef; + + _isa_set; } -sub detect() { - # free some memory - *detect = sub () { $MODEL }; +# all autoloaded methods reserve the complete glob, not just the method slot. +# due to bugs in perls method cache implementation. +our @methods = qw(io timer time now now_update signal child idle condvar); +sub detect() { local $!; # for good measure - local $SIG{__DIE__}; + local $SIG{__DIE__}; # we use eval - if ($ENV{PERL_ANYEVENT_MODEL} =~ /^([a-zA-Z]+)$/) { - my $model = "AnyEvent::Impl::$1"; + # free some memory + *detect = sub () { $MODEL }; + # undef &func doesn't correctly update the method cache. grmbl. + # so we delete the whole glob. grmbl. + # otoh, perl doesn't let me undef an active usb, but it lets me free + # a glob with an active sub. hrm. i hope it works, but perl is + # usually buggy in this department. sigh. + delete @{"AnyEvent::"}{@methods}; + undef @methods; + + if ($ENV{PERL_ANYEVENT_MODEL} =~ /^([a-zA-Z0-9:]+)$/) { + my $model = $1; + $model = "AnyEvent::Impl::$model" unless $model =~ s/::$//; if (eval "require $model") { $MODEL = $model; warn "AnyEvent: loaded model '$model' (forced by \$ENV{PERL_ANYEVENT_MODEL}), using it.\n" if $VERBOSE >= 2; @@ -1287,25 +1378,43 @@ } } - @models = (); # free probe data + # free memory only needed for probing + undef @models; + undef @REGISTRY; push @{"$MODEL\::ISA"}, "AnyEvent::Base"; - unshift @ISA, $MODEL; # now nuke some methods that are overridden by the backend. - # SUPER is not allowed. + # SUPER usage is not allowed in these. for (qw(time signal child idle)) { undef &{"AnyEvent::Base::$_"} if defined &{"$MODEL\::$_"}; } + _isa_set; + if ($ENV{PERL_ANYEVENT_STRICT}) { - eval { require AnyEvent::Strict }; - warn "AnyEvent: cannot load AnyEvent::Strict: $@" - if $@ && $VERBOSE; + require AnyEvent::Strict; + } + + if ($ENV{PERL_ANYEVENT_DEBUG_WRAP}) { + require AnyEvent::Debug; + AnyEvent::Debug::wrap ($ENV{PERL_ANYEVENT_DEBUG_WRAP}); + } + + if (exists $ENV{PERL_ANYEVENT_DEBUG_SHELL}) { + require AnyEvent::Socket; + require AnyEvent::Debug; + + my $shell = $ENV{PERL_ANYEVENT_DEBUG_SHELL}; + $shell =~ s/\$\$/$$/g; + + my ($host, $service) = AnyEvent::Socket::parse_hostport ($shell); + $AnyEvent::Debug::SHELL = AnyEvent::Debug::shell ($host, $service); } (shift @post_detect)->() while @post_detect; + undef @post_detect; *post_detect = sub(&) { shift->(); @@ -1316,16 +1425,14 @@ $MODEL } -sub AUTOLOAD { - (my $func = $AUTOLOAD) =~ s/.*://; - - $method{$func} - or Carp::croak "$func: not a valid AnyEvent class method"; - - detect; - - my $class = shift; - $class->$func (@_); +for my $name (@methods) { + *$name = sub { + detect; + # we use goto because + # a) it makes the thunk more transparent + # b) it allows us to delete the thunk later + goto &{ UNIVERSAL::can AnyEvent => "SUPER::$name" } + }; } # utility function to dup a filehandle. this is used by many backends @@ -1359,45 +1466,54 @@ our $VERSION = $AnyEvent::VERSION; -# fall back to the main API by default - backends and AnyEvent::Base -# implementations can overwrite these. +sub _reset() { + eval q{ + # 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]) -} + sub io($$$) { + AnyEvent->io (fh => $_[0], poll => $_[1] ? "w" : "r", cb => $_[2]) + } -sub timer($$$) { - AnyEvent->timer (after => $_[0], interval => $_[1], cb => $_[2]) -} + sub timer($$$) { + AnyEvent->timer (after => $_[0], interval => $_[1], cb => $_[2]) + } -sub signal($$) { - AnyEvent->signal (signal => $_[0], cb => $_[1]) -} + sub signal($$) { + AnyEvent->signal (signal => $_[0], cb => $_[1]) + } -sub child($$) { - AnyEvent->child (pid => $_[0], cb => $_[1]) -} + sub child($$) { + AnyEvent->child (pid => $_[0], cb => $_[1]) + } -sub idle($) { - AnyEvent->idle (cb => $_[0]) -} + sub idle($) { + AnyEvent->idle (cb => $_[0]); + } -sub cv(;&) { - AnyEvent->condvar (@_ ? (cb => $_[0]) : ()) -} + sub cv(;&) { + AnyEvent->condvar (@_ ? (cb => $_[0]) : ()) + } -sub now() { - AnyEvent->now -} + sub now() { + AnyEvent->now + } -sub now_update() { - AnyEvent->now_update -} + sub now_update() { + AnyEvent->now_update + } + + sub time() { + AnyEvent->time + } -sub time() { - AnyEvent->time + *postpone = \&AnyEvent::postpone; + }; + die if $@; } +BEGIN { _reset } + package AnyEvent::Base; # default implementations for many methods @@ -1407,14 +1523,16 @@ # 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; + *time = sub { Time::HiRes::time () }; + *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 { CORE::time }; + *AE::time = sub (){ CORE::time }; } - *time = sub { AE::time }; # different prototypes + *now = \&time; }; die if $@; @@ -1422,7 +1540,6 @@ } *now = \&time; - sub now_update { } sub _poll { @@ -1430,7 +1547,7 @@ } # default implementation for ->condvar -# in fact,t he default should not be overwritten +# in fact, the default should not be overwritten sub condvar { eval q{ # poor man's autoloading {} @@ -1610,7 +1727,7 @@ while (%SIG_EV) { for (keys %SIG_EV) { delete $SIG_EV{$_}; - $_->() for values %{ $SIG_CB{$_} || {} }; + &$_ for values %{ $SIG_CB{$_} || {} }; } } }; @@ -1687,9 +1804,9 @@ $rcb = sub { if ($cb) { - $w = _time; + $w = AE::time; &$cb; - $w = _time - $w; + $w = AE::time - $w; # never use more then 50% of the time for the idle watcher, # within some limits @@ -1868,16 +1985,42 @@ C in your environment while developing programs can be very useful, however. +=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>. + +This takes place 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=unix/:/tmp/debug\$\$.sock perlprog + +Note that creating sockets in F is very unsafe on multiuser +systems. + +=item C + +Can be set to C<0>, C<1> or C<2> and enables wrapping of all watchers for +debugging purposes. See C for details. + =item C This can be used to specify the event model to be used by AnyEvent, before -auto detection and -probing kicks in. It must be a string consisting -entirely of ASCII letters. The string C gets prepended -and the resulting module name is loaded and if the load was successful, -used as event model. If it fails to load AnyEvent will proceed with +auto detection and -probing kicks in. + +It normally is a string consisting entirely of ASCII letters (e.g. C +or C). The string C gets prepended and the +resulting module name is loaded and - if the load was successful - used as +event model backend. If it fails to load then AnyEvent will proceed with auto detection and -probing. -This functionality might change in future versions. +If the string ends with C<::> instead (e.g. C) then +nothing gets prepended and the module name is used as-is (hint: C<::> at +the end of a string designates a module name and quotes it appropriately). For example, to force the pure perl model (L) you could start your program like this: @@ -2279,7 +2422,7 @@ =item * The overhead AnyEvent adds is usually much smaller than the overhead of the actual event loop, only with extremely fast event loops such as EV -adds AnyEvent significant overhead. +does AnyEvent add significant overhead. =item * You should avoid POE like the plague if you want performance or reasonable memory usage.