AnyEvent

 view release on metacpan or  search on metacpan

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
      interval => 1, # then invoke every second
      cb    => sub { # the callback to invoke
         $cv->send;



( run in 0.463 second using v1.01-cache-2.11-cpan-39bf76dae61 )