Coro::AnyEvent - integrate coroutines into AnyEvent
use Coro; use Coro::AnyEvent; # use coro within an AnyEvent environment
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 use Coro::AnyEvent
and then you can run
coroutines freely.
This module autodetects the event loop used (by relying on AnyEvent) and will either automatically defer to the high-performance Coro::EV or Coro::Event modules, or will use a generic integration into any event loop supported by AnyEvent.
Unfortunately, few event loops (basically only EV and Event) support this kind of integration well, and consequently, AnyEvent cannot offer the functionality required by this module, so we need to improvise.
Here is what this module does when it has to work with other event loops:
Each time a coroutine is put into the ready queue (and there are no other
coroutines in the ready queue), a timer with an after
value of 0
is
registered with AnyEvent.
This creates something similar to an idle 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 0
and will always block for a bit).
The callback for that timer will cede
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 untill 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, which usually has a priority of
0
.
ready
, this module will also provide a
$Coro::idle
handler that runs the event loop. It is best not to take
advantage of this too often, as this is rather inefficient, but it should
work perfectly fine.
As unblock_sub
cannot be used 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, unblock_sub
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. unblock_sub
), see
the description of unblock_sub
in the Coro 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.
AnyEvent, to see which event loops are supported, Coro::EV and Coro::Event for more efficient and more correct solutions (they will be used automatically if applicable).
Marc Lehmann <schmorp@schmorp.de> http://home.schmorp.de/