--- AnyEvent/lib/AnyEvent.pm 2008/04/27 21:16:26 1.102 +++ AnyEvent/lib/AnyEvent.pm 2008/05/01 13:45:22 1.106 @@ -17,8 +17,8 @@ }); my $w = AnyEvent->condvar; # stores whether a condition was flagged - $w->wait; # enters "main loop" till $condvar gets ->broadcast - $w->broadcast; # wake up current and all future wait's + $w->wait; # enters "main loop" till $condvar gets ->send + $w->send; # wake up current and all future wait's =head1 WHY YOU SHOULD USE THIS MODULE (OR NOT) @@ -290,7 +290,7 @@ cb => sub { my ($pid, $status) = @_; warn "pid $pid exited with status $status"; - $done->broadcast; + $done->send; }, ); @@ -299,39 +299,177 @@ =head2 CONDITION VARIABLES -Condition variables can be created by calling the C<< AnyEvent->condvar >> -method without any arguments. +If you are familiar with some event loops you will know that all of them +require you to run some blocking "loop", "run" or similar function that +will actively watch for new events and call your callbacks. + +AnyEvent is different, it expects somebody else to run the event loop and +will only block when necessary (usually when told by the user). + +The instrument to do that is called a "condition variable", so called +because they represent a condition that must become true. + +Condition variables can be created by calling the C<< AnyEvent->condvar +>> method, usually without arguments. The only argument pair allowed is +C, which specifies a callback to be called when the condition variable +becomes true. + +After creation, the conditon variable is "false" until it becomes "true" +by calling the C method. + +Condition variables are similar to callbacks, except that you can +optionally wait for them. They can also be called merge points - points +in time where multiple outstandign events have been processed. And yet +another way to call them is transations - each condition variable can be +used to represent a transaction, which finishes at some point and delivers +a result. -A condition variable waits for a condition - precisely that the C<< -->broadcast >> method has been called. - -They are very useful to signal that a condition has been fulfilled, for -example, if you write a module that does asynchronous http requests, +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. +availability of results. The user can either act when the callback is +called or can synchronously C<< ->wait >> for the results. -You can also use condition variables to block your main program until -an event occurs - for example, you could C<< ->wait >> in your main -program until the user clicks the Quit button in your app, which would C<< -->broadcast >> the "quit" event. +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<< ->wait >> 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 pirces of code that call C<< ->wait >> in a round-robbin fashion, you +two pieces of code that call C<< ->wait >> in a round-robbin 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. -This object has two methods: +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 as base class and call +it's C method in your own C 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 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->wait; + +=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<< ->wait >> and all further +calls to C 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 call will be returned by all +future C<< ->wait >> calls. + +=item $cv->croak ($error) + +Similar to send, but causes all call's wait C<< ->wait >> to invoke +C 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 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. + +Every call to C<< ->begin >> will increment a counter, and every call to +C<< ->end >> will decrement it. If the counter reaches C<0> in C<< ->end +>>, the (last) callback passed to C will be executed. That callback +is I to call C<< ->send >>, but that is not required. If no +callback was set, C will be called without any arguments. + +Let's clarify this with the ping example: + + my $cv = AnyEvent->condvar; + + my %result; + $cv->begin (sub { $cv->send (\%result) }); + + for my $host (@list_of_hosts) { + $cv->begin; + ping_host_then_call_callback $host, sub { + $result{$host} = ...; + $cv->end; + }; + } + + $cv->end; + +This code fragment supposedly pings a number of hosts and calls +C after results for all then have have been gathered - in any +order. To achieve this, the code issues a call to C when it starts +each ping request and calls C when it has received some result for +it. Since C and C only maintain a counter, the order in which +results arrive is not relevant. + +There is an additional bracketing call to C and C outside the +loop, which serves two important purposes: first, it sets the callback +to be called once the counter reaches C<0>, and second, it ensures that +C is called even when C hosts are being pinged (the loop +doesn't execute once). + +This is the general pattern when you "fan out" into multiple subrequests: +use an outer C/C pair to set the callback and ensure C +is called at least once, and then, for each subrequest you start, call +C and for eahc subrequest you finish, call C. + +=back + +=head3 METHODS FOR CONSUMERS + +These methods should only be used by the consuming side, i.e. the +code awaits the condition. =over 4 =item $cv->wait -Wait (blocking if necessary) until the C<< ->broadcast >> method has been -called on c<$cv>, while servicing other watchers normally. +Wait (blocking if necessary) until the C<< ->send >> or C<< ->croak +>> methods have been called on c<$cv>, while servicing other watchers +normally. -You can only wait once on a condition - additional calls will return -immediately. +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 C<< ->croak >>, then this +function will call C. + +In list context, all parameters passed to C will be returned, +in scalar context only the first one will be returned. Not all event models support a blocking wait - some die in that case (programs might want to do that to stay interactive), so I explicitly support concurrent C<< ->wait >>'s from different coroutines, however). -=item $cv->broadcast +You can ensure that C<< -wait >> never blocks by setting a callback and +only calling C<< ->wait >> from within that callback (or at a later +time). This will work even when the event loop does not support blocking +waits otherwise. -Flag the condition as ready - a running C<< ->wait >> and all further -calls to C will (eventually) return after this method has been -called. If nobody is waiting the broadcast will be remembered.. +=item $bool = $cv->ready -=back +Returns true when the condition is "true", i.e. whether C or +C have been called. -Example: +=item $cb = $cv->cb ([new callback]) - # wait till the result is ready - my $result_ready = AnyEvent->condvar; +This is a mutator function that returns the callback set and optionally +replaces it before doing so. - # do something such as adding a timer - # or socket watcher the calls $result_ready->broadcast - # when the "result" is ready. - # in this case, we simply use a timer: - my $w = AnyEvent->timer ( - after => 1, - cb => sub { $result_ready->broadcast }, - ); +The callback will be called when the condition becomes "true", i.e. when +C or C are called. Calling C inside the callback +or at any later time is guaranteed not to block. - # this "blocks" (while handling events) till the watcher - # calls broadcast - $result_ready->wait; +=back =head1 GLOBAL VARIABLES AND FUNCTIONS @@ -392,8 +525,8 @@ AnyEvent::Impl::CoroEvent based on Coro::Event, second best choice. AnyEvent::Impl::EV based on EV (an interface to libev, best choice). AnyEvent::Impl::Event based on Event, second best choice. + AnyEvent::Impl::Perl pure-perl implementation, fast and portable. AnyEvent::Impl::Glib based on Glib, third-best choice. - AnyEvent::Impl::Perl pure-perl implementation, inefficient but portable. AnyEvent::Impl::Tk based on Tk, very bad choice. AnyEvent::Impl::Qt based on Qt, cannot be autoprobed (see its docs). AnyEvent::Impl::EventLib based on Event::Lib, leaks memory and worse. @@ -429,7 +562,7 @@ to load the event module first. Never call C<< ->wait >> on a condition variable unless you I that -the C<< ->broadcast >> method has been called on it already. This is +the C<< ->send >> method has been called on it already. This is because it will stall the whole program, and the whole point of using events is to stay interactive. @@ -555,18 +688,18 @@ [Coro::Event:: => AnyEvent::Impl::CoroEvent::], [EV:: => AnyEvent::Impl::EV::], [Event:: => AnyEvent::Impl::Event::], - [Glib:: => AnyEvent::Impl::Glib::], [Tk:: => AnyEvent::Impl::Tk::], [Wx:: => AnyEvent::Impl::POE::], [Prima:: => AnyEvent::Impl::POE::], [AnyEvent::Impl::Perl:: => AnyEvent::Impl::Perl::], # everything below here will not be autoprobed as the pureperl backend should work everywhere + [Glib:: => AnyEvent::Impl::Glib::], [Event::Lib:: => AnyEvent::Impl::EventLib::], # too buggy [Qt:: => AnyEvent::Impl::Qt::], # requires special main program [POE::Kernel:: => AnyEvent::Impl::POE::], # lasciate ogni speranza ); -our %method = map +($_ => 1), qw(io timer signal child condvar broadcast wait one_event DESTROY); +our %method = map +($_ => 1), qw(io timer signal child condvar one_event DESTROY); sub detect() { unless ($MODEL) { @@ -1073,17 +1206,22 @@ hidden memory cost inside the kernel which is not reflected in the figures above). -C, regardless of underlying event loop (whether using its pure -perl select-based backend or the Event module, the POE-EV backend -couldn't be tested because it wasn't working) shows abysmal performance -and memory usage: Watchers use almost 30 times as much memory as -EV watchers, and 10 times as much memory as Event (the high memory +C, regardless of underlying event loop (whether using its pure perl +select-based backend or the Event module, the POE-EV backend couldn't +be tested because it wasn't working) shows abysmal performance and +memory usage with AnyEvent: Watchers use almost 30 times as much memory +as EV watchers, and 10 times as much memory as Event (the high memory requirements are caused by requiring a session for each watcher). Watcher invocation speed is almost 900 times slower than with AnyEvent's pure perl -implementation. The design of the POE adaptor class in AnyEvent can not -really account for this, as session creation overhead is small compared -to execution of the state machine, which is coded pretty optimally within -L. POE simply seems to be abysmally slow. +implementation. + +The design of the POE adaptor class in AnyEvent can not really account +for the performance issues, though, as session creation overhead is +small compared to execution of the state machine, which is coded pretty +optimally within L (and while everybody agrees that +using multiple sessions is not a good approach, especially regarding +memory usage, even the author of POE could not come up with a faster +design). =head3 Summary @@ -1172,8 +1310,7 @@ =over 4 -=item * The pure perl implementation performs extremely well, considering -that it uses select. +=item * The pure perl implementation performs extremely well. =item * Avoid Glib or POE in large projects where performance matters. @@ -1232,7 +1369,8 @@ =head1 FORK Most event libraries are not fork-safe. The ones who are usually are -because they are so inefficient. Only L is fully fork-aware. +because they rely on inefficient but fork-safe C