Coro
view release on metacpan or search on metacpan
This module collection manages continuations in general, most often in
the form of cooperative threads (also called coros, or simply "coro" in
the documentation). They are similar to kernel threads but don't (in
general) run in parallel at the same time even on SMP machines. The
specific flavor of thread offered by this module also guarantees you
that it will not switch between threads unless necessary, at
easily-identified points in your program, so locking and parallel access
are rarely an issue, making thread programming much safer and easier
than using other thread models.
Unlike the so-called "Perl threads" (which are not actually real threads
but only the windows process emulation (see section of same name for
more details) ported to UNIX, and as such act as processes), Coro
provides a full shared address space, which makes communication between
threads very easy. And coro threads are fast, too: disabling the Windows
process emulation code in your perl and using Coro can easily result in
a two to four times speed increase for your programs. A parallel matrix
multiplication benchmark (very communication-intensive) runs over 300
times faster on a single core than perls pseudo-threads on a quad core
using all four cores.
Coro achieves that by supporting multiple running interpreters that
share data, which is especially useful to code pseudo-parallel processes
and for event-based programming, such as multiple HTTP-GET requests
running concurrently. See Coro::AnyEvent to learn more on how to
integrate Coro into an event-based environment.
In this module, a thread is defined as "callchain + lexical variables +
some package variables + C stack), that is, a thread has its own
callchain, its own set of lexicals and its own set of perls most
important global variables (see Coro::State for more configuration and
background info).
See also the "SEE ALSO" section at the end of this document - the Coro
module family is quite large.
CORO THREAD LIFE CYCLE
During the long and exciting (or not) life of a coro thread, it goes
through a number of states:
1. Creation
The first thing in the life of a coro thread is it's creation -
obviously. The typical way to create a thread is to call the "async
BLOCK" function:
async {
# thread code goes here
};
You can also pass arguments, which are put in @_:
async {
print $_[1]; # prints 2
} 1, 2, 3;
This creates a new coro thread and puts it into the ready queue,
meaning it will run as soon as the CPU is free for it.
"async" will return a Coro object - you can store this for future
reference or ignore it - a thread that is running, ready to run or
waiting for some event is alive on it's own.
Another way to create a thread is to call the "new" constructor with
a code-reference:
new Coro sub {
# thread code goes here
}, @optional_arguments;
This is quite similar to calling "async", but the important
difference is that the new thread is not put into the ready queue,
so the thread will not run until somebody puts it there. "async" is,
therefore, identical to this sequence:
my $coro = new Coro sub {
# thread code goes here
};
$coro->ready;
return $coro;
2. Startup
When a new coro thread is created, only a copy of the code reference
and the arguments are stored, no extra memory for stacks and so on
is allocated, keeping the coro thread in a low-memory state.
Only when it actually starts executing will all the resources be
finally allocated.
The optional arguments specified at coro creation are available in
@_, similar to function calls.
3. Running / Blocking
A lot can happen after the coro thread has started running. Quite
usually, it will not run to the end in one go (because you could use
a function instead), but it will give up the CPU regularly because
it waits for external events.
As long as a coro thread runs, its Coro object is available in the
global variable $Coro::current.
The low-level way to give up the CPU is to call the scheduler, which
selects a new coro thread to run:
Coro::schedule;
Since running threads are not in the ready queue, calling the
scheduler without doing anything else will block the coro thread
forever - you need to arrange either for the coro to put woken up
(readied) by some other event or some other thread, or you can put
it into the ready queue before scheduling:
# this is exactly what Coro::cede does
$Coro::current->ready;
Coro::schedule;
All the higher-level synchronisation methods (Coro::Semaphore,
Coro::rouse_*...) are actually implemented via "->ready" and
"Coro::schedule".
While the coro thread is running it also might get assigned a
C-level thread, or the C-level thread might be unassigned from it,
$SIG{VTALRM} = sub { cede };
# and then start the interval timer
Time::HiRes::setitimer &Time::HiRes::ITIMER_VIRTUAL, 0.01, 0.01;
};
Coro::on_leave {
# on leaving the thread, we stop the interval timer again
Time::HiRes::setitimer &Time::HiRes::ITIMER_VIRTUAL, 0, 0;
};
&{+shift};
}
# use like this:
timeslice {
# The following is an endless loop that would normally
# monopolise the process. Since it runs in a timesliced
# environment, it will regularly cede to other threads.
while () { }
};
killall
Kills/terminates/cancels all coros except the currently running one.
Note that while this will try to free some of the main interpreter
resources if the calling coro isn't the main coro, but one cannot
free all of them, so if a coro that is not the main coro calls this
function, there will be some one-time resource leak.
CORO OBJECT METHODS
These are the methods you can call on coro objects (or to create them).
new Coro \&sub [, @args...]
Create a new coro and return it. When the sub returns, the coro
automatically terminates as if "terminate" with the returned values
were called. To make the coro run you must first put it into the
ready queue by calling the ready method.
See "async" and "Coro::State::new" for additional info about the
coro environment.
$success = $coro->ready
Put the given coro into the end of its ready queue (there is one
queue for each priority) and return true. If the coro is already in
the ready queue, do nothing and return false.
This ensures that the scheduler will resume this coro automatically
once all the coro of higher priority and all coro of the same
priority that were put into the ready queue earlier have been
resumed.
$coro->suspend
Suspends the specified coro. A suspended coro works just like any
other coro, except that the scheduler will not select a suspended
coro for execution.
Suspending a coro can be useful when you want to keep the coro from
running, but you don't want to destroy it, or when you want to
temporarily freeze a coro (e.g. for debugging) to resume it later.
A scenario for the former would be to suspend all (other) coros
after a fork and keep them alive, so their destructors aren't
called, but new coros can be created.
$coro->resume
If the specified coro was suspended, it will be resumed. Note that
when the coro was in the ready queue when it was suspended, it might
have been unreadied by the scheduler, so an activation might have
been lost.
To avoid this, it is best to put a suspended coro into the ready
queue unconditionally, as every synchronisation mechanism must
protect itself against spurious wakeups, and the one in the Coro
family certainly do that.
$state->is_new
Returns true iff this Coro object is "new", i.e. has never been run
yet. Those states basically consist of only the code reference to
call and the arguments, but consumes very little other resources.
New states will automatically get assigned a perl interpreter when
they are transferred to.
$state->is_zombie
Returns true iff the Coro object has been cancelled, i.e. it's
resources freed because they were "cancel"'ed, "terminate"'d,
"safe_cancel"'ed or simply went out of scope.
The name "zombie" stems from UNIX culture, where a process that has
exited and only stores and exit status and no other resources is
called a "zombie".
$is_ready = $coro->is_ready
Returns true iff the Coro object is in the ready queue. Unless the
Coro object gets destroyed, it will eventually be scheduled by the
scheduler.
$is_running = $coro->is_running
Returns true iff the Coro object is currently running. Only one Coro
object can ever be in the running state (but it currently is
possible to have multiple running Coro::States).
$is_suspended = $coro->is_suspended
Returns true iff this Coro object has been suspended. Suspended
Coros will not ever be scheduled.
$coro->cancel ($arg...)
Terminate the given Coro thread and make it return the given
arguments as status (default: an empty list). Never returns if the
Coro is the current Coro.
This is a rather brutal way to free a coro, with some limitations -
if the thread is inside a C callback that doesn't expect to be
canceled, bad things can happen, or if the cancelled thread insists
on running complicated cleanup handlers that rely on its thread
context, things will not work.
Any cleanup code being run (e.g. from "guard" blocks, destructors
and so on) will be run without a thread context, and is not allowed
to switch to other threads. A common mistake is to call "->cancel"
from a destructor called by die'ing inside the thread to be
cancelled for example.
( run in 2.334 seconds using v1.01-cache-2.11-cpan-5837b0d9d2c )