=head1 NAME Coro::AnyEvent - integrate coroutines into AnyEvent =head1 SYNOPSIS use Coro; use Coro::AnyEvent; # use coro within an AnyEvent environment =head1 INTRODUCTION When one naively starts to use coroutines in Perl, one will quickly run into the problem that coroutines that block on a syscall (sleeping, reading from a socket etc.) will block all coroutines. If one then uses an event loop, the problem is that the event loop has no knowledge of coroutines and will not run them before it polls for new events, again blocking the whole process. This module integrates coroutines into any event loop supported by AnyEvent, combining event-based programming with coroutine-based programming in a natural way. All you have to do is C and then you can run a coroutines freely. =head1 DESCRIPTION This module autodetects the event loop used (by relying on L) and will either automatically defer to the high-performance L or L modules, or will use a generic integration into any event loop supported by L. Unfortunately, few event loops (basically only L and L) support this kind of integration well, and therefore AnyEvent cannot offer the required functionality. Here is what this module does when it has to work with other event loops: =over 4 =item * run ready coroutines before blocking the process Each time a coroutine is put into the ready queue (and there are no other coroutines in the ready queue), a timer with an C value of C<0> is registered with AnyEvent. This creates something similar to an I watcher, i.e. a watcher that keeps the event loop from blocking but still polls for new events. (Unfortunately, some badly designed event loops (e.g. Event::Lib) don't support a timeout of C<0> and will always block for a bit). The callback for that timer will C to other coroutines of the same or higher priority for as long as such coroutines exists. This has the effect of running all coroutines that have work to do will all coroutines block to wait for external events. If no coroutines of equal or higher priority are ready, it will cede to any coroutine, but only once. This has the effect of running lower-priority coroutines as well, but it will not keep higher priority coroutines from receiving new events. The priority used is simply the priority of the coroutine that runs the event loop, usually the main program, and the priority is usually C<0>. =item * provide a suitable idle callback. In addition to hooking into C, this module will also provide a C<$Coro::idle> handler that runs the event loop. It is best not to rely on this, as this is rather inefficient. =item * provide overrides for AnyEvent's condvars This module installs overrides for AnyEvent's condvars. That is, when the module is loaded it will provide its own condition variables. This makes the coroutine-safe, i.e. you can safely block on them from within a coroutine. =item * lead to data corruption or worse As C cannot be by this module (as it is the module that implements it, basically), you must not call into the event loop recursively from any coroutine. This is not usually a difficult restriction to live with, just use condvars, C or other means of inter-coroutine-communications. If you use a module that supports AnyEvent (or uses the same event loop as AnyEvent, making the compatible), and it offers callbacks of any kind, then you must not block in them, either (or use e.g. C), see the description of C in the L module. This also means that you should load the module as early as possible, as only condvars created after this module has been loaded will work correctly. =back =cut package Coro::AnyEvent; no warnings; use strict; use Coro; use AnyEvent (); our $VERSION = 4.8; ############################################################################# # idle handler our $IDLE; ############################################################################# # 0-timeout idle emulation watcher our $ACTIVITY; sub _activity { $ACTIVITY ||= AnyEvent->timer (after => 0, cb => \&_schedule); } Coro::_set_readyhook (\&AnyEvent::detect); AnyEvent::post_detect { unshift @AnyEvent::CondVar::ISA, "Coro::AnyEvent::CondVar"; Coro::_set_readyhook undef; my $model = $AnyEvent::MODEL; if ($model eq "AnyEvent::Impl::EV") { require Coro::EV; } elsif ($model eq "AnyEvent::Impl::Event") { require Coro::Event; } else { Coro::_set_readyhook \&_activity; $IDLE = new Coro sub { while () { AnyEvent->one_event; &Coro::schedule; } }; $IDLE->{desc} = "[AnyEvent idle process]"; $Coro::idle = sub { local $ACTIVITY = 1; # hack to keep it from being set by the ready call $IDLE->ready; }; } }; ############################################################################# # override condvars package Coro::AnyEvent::CondVar; sub _send { (delete $_[0]{_ae_coro})->ready if $_[0]{_ae_coro}; } sub _wait { while (!$_[0]{_ae_sent}) { local $_[0]{_ae_coro} = $Coro::current; Coro::schedule; } } 1; =head1 SEE ALSO L, to see which event loops are supported, L and L for more efficient and more correct solutions (they will be used automatically if applicable). =head1 AUTHOR Marc Lehmann http://home.schmorp.de/ =cut