AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Intro.pod view on Meta::CPAN
there he doesn't have to choose, he can just let L<AnyEvent> choose the
most efficient event loop available on the system.
Read more about this in the main documentation of the L<AnyEvent> module.
=head1 Introduction to Event-Based Programming
So what exactly is programming using events? It quite simply means that
instead of your code actively waiting for something, such as the user
entering something on STDIN:
$| = 1; print "enter your name> ";
my $name = <STDIN>;
You instead tell your event framework to notify you in the event of some
data being available on STDIN, by using a callback mechanism:
use AnyEvent;
$| = 1; print "enter your name> ";
my $name;
my $wait_for_input = AnyEvent->io (
fh => \*STDIN, # which file handle to check
poll => "r", # which event to wait for ("r"ead data)
cb => sub { # what callback to execute
$name = <STDIN>; # read it
}
);
# do something else here
Looks more complicated, and surely is, but the advantage of using events
is that your program can do something else instead of waiting for input
(side note: combining AnyEvent with a thread package such as Coro can
recoup much of the simplicity, effectively getting the best of two
worlds).
Waiting as done in the first example is also called "blocking" the process
because you "block"/keep your process from executing anything else while
you do so.
The second example avoids blocking by only registering interest in a read
event, which is fast and doesn't block your process. The callback will
be called only when data is available and can be read without blocking.
The "interest" is represented by an object returned by C<< AnyEvent->io
>> called a "watcher" object - thus named because it "watches" your
file handle (or other event sources) for the event you are interested in.
In the example above, we create an I/O watcher by calling the C<<
AnyEvent->io >> method. A lack of further interest in some event is
expressed by simply forgetting about its watcher, for example by
C<undef>-ing the only variable it is stored in. AnyEvent will
automatically clean up the watcher if it is no longer used, much like
Perl closes your file handles if you no longer use them anywhere.
=head3 A short note on callbacks
A common issue that hits people is the problem of passing parameters
to callbacks. Programmers used to languages such as C or C++ are often
used to a style where one passes the address of a function (a function
reference) and some data value, e.g.:
sub callback {
my ($arg) = @_;
$arg->method;
}
my $arg = ...;
call_me_back_later \&callback, $arg;
This is clumsy, as the place where behaviour is specified (when the
callback is registered) is often far away from the place where behaviour
is implemented. It also doesn't use Perl syntax to invoke the code. There
is also an abstraction penalty to pay as one has to I<name> the callback,
which often is unnecessary and leads to nonsensical or duplicated names.
In Perl, one can specify behaviour much more directly by using
I<closures>. Closures are code blocks that take a reference to the
enclosing scope(s) when they are created. This means lexical variables
in scope when a closure is created can be used inside the closure:
my $arg = ...;
call_me_back_later sub { $arg->method };
Under most circumstances, closures are faster, use fewer resources and
result in much clearer code than the traditional approach. Faster,
because parameter passing and storing them in local variables in Perl
is relatively slow. Fewer resources, because closures take references
to existing variables without having to create new ones, and clearer
code because it is immediately obvious that the second example calls the
C<method> method when the callback is invoked.
Apart from these, the strongest argument for using closures with AnyEvent
is that AnyEvent does not allow passing parameters to the callback, so
closures are the only way to achieve that in most cases :->
=head3 A little hint to catch mistakes
AnyEvent does not check the parameters you pass in, at least not by
default. to enable checking, simply start your program with C<AE_STRICT=1>
in the environment, or put C<use AnyEvent::Strict> near the top of your
program:
AE_STRICT=1 perl myprogram
You can find more info on this and additional debugging aids later in this
introduction.
=head2 Condition Variables
Back to the I/O watcher example: The code is not yet a fully working
program, and will not work as-is. The reason is that your callback will
not be invoked out of the blue; you have to run the event loop first.
Also, event-based programs need to block sometimes too, such as when
there is nothing to do, and everything is waiting for new events to
arrive.
In AnyEvent, this is done using condition variables. Condition variables
are named "condition variables" because they represent a condition that is
initially false and needs to be fulfilled.
You can also call them "merge points", "sync points", "rendezvous ports"
or even callbacks and many other things (and they are often called these
names in other frameworks). The important point is that you can create them
freely and later wait for them to become true.
Condition variables have two sides - one side is the "producer" of the
condition (whatever code detects and flags the condition), the other side
is the "consumer" (the code that waits for that condition).
In our example in the previous section, the producer is the event callback
and there is no consumer yet - let's change that right now:
use AnyEvent;
$| = 1; print "enter your name> ";
my $name;
my $name_ready = AnyEvent->condvar;
my $wait_for_input = AnyEvent->io (
fh => \*STDIN,
poll => "r",
cb => sub {
$name = <STDIN>;
$name_ready->send;
}
);
# do something else here
# now wait until the name is available:
$name_ready->recv;
undef $wait_for_input; # watcher no longer needed
print "your name is $name\n";
This program creates an AnyEvent condvar by calling the C<<
AnyEvent->condvar >> method. It then creates a watcher as usual, but
inside the callback it C<send>s the C<$name_ready> condition variable,
which causes whoever is waiting on it to continue.
The "whoever" in this case is the code that follows, which calls C<<
$name_ready->recv >>: The producer calls C<send>, the consumer calls
C<recv>.
If there is no C<$name> available yet, then the call to C<<
$name_ready->recv >> will halt your program until the condition becomes
true.
As the names C<send> and C<recv> imply, you can actually send and receive
data using this, for example, the above code could also be written like
this, without an extra variable to store the name in:
use AnyEvent;
$| = 1; print "enter your name> ";
my $name_ready = AnyEvent->condvar;
my $wait_for_input = AnyEvent->io (
lib/AnyEvent/Intro.pod view on Meta::CPAN
my $window = new Gtk2::Window "toplevel";
$window->add (my $label = new Gtk2::Label "soon replaced by name");
$window->show_all;
############################################
# do our AnyEvent stuff
$| = 1; print "enter your name> ";
my $wait_for_input = AnyEvent->io (
fh => \*STDIN, poll => "r",
cb => sub {
# set the label
$label->set_text (scalar <STDIN>);
print "enter another name> ";
}
);
############################################
# Now enter Gtk2's event loop
main Gtk2;
No condition variable anywhere in sight - instead, we just read a line
from STDIN and replace the text in the label. In fact, since nobody
C<undef>s C<$wait_for_input> you can enter multiple lines.
Instead of waiting for a condition variable, the program enters the Gtk2
main loop by calling C<< Gtk2->main >>, which will block the program and
wait for events to arrive.
This also shows that AnyEvent is quite flexible - you didn't have to do
anything to make the AnyEvent watcher use Gtk2 (actually Glib) - it just
worked.
Admittedly, the example is a bit silly - who would want to read names
from standard input in a Gtk+ application? But imagine that instead of
doing that, you make an HTTP request in the background and display its
results. In fact, with event-based programming you can make many
HTTP requests in parallel in your program and still provide feedback to
the user and stay interactive.
And in the next part you will see how to do just that - by implementing an
HTTP request, on our own, with the utility modules AnyEvent comes with.
Before that, however, let's briefly look at how you would write your
program using only AnyEvent, without ever calling some other event
loop's run function.
In the example using condition variables, we used those to start waiting
for events, and in fact, condition variables are the solution:
my $quit_program = AnyEvent->condvar;
# create AnyEvent watchers (or not) here
$quit_program->recv;
If any of your watcher callbacks decide to quit (this is often
called an "unloop" in other frameworks), they can just call C<<
$quit_program->send >>. Of course, they could also decide not to and
call C<exit> instead, or they could decide never to quit (e.g. in a
long-running daemon program).
If you don't need some clean quit functionality and just want to run the
event loop, you can do this:
AnyEvent->condvar->recv;
And this is, in fact, the closest to the idea of a main loop run
function that AnyEvent offers.
=head2 Timers and other event sources
So far, we have used only I/O watchers. These are useful mainly to find
out whether a socket has data to read, or space to write more data. On sane
operating systems this also works for console windows/terminals (typically
on standard input), serial lines, all sorts of other devices, basically
almost everything that has a file descriptor but isn't a file itself. (As
usual, "sane" excludes windows - on that platform you would need different
functions for all of these, complicating code immensely - think "socket
only" on windows).
However, I/O is not everything - the second most important event source is
the clock. For example when doing an HTTP request you might want to time
out when the server doesn't answer within some predefined amount of time.
In AnyEvent, timer event watchers are created by calling the C<<
AnyEvent->timer >> method:
use AnyEvent;
my $cv = AnyEvent->condvar;
my $wait_one_and_a_half_seconds = AnyEvent->timer (
after => 1.5, # after how many seconds to invoke the cb?
cb => sub { # the callback to invoke
$cv->send;
},
);
# can do something else here
# now wait till our time has come
$cv->recv;
Unlike I/O watchers, timers are only interested in the amount of seconds
they have to wait. When (at least) that amount of time has passed,
AnyEvent will invoke your callback.
Unlike I/O watchers, which will call your callback as many times as there
is data available, timers are normally one-shot: after they have "fired"
once and invoked your callback, they are dead and no longer do anything.
To get a repeating timer, such as a timer firing roughly once per second,
you can specify an C<interval> parameter:
my $once_per_second = AnyEvent->timer (
after => 0, # first invoke ASAP
lib/AnyEvent/Intro.pod view on Meta::CPAN
});
}
And now let's go through it step by step. First, as usual, the overall
C<http_get> function structure:
sub http_get {
my ($host, $uri, $cb) = @_;
# store results here
my ($response, $header, $body);
my $handle; $handle = new AnyEvent::Handle
... create handle object
... push data to write
... push what to expect to read queue
}
Unlike in the finger example, this time the caller has to pass a callback
to C<http_get>. Also, instead of passing a URL as one would expect, the
caller has to provide the hostname and URI - normally you would use the
C<URI> module to parse a URL and separate it into those parts, but that is
left to the inspired reader :)
Since everything else is left to the caller, all C<http_get> does is
initiate the connection by creating the AnyEvent::Handle object (which
calls C<tcp_connect> for us) and leave everything else to its callback.
The handle object is created, unsurprisingly, by calling the C<new>
method of L<AnyEvent::Handle>:
my $handle; $handle = new AnyEvent::Handle
connect => [$host => 'http'],
on_error => sub {
$cb->("HTTP/1.0 500 $!");
$handle->destroy; # explicitly destroy handle
},
on_eof => sub {
$cb->($response, $header, $body);
$handle->destroy; # explicitly destroy handle
};
The C<connect> argument tells AnyEvent::Handle to call C<tcp_connect> for
the specified host and service/port.
The C<on_error> callback will be called on any unexpected error, such as a
refused connection, or unexpected end-of-file while reading headers.
Instead of having an extra mechanism to signal errors, connection errors
are signalled by crafting a special "response status line", like this:
HTTP/1.0 500 Connection refused
This means the caller cannot distinguish (easily) between
locally-generated errors and server errors, but it simplifies error
handling for the caller a lot.
The error callback also destroys the handle explicitly, because we are not
interested in continuing after any errors. In AnyEvent::Handle callbacks
you have to call C<destroy> explicitly to destroy a handle. Outside of
those callbacks you can just forget the object reference and it will be
automatically cleaned up.
Last but not least, we set an C<on_eof> callback that is called when the
other side indicates it has stopped writing data, which we will use to
gracefully shut down the handle and report the results. This callback is
only called when the read queue is empty - if the read queue expects
some data and the handle gets an EOF from the other side this will be an
error - after all, you did expect more to come.
If you wanted to write a server using AnyEvent::Handle, you would use
C<tcp_accept> and then create the AnyEvent::Handle with the C<fh>
argument.
=head3 The write queue
The next line sends the actual request:
$handle->push_write ("GET $uri HTTP/1.0\015\012\015\012");
No headers will be sent (this is fine for simple requests), so the whole
request is just a single line followed by an empty line to signal the end
of the headers to the server.
The more interesting question is why the method is called C<push_write>
and not just write. The reason is that you can I<always> add some write
data without blocking, and to do this, AnyEvent::Handle needs some write
queue internally - and C<push_write> pushes some data onto the end of
that queue, just like Perl's C<push> pushes data onto the end of an
array.
The deeper reason is that at some point in the future, there might
be C<unshift_write> as well, and in any case, we will shortly meet
C<push_read> and C<unshift_read>, and it's usually easiest to remember if
all those functions have some symmetry in their name. So C<push> is used
as the opposite of C<unshift> in AnyEvent::Handle, not as the opposite of
C<pull> - just like in Perl.
Note that we call C<push_write> right after creating the AnyEvent::Handle
object, before it has had time to actually connect to the server. This is
fine, pushing the read and write requests will queue them in the handle
object until the connection has been established. Alternatively, we
could do this "on demand" in the C<on_connect> callback.
If C<push_write> is called with more than one argument, then you can do
I<formatted> I/O. For example, this would JSON-encode your data before
pushing it to the write queue:
$handle->push_write (json => [1, 2, 3]);
This pretty much summarises the write queue, there is little else to it.
Reading the response is far more interesting, because it involves the more
powerful and complex I<read queue>:
=head3 The read queue
The response consists of three parts: a single line with the response
status, a single paragraph of headers ended by an empty line, and the
request body, which is the remaining data on the connection.
( run in 0.621 second using v1.01-cache-2.11-cpan-39bf76dae61 )