AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent.pm view on Meta::CPAN
sub croak {
$_[0]{_ae_croak} = $_[1];
$_[0]->send;
}
sub ready {
$_[0]{_ae_sent}
}
sub recv {
unless ($_[0]{_ae_sent}) {
$WAITING
and Carp::croak "AnyEvent::CondVar: recursive blocking wait attempted";
local $WAITING = 1;
$_[0]->_wait;
}
$_[0]{_ae_croak}
and Carp::croak $_[0]{_ae_croak};
wantarray
? @{ $_[0]{_ae_sent} }
: $_[0]{_ae_sent}[0]
}
sub cb {
my $cv = shift;
@_
and $cv->{_ae_cb} = shift
and $cv->{_ae_sent}
and (delete $cv->{_ae_cb})->($cv);
$cv->{_ae_cb}
}
sub begin {
++$_[0]{_ae_counter};
$_[0]{_ae_end_cb} = $_[1] if @_ > 1;
}
sub end {
return if --$_[0]{_ae_counter};
&{ $_[0]{_ae_end_cb} || sub { $_[0]->send } };
}
# undocumented/compatibility with pre-3.4
*broadcast = \&send;
*wait = \&recv;
=head1 ERROR AND EXCEPTION HANDLING
In general, AnyEvent does not do any error handling - it relies on the
caller to do that if required. The L<AnyEvent::Strict> module (see also
the C<PERL_ANYEVENT_STRICT> environment variable, below) provides strict
checking of all AnyEvent methods, however, which is highly useful during
development.
As for exception handling (i.e. runtime errors and exceptions thrown while
executing a callback), this is not only highly event-loop specific, but
also not in any way wrapped by this module, as this is the job of the main
program.
The pure perl event loop simply re-throws the exception (usually
within C<< condvar->recv >>), the L<Event> and L<EV> modules call C<<
$Event/EV::DIED->() >>, L<Glib> uses C<< install_exception_handler >> and
so on.
=head1 ENVIRONMENT VARIABLES
AnyEvent supports a number of environment variables that tune the
runtime behaviour. They are usually evaluated when AnyEvent is
loaded, initialised, or a submodule that uses them is loaded. Many of
them also cause AnyEvent to load additional modules - for example,
C<PERL_ANYEVENT_DEBUG_WRAP> causes the L<AnyEvent::Debug> module to be
loaded.
All the environment variables documented here start with
C<PERL_ANYEVENT_>, which is what AnyEvent considers its own
namespace. Other modules are encouraged (but by no means required) to use
C<PERL_ANYEVENT_SUBMODULE> if they have registered the AnyEvent::Submodule
namespace on CPAN, for any submodule. For example, L<AnyEvent::HTTP> could
be expected to use C<PERL_ANYEVENT_HTTP_PROXY> (it should not access env
variables starting with C<AE_>, see below).
All variables can also be set via the C<AE_> prefix, that is, instead
of setting C<PERL_ANYEVENT_VERBOSE> you can also set C<AE_VERBOSE>. In
case there is a clash btween anyevent and another program that uses
C<AE_something> you can set the corresponding C<PERL_ANYEVENT_something>
variable to the empty string, as those variables take precedence.
When AnyEvent is first loaded, it copies all C<AE_xxx> env variables
to their C<PERL_ANYEVENT_xxx> counterpart unless that variable already
exists. If taint mode is on, then AnyEvent will remove I<all> environment
variables starting with C<PERL_ANYEVENT_> from C<%ENV> (or replace them
with C<undef> or the empty string, if the corresaponding C<AE_> variable
is set).
The exact algorithm is currently:
1. if taint mode enabled, delete all PERL_ANYEVENT_xyz variables from %ENV
2. copy over AE_xyz to PERL_ANYEVENT_xyz unless the latter alraedy exists
3. if taint mode enabled, set all PERL_ANYEVENT_xyz variables to undef.
This ensures that child processes will not see the C<AE_> variables.
The following environment variables are currently known to AnyEvent:
=over 4
=item C<PERL_ANYEVENT_VERBOSE>
By default, AnyEvent will log messages with loglevel C<4> (C<error>) or
higher (see L<AnyEvent::Log>). 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<PERL_ANYEVENT_LOG>, which allows much more
complex specifications.
When set to C<0> (C<off>), then no messages whatsoever will be logged with
everything else at defaults.
When set to C<5> or higher (C<warn>), AnyEvent warns about unexpected
conditions, such as not being able to load the event model specified by
C<PERL_ANYEVENT_MODEL>, or a guard callback throwing an exception - this
is the minimum recommended level for use during development.
When set to C<7> or higher (info), AnyEvent reports which event model it
chooses.
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<PERL_ANYEVENT_LOG>
Accepts rather complex logging specifications. For example, you could log
all C<debug> messages of some module to stderr, warnings and above to
stderr, and errors and above to syslog, with:
PERL_ANYEVENT_LOG=Some::Module=debug,+log:filter=warn,+%syslog:%syslog=error,syslog
For the rather extensive details, see L<AnyEvent::Log>.
This variable is evaluated when AnyEvent (or L<AnyEvent::Log>) is loaded,
so will take effect even before AnyEvent has initialised itself.
Note that specifying this environment variable causes the L<AnyEvent::Log>
module to be loaded, while C<PERL_ANYEVENT_VERBOSE> does not, so only
using the latter saves a few hundred kB of memory unless a module
explicitly needs the extra features of AnyEvent::Log.
=item C<PERL_ANYEVENT_STRICT>
AnyEvent does not do much argument checking by default, as thorough
argument checking is very costly. Setting this variable to a true value
will cause AnyEvent to load C<AnyEvent::Strict> and then to thoroughly
check the arguments passed to most method calls. If it finds any problems,
it will croak.
In other words, enables "strict" mode.
Unlike C<use strict> (or its modern cousin, C<< use L<common::sense>
>>, it is definitely recommended to keep it off in production. Keeping
C<PERL_ANYEVENT_STRICT=1> in your environment while developing programs
can be very useful, however.
=item C<PERL_ANYEVENT_DEBUG_SHELL>
If this env variable is nonempty, then its contents will be interpreted by
C<AnyEvent::Socket::parse_hostport> and C<AnyEvent::Debug::shell> (after
replacing every occurance of C<$$> by the process pid). The shell object
is saved in C<$AnyEvent::Debug::SHELL>.
This happens when the first watcher is created.
For example, to bind a debug shell on a unix domain socket in
F<< /tmp/debug<pid>.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
lib/AnyEvent.pm view on Meta::CPAN
L<Net::FCP>, and it works as simple as in any other, similar, module.
More complicated is C<txn_client_get>: It only creates a transaction
(completion, result, ...) object and initiates the transaction.
my $txn = bless { }, Net::FCP::Txn::;
It also creates a condition variable that is used to signal the completion
of the request:
$txn->{finished} = AnyAvent->condvar;
It then creates a socket in non-blocking mode.
socket $txn->{fh}, ...;
fcntl $txn->{fh}, F_SETFL, O_NONBLOCK;
connect $txn->{fh}, ...
and !$!{EWOULDBLOCK}
and !$!{EINPROGRESS}
and Carp::croak "unable to connect: $!\n";
Then it creates a write-watcher which gets called whenever an error occurs
or the connection succeeds:
$txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'w', cb => sub { $txn->fh_ready_w });
And returns this transaction object. The C<fh_ready_w> callback gets
called as soon as the event loop detects that the socket is ready for
writing.
The C<fh_ready_w> method makes the socket blocking again, writes the
request data and replaces the watcher by a read watcher (waiting for reply
data). The actual code is more complicated, but that doesn't matter for
this example:
fcntl $txn->{fh}, F_SETFL, 0;
syswrite $txn->{fh}, $txn->{request}
or die "connection or write error";
$txn->{w} = AnyEvent->io (fh => $txn->{fh}, poll => 'r', cb => sub { $txn->fh_ready_r });
Again, C<fh_ready_r> waits till all data has arrived, and then stores the
result and signals any possible waiters that the request has finished:
sysread $txn->{fh}, $txn->{buf}, length $txn->{$buf};
if (end-of-file or data complete) {
$txn->{result} = $txn->{buf};
$txn->{finished}->send;
$txb->{cb}->($txn) of $txn->{cb}; # also call callback
}
The C<result> method, finally, just waits for the finished signal (if the
request was already finished, it doesn't wait, of course, and returns the
data:
$txn->{finished}->recv;
return $txn->{result};
The actual code goes further and collects all errors (C<die>s, exceptions)
that occurred during request processing. The C<result> method detects
whether an exception as thrown (it is stored inside the $txn object)
and just throws the exception, which means connection errors and other
problems get reported to the code that tries to use the result, not in a
random callback.
All of this enables the following usage styles:
1. Blocking:
my $data = $fcp->client_get ($url);
2. Blocking, but running in parallel:
my @datas = map $_->result,
map $fcp->txn_client_get ($_),
@urls;
Both blocking examples work without the module user having to know
anything about events.
3a. Event-based in a main program, using any supported event module:
use EV;
$fcp->txn_client_get ($url)->cb (sub {
my $txn = shift;
my $data = $txn->result;
...
});
EV::run;
3b. The module user could use AnyEvent, too:
use AnyEvent;
my $quit = AnyEvent->condvar;
$fcp->txn_client_get ($url)->cb (sub {
...
$quit->send;
});
$quit->recv;
=head1 BENCHMARKS
To give you an idea of the performance and overheads that AnyEvent adds
over the event loops themselves and to give you an impression of the speed
of various event loops I prepared some benchmarks.
=head2 BENCHMARKING ANYEVENT OVERHEAD
Here is a benchmark of various supported event models used natively and
through AnyEvent. The benchmark creates a lot of timers (with a zero
timeout) and I/O watchers (watching STDOUT, a pty, to become writable,
which it is), lets them fire exactly once and destroys them again.
Source code for this benchmark is found as F<eg/bench> in the AnyEvent
distribution. It uses the L<AE> interface, which makes a real difference
for the EV and Perl backends only.
( run in 1.335 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )