Coro::Cont resurrection

scrottie on 2008-11-15T06:34:18

use Coro; 
use Coro::Cont "yield";
sub foo :Cont { yield 1; yield 3; }; 

print foo(), "\n"; print foo(), "\n";


Pretty boring. The neat thing is foo() can have my variables, and they keep value between calls. It can yield from in middle of for loops. Etc, etc. But here's a bit of guts, just for fun. Working on Coro::Cont, I was using -d:Trace (Devel::Trace), another thing I love.

>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
>> Coro/Cont.pm:130:    @ret = @_; # XXX if this works, make it a stack, I guess -- sdw
>> Coro/Cont.pm:131:    &Coro::State::transfer(@{pop @$$return});
>> Coro/Cont.pm:131:    &Coro::State::transfer(@{pop @$$return});
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53:    $Coro::current->{_specific}[${$_[0]}];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53:    $Coro::current->{_specific}[${$_[0]}];
>> Coro/Cont.pm:116:       wantarray ? @ret : $ret[0];
1
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
>> Coro/Cont.pm:114:       push @$$return, [$coro, $prev];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53:    $Coro::current->{_specific}[${$_[0]}];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53:    $Coro::current->{_specific}[${$_[0]}];
>> Coro/Cont.pm:115:       &Coro::State::transfer($prev, $coro);
>> Coro/Cont.pm:132:    wantarray ? @_ : $_[0];
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"
; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
csub again:
>> -e:1: use strict; use warnings; use Coro; use lib "."; use Coro::Cont "yield", "csub"; *foo = csub { print "csub: @_\n"; yield 1; print "csub again: @_\n"
; yield 3;}; print foo(5),"\n"; print foo(18), "\n";
>> Coro/Cont.pm:130:    @ret = @_; # XXX if this works, make it a stack, I guess -- sdw
>> Coro/Cont.pm:131:    &Coro::State::transfer(@{pop @$$return});
>> Coro/Cont.pm:131:    &Coro::State::transfer(@{pop @$$return});
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53:    $Coro::current->{_specific}[${$_[0]}];
>> /home/knoppix/lib/perl5/site_perl/5.8.8/i686-linux/Coro/Specific.pm:53:    $Coro::current->{_specific}[${$_[0]}];
>> Coro/Cont.pm:116:       wantarray ? @ret : $ret[0];


@ret holds return values from before to after the call to Coro::State::transfer. Coro::State::transfer switches from one execution context to another. It's fun to look at this print out the -e line of code and have execution teleported from one place in the code to another -- from inside the function to outside of it and back. Not shown, Coro has a function for creating an execution context object to represent the current execution context, and that's what $prev is. It keeps these execution contexts on a nice little stack. When you yield, it pops up a level and does an implicit return of whatever arguments were passed to yield. When the function is called again, transfer is called again to switch execution back into the routine, foo in our example, and the stack is pushed again, and foo resumes execution exactly where it left off... right after the yield.

-scott


I got one of those

awwaiid on 2008-11-16T15:06:18

http://search.cpan.org/dist/Coro-Generator/