AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Impl/IOAsync.pm view on Meta::CPAN
back when I learned that the only "async" aspect of it is the name).
=item Inconsistent, incomplete and convoluted API
Implementing AnyEvent's rather simple timers on top of IO::Async's timers
was a nightmare (try implementing a timer with configurable interval and
delay value...).
The method naming is chaotic: C<watch_child> creates a child watcher,
but C<watch_io> is an internal method; C<detach_signal> removes a signal
watcher, but C<detach_child> forks a subprocess and so on).
=item Unpleasant surprises on GNU/Linux
When you develop your program on FreeBSD and run it on GNU/Linux, you
might have unpleasant surprises, as IO::Async::Loop will by default use
L<IO::Async::Loop::Epoll>, which is incompatible with C<fork>, so your
network server will run into spurious and very hard to debug problems
under heavy load, as IO::Async forks a lot of processes, e.g. for DNS
resolution. It would be better if IO::Async would only load "safe"
backends by default (or fix the epoll backend to work in the presence of
fork, which admittedly is hard - EV does it for you, and also does not use
unsafe backends by default).
=back
On the positive side, performance with IO::Async is quite good even in my
very demanding eyes.
=cut
package AnyEvent::Impl::IOAsync;
use AnyEvent (); BEGIN { AnyEvent::common_sense }
use Time::HiRes ();
use Scalar::Util ();
use IO::Async::Loop 0.33;
our $LOOP = new IO::Async::Loop;
sub set_loop($) {
$LOOP = $_[0];
}
sub timer {
my ($class, %arg) = @_;
my $cb = $arg{cb};
my $id;
if (my $ival = $arg{interval}) {
my $ival_cb; $ival_cb = sub {
$id = $LOOP->enqueue_timer (delay => $ival, code => $ival_cb);
&$cb;
};
$id = $LOOP->enqueue_timer (delay => $arg{after}, code => $ival_cb);
# we have to weaken afterwards, but when enqueue dies, we have a memleak.
# still, we do anything for speed...
Scalar::Util::weaken $ival_cb;
} else {
# IO::Async has problems with overloaded objects
$id = $LOOP->enqueue_timer (delay => $arg{after}, code => sub {
undef $id; # IO::Async <= 0.43 bug workaround
&$cb;
});
}
bless \\$id, "AnyEvent::Impl::IOAsync::timer"
}
sub AnyEvent::Impl::IOAsync::timer::DESTROY {
# Need to be well-behaved during global destruction
$LOOP->cancel_timer (${${$_[0]}})
if defined ${${$_[0]}}; # IO::Async <= 0.43 bug workaround
}
sub io {
my ($class, %arg) = @_;
# Ensure we have a real IO handle, and not just a UNIX fd integer
my ($fh) = AnyEvent::_dupfh $arg{poll}, $arg{fh};
my $event = $arg{poll} eq "r" ? "on_read_ready" : "on_write_ready";
$LOOP->watch_io (
handle => $fh,
$event => $arg{cb},
);
bless [$fh, $event], "AnyEvent::Impl::IOAsync::io"
}
sub AnyEvent::Impl::IOAsync::io::DESTROY {
$LOOP->unwatch_io (
handle => $_[0][0],
$_[0][1] => 1,
);
}
sub signal {
my ($class, %arg) = @_;
my $signal = $arg{signal};
my $id = $LOOP->attach_signal ($arg{signal}, $arg{cb});
bless [$signal, $id], "AnyEvent::Impl::IOAsync::signal"
}
sub AnyEvent::Impl::IOAsync::signal::DESTROY {
$LOOP->detach_signal (@{ $_[0] });
}
our %pid_cb;
sub child {
my ($class, %arg) = @_;
my $pid = $arg{pid};
( run in 0.551 second using v1.01-cache-2.11-cpan-39bf76dae61 )