AnyEvent

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN


        Every call to "->begin" will increment a counter, and every call to
        "->end" will decrement it. If the counter reaches 0 in "->end", the
        (last) callback passed to "begin" will be executed, passing the
        condvar as first argument. That callback is *supposed* to call
        "->send", but that is not required. If no group callback was set,
        "send" will be called without any arguments.

        You can think of "$cv->send" giving you an OR condition (one call
        sends), while "$cv->begin" and "$cv->end" giving you an AND
        condition (all "begin" calls must be "end"'ed before the condvar
        sends).

        Let's start with a simple example: you have two I/O watchers (for
        example, STDOUT and STDERR for a program), and you want to wait for
        both streams to close before activating a condvar:

           my $cv = AnyEvent->condvar;

           $cv->begin; # first watcher
           my $w1 = AnyEvent->io (fh => $fh1, cb => sub {
              defined sysread $fh1, my $buf, 4096
                 or $cv->end;
           });

           $cv->begin; # second watcher
           my $w2 = AnyEvent->io (fh => $fh2, cb => sub {
              defined sysread $fh2, my $buf, 4096
                 or $cv->end;
           });

           $cv->recv;

        This works because for every event source (EOF on file handle),
        there is one call to "begin", so the condvar waits for all calls to
        "end" before sending.

        The ping example mentioned above is slightly more complicated, as
        the there are results to be passed back, and the number of tasks
        that are begun can potentially be zero:

           my $cv = AnyEvent->condvar;

           my %result;
           $cv->begin (sub { shift->send (\%result) });

           for my $host (@list_of_hosts) {
              $cv->begin;
              ping_host_then_call_callback $host, sub {
                 $result{$host} = ...;
                 $cv->end;
              };
           }

           $cv->end;

           ...

           my $results = $cv->recv;

        This code fragment supposedly pings a number of hosts and calls
        "send" after results for all then have have been gathered - in any
        order. To achieve this, the code issues a call to "begin" when it
        starts each ping request and calls "end" when it has received some
        result for it. Since "begin" and "end" only maintain a counter, the
        order in which results arrive is not relevant.

        There is an additional bracketing call to "begin" and "end" outside
        the loop, which serves two important purposes: first, it sets the
        callback to be called once the counter reaches 0, and second, it
        ensures that "send" is called even when "no" hosts are being pinged
        (the loop doesn't execute once).

        This is the general pattern when you "fan out" into multiple (but
        potentially zero) subrequests: use an outer "begin"/"end" pair to
        set the callback and ensure "end" is called at least once, and then,
        for each subrequest you start, call "begin" and for each subrequest
        you finish, call "end".

   METHODS FOR CONSUMERS
    These methods should only be used by the consuming side, i.e. the code
    awaits the condition.

    $cv->recv
        Wait (blocking if necessary) until the "->send" or "->croak" methods
        have been called on $cv, while servicing other watchers normally.

        You can only wait once on a condition - additional calls are valid
        but will return immediately.

        If an error condition has been set by calling "->croak", then this
        function will call "croak".

        In list context, all parameters passed to "send" will be returned,
        in scalar context only the first one will be returned.

        Note that doing a blocking wait in a callback is not supported by
        any event loop, that is, recursive invocation of a blocking "->recv"
        is not allowed and the "recv" call will "croak" if such a condition
        is detected. This requirement can be dropped by relying on
        Coro::AnyEvent , which allows you to do a blocking "->recv" from any
        thread that doesn't run the event loop itself. Coro::AnyEvent is
        loaded automatically when Coro is used with AnyEvent, so code does
        not need to do anything special to take advantage of that: any code
        that would normally block your program because it calls "recv", be
        executed in an "async" thread instead without blocking other
        threads.

        Not all event models support a blocking wait - some die in that case
        (programs might want to do that to stay interactive), so *if you are
        using this from a module, never require a blocking wait*. Instead,
        let the caller decide whether the call will block or not (for
        example, by coupling condition variables with some kind of request
        results and supporting callbacks so the caller knows that getting
        the result will not block, while still supporting blocking waits if
        the caller so desires).

        You can ensure that "->recv" never blocks by setting a callback and
        only calling "->recv" from within that callback (or at a later
        time). This will work even when the event loop does not support
        blocking waits otherwise.



( run in 0.999 second using v1.01-cache-2.11-cpan-b16cb0d3907 )