Cooperative Threads
 “First class continuations called Coroutines”
 A pseudo-threads suite implemented on Perl
 Only one thread is running in any moment
Why do we need it?
 Because “real” threads are difficult
 And “real” Perl threads are not threads at all –
almost processes
 Integration with AnyEvent
Won’t print anything
The main program ends without giving the
coroutine chance to run
Need to add a “cede;” in the end
use Coro;
async {
print "hellon";
};
use Coro;
async {
print "async 1n";
cede;
print "async 2n";
};
print "main 1n";
cede;
print "main 2n";
cede;
Will Print:
main 1
async 1
main 2
async 2
 If the test inside the async block fails, we will get the following
messge:
• FATAL: deadlock detected at - line 0
 Main program gave up the CPU, and is not in ready mode
 Async block ended already
 No runnable code – oops.
 What if we want to wait for something to happen? (AnyEvent –
Later)
use Coro;
my $wakeme = $Coro::current;
async {
$wakeme->ready if 0.5 < rand;
};
schedule;
 Can be upped and downed
multiple times
 Can be used with guard:
my $guard = $lock->guard;
use Coro;
use Coro::Semaphore;
my $sem = new Coro::Semaphore
0; # a locked semaphore
async {
print "unlocking semaphoren";
$sem->up;
};
print "trying to lock semaphoren";
$sem->down;
print "we got it!n";
use Coro;
use Coro::Semaphore;
my $calculate = new Coro::Channel;
my $result = new Coro::Channel;
async {
while (1) {
my $num = $calculate->get; # read a number
$num **= 2; # square it
$result->put ($num); # put the result into the result queue
}
};
use Coro;
use Coro::Socket;
sub finger {
my ($user, $host) = @_;
my $fh = new Coro::Socket PeerHost => $host, PeerPort => "finger"
or die "$user@$host: $!";
print $fh "$usern";
print "$user@$host: $_" while <$fh>;
print "$user@$host: donen";
}
# now finger a few accounts
for (
(async { finger "abc", "cornell.edu" }),
(async { finger "sebbo", "world.std.com" }),
(async { finger "trouble", "noc.dfn.de" }) ) {
$_->join; # wait for the result
}
use Coro::Timer;
async {
say "before sleep 10";
Coro::Timer::sleep(10);
say "after sleep 10";
};
 Internally, uses AnyEvent
For using AnyEvent, you need event loop
• Can put it in the main thread, or in async block
When both Coro and AnyEvent are loaded,
Coro::AnyEvent is automatically loaded
use Modern::Perl;
use Coro;
use AnyEvent;
use AnyEvent::Impl::Perl;
use Coro::Timer;
$|=1;
for my $t (10, 20) {
async {
say "before sleep $t";
Coro::Timer::sleep($t);
say "after sleep $t";
};
}
my $t1 = AE::timer 5, 0, sub {say "it's time 5"};
my $t2 = AE::timer 15, 0, sub {say "it's time 15"};
say "before loop";
AnyEvent->condvar->recv;
The Output:
before loop
before sleep 10
before sleep 20
it's time 5
after sleep 10
it's time 15
after sleep 20

Perl: Coro asynchronous

  • 1.
  • 2.
     “First classcontinuations called Coroutines”  A pseudo-threads suite implemented on Perl  Only one thread is running in any moment Why do we need it?  Because “real” threads are difficult  And “real” Perl threads are not threads at all – almost processes  Integration with AnyEvent
  • 3.
    Won’t print anything Themain program ends without giving the coroutine chance to run Need to add a “cede;” in the end use Coro; async { print "hellon"; };
  • 4.
    use Coro; async { print"async 1n"; cede; print "async 2n"; }; print "main 1n"; cede; print "main 2n"; cede; Will Print: main 1 async 1 main 2 async 2
  • 5.
     If thetest inside the async block fails, we will get the following messge: • FATAL: deadlock detected at - line 0  Main program gave up the CPU, and is not in ready mode  Async block ended already  No runnable code – oops.  What if we want to wait for something to happen? (AnyEvent – Later) use Coro; my $wakeme = $Coro::current; async { $wakeme->ready if 0.5 < rand; }; schedule;
  • 6.
     Can beupped and downed multiple times  Can be used with guard: my $guard = $lock->guard; use Coro; use Coro::Semaphore; my $sem = new Coro::Semaphore 0; # a locked semaphore async { print "unlocking semaphoren"; $sem->up; }; print "trying to lock semaphoren"; $sem->down; print "we got it!n";
  • 7.
    use Coro; use Coro::Semaphore; my$calculate = new Coro::Channel; my $result = new Coro::Channel; async { while (1) { my $num = $calculate->get; # read a number $num **= 2; # square it $result->put ($num); # put the result into the result queue } };
  • 8.
    use Coro; use Coro::Socket; subfinger { my ($user, $host) = @_; my $fh = new Coro::Socket PeerHost => $host, PeerPort => "finger" or die "$user@$host: $!"; print $fh "$usern"; print "$user@$host: $_" while <$fh>; print "$user@$host: donen"; } # now finger a few accounts for ( (async { finger "abc", "cornell.edu" }), (async { finger "sebbo", "world.std.com" }), (async { finger "trouble", "noc.dfn.de" }) ) { $_->join; # wait for the result }
  • 9.
    use Coro::Timer; async { say"before sleep 10"; Coro::Timer::sleep(10); say "after sleep 10"; };  Internally, uses AnyEvent
  • 10.
    For using AnyEvent,you need event loop • Can put it in the main thread, or in async block When both Coro and AnyEvent are loaded, Coro::AnyEvent is automatically loaded
  • 11.
    use Modern::Perl; use Coro; useAnyEvent; use AnyEvent::Impl::Perl; use Coro::Timer; $|=1; for my $t (10, 20) { async { say "before sleep $t"; Coro::Timer::sleep($t); say "after sleep $t"; }; } my $t1 = AE::timer 5, 0, sub {say "it's time 5"}; my $t2 = AE::timer 15, 0, sub {say "it's time 15"}; say "before loop"; AnyEvent->condvar->recv; The Output: before loop before sleep 10 before sleep 20 it's time 5 after sleep 10 it's time 15 after sleep 20