Condition variables are very useful to signal that something has finished,
for example, if you write a module that does asynchronous http requests,
then a condition variable would be the ideal candidate to signal the
availability of results. The user can either act when the callback is
called or can synchronously C<< ->recv >> for the results.
You can also use them to simulate traditional event loops - for example,
you can block your main program until an event occurs - for example, you
could C<< ->recv >> in your main program until the user clicks the Quit
button of your app, which would C<< ->send >> the "quit" event.
Note that condition variables recurse into the event loop - if you have
two pieces of code that call C<< ->recv >> in a round-robin fashion, you
lose. Therefore, condition variables are good to export to your caller, but
you should avoid making a blocking wait yourself, at least in callbacks,
as this asks for trouble.
Condition variables are represented by hash refs in perl, and the keys
used by AnyEvent itself are all named C<_ae_XXX> to make subclassing
easy (it is often useful to build your own transaction class on top of
AnyEvent). To subclass, use C<AnyEvent::CondVar> as base class and call
it's C<new> method in your own C<new> method.
There are two "sides" to a condition variable - the "producer side" which
eventually calls C<< -> send >>, and the "consumer side", which waits
for the send to occur.
Example: wait for a timer.
# wait till the result is ready
my $result_ready = AnyEvent->condvar;
# do something such as adding a timer
# or socket watcher the calls $result_ready->send
# when the "result" is ready.
# in this case, we simply use a timer:
my $w = AnyEvent->timer (
after => 1,
cb => sub { $result_ready->send },
);
# this "blocks" (while handling events) till the callback
# calls send
$result_ready->recv;
Example: wait for a timer, but take advantage of the fact that
condition variables are also code references.
my $done = AnyEvent->condvar;
my $delay = AnyEvent->timer (after => 5, cb => $done);
$done->recv;
=head3 METHODS FOR PRODUCERS
These methods should only be used by the producing side, i.e. the
code/module that eventually sends the signal. Note that it is also
the producer side which creates the condvar in most cases, but it isn't
uncommon for the consumer to create it as well.
=over 4
=item $cv->send (...)
Flag the condition as ready - a running C<< ->recv >> and all further
calls to C<recv> will (eventually) return after this method has been
called. If nobody is waiting the send will be remembered.
If a callback has been set on the condition variable, it is called
immediately from within send.
Any arguments passed to the C<send> call will be returned by all
future C<< ->recv >> calls.
Condition variables are overloaded so one can call them directly
(as a code reference). Calling them directly is the same as calling
C<send>. Note, however, that many C-based event loops do not handle
overloading, so as tempting as it may be, passing a condition variable
instead of a callback does not work. Both the pure perl and EV loops
support overloading, however, as well as all functions that use perl to
invoke a callback (as in L<AnyEvent::Socket> and L<AnyEvent::DNS> for
example).
=item $cv->croak ($error)
Similar to send, but causes all call's to C<< ->recv >> to invoke
C<Carp::croak> with the given error message/object/scalar.
This can be used to signal any errors to the condition variable
user/consumer.
=item $cv->begin ([group callback])
=item $cv->end
These two methods are EXPERIMENTAL and MIGHT CHANGE.
These two methods can be used to combine many transactions/events into
one. For example, a function that pings many hosts in parallel might want
to use a condition variable for the whole process.
=5= |