--- AnyEvent/lib/AnyEvent.pm 2009/12/26 08:59:35 1.309 +++ AnyEvent/lib/AnyEvent.pm 2010/02/15 18:02:35 1.312 @@ -1158,7 +1158,7 @@ use Carp (); -our $VERSION = '5.23'; +our $VERSION = '5.24'; our $MODEL; our $AUTOLOAD; @@ -1169,8 +1169,9 @@ our $VERBOSE; BEGIN { - eval "sub WIN32(){ " . (($^O =~ /mswin32/i)*1) ." }"; - eval "sub TAINT(){ " . (${^TAINT}*1) . " }"; + eval "sub CYGWIN(){" . (($^O =~ /cygwin/i) *1) . "}"; + eval "sub WIN32 (){" . (($^O =~ /mswin32/i)*1) . "}"; + eval "sub TAINT (){" . (${^TAINT} *1) . "}"; delete @ENV{grep /^PERL_ANYEVENT_/, keys %ENV} if ${^TAINT}; @@ -1241,61 +1242,64 @@ } 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"; + @models = (); # free probe data - unshift @ISA, $MODEL; + push @{"$MODEL\::ISA"}, "AnyEvent::Base"; + unshift @ISA, $MODEL; - require AnyEvent::Strict if $ENV{PERL_ANYEVENT_STRICT}; + require AnyEvent::Strict if $ENV{PERL_ANYEVENT_STRICT}; - (shift @post_detect)->() while @post_detect; - } + (shift @post_detect)->() while @post_detect; $MODEL } @@ -1304,9 +1308,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 (@_); @@ -1384,15 +1388,18 @@ # 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 - } + 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; + *_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 + } + }; + die if $@; &_time } @@ -1423,20 +1430,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 @@ -1577,8 +1572,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 } @@ -1589,6 +1598,7 @@ our $CHLD_DELAY_W; our $WNOHANG; +# used by many Impl's sub _emit_childstatus($$) { my (undef, $rpid, $rstatus) = @_; @@ -1597,78 +1607,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;