#!/usr/bin/perl
use strict;
use warnings;
use Combinator verbose => 1;
use AE;
my $ser_done = AE::cv;
{{com
print "Begin\n";
my $a = 'a';
my $t = AE::timer .5, 0, {{next}};
--ser
undef $t;
print "First $a\n";
my $b = 'b';
--ser
print "Second (no delay) $a $b\n";
my $c = 'c';
{{com
print "Nest begin $a $b $c\n";
my $t = AE::timer .5, 0, {{next}};
my $d = 'd';
--ser
undef $t;
print "Nest second $a $b $c $d\n";
return;
--ser
print "Won't be here\n";
}}com
print "After nest begin\n";
--ser
print "Test par\n";
for(0..4) {{com
my $n = $_;
my $delay = .5 - $_*.02;
my $t = AE::timer $delay, 0, {{next}};
--ser
undef $t;
print "par1 $n after $delay\n";
{{next}}->($n); # push args to the next receiver
}}com
for(0..4) {{com
my $n = $_;
my $delay = $_*.02;
my $t = AE::timer $delay, 0, {{next}};
--ser
undef $t;
print "par2 $n after $delay\n";
{{next}}->($n); # push args to the next receiver
}}com
my @nex;
for(0..2) {{com
my $n = $_;
my $delay = .5 - $_*.03;
my $t; $t = AE::timer $delay, 0, {{nex
undef $t;
$t = AE::timer .05, 0, {{next}};
$delay += .05;
--ser
undef $t;
$nex[$n] = $n;
print "nex $n after $delay\n";
}}nex;
}}com
--ser
print "Done $a $b $c @nex @_\n"; # print the received args
$ser_done->send;
}}com
$ser_done->recv;
my $par_cv = AE::cv;
{{com
print "Jobs begin\n";
{{com
print "Job 1 begin\n";
my $t = AE::timer 1, 0, {{next}};
--ser
undef $t;
print "Job 1 done\n";
--com
print "Job 2 begin\n";
my $t = AE::timer .5, 0, {{next}};
--ser
undef $t;
print "Job 2 done\n";
}}com
print "Jobs begun\n";
my $next = {{next}};
$next->();
$next->(); # next should be invoked only once
--ser
print "Jobs done\n";
$par_cv->send;
}}com
$par_cv->recv;
my $cir_cv = AE::cv;
{{com
my $n = 0;
my $m = 0;
{{cir
++$n;
print "Cir1 $n begin\n";
my $t = AE::timer .2, 0, {{next}};
--ser
undef $t;
print "Cir1 $n second\n";
my $t = AE::timer .2, 0, {{next}};
--ser
undef $t;
return if( $n == 8 );
print "Cir1 $n repeat\n";
--com
print "One shot!\n";
--cir
++$m;
print "Cir2 $m begin\n";
my $t = AE::timer .5, 0, {{next}};
--ser
undef $t;
print "Cir2 $m second\n";
my $t = AE::timer .5, 0, {{next}};
--ser
undef $t;
return if( $m == 3 );
print "Cir2 $m repeat\n";
}}com
--ser
$cir_cv->send;
}}com
$cir_cv->recv;
=comment Expected Output
Begin
First a
Second (no delay) a b
Nest begin a b c
After nest begin
Nest second a b c d
Test par
par2 0 after 0
par2 1 after 0.02
par2 2 after 0.04
par2 3 after 0.06
par2 4 after 0.08
par1 4 after 0.42
par1 3 after 0.44
par1 2 after 0.46
par1 1 after 0.48
nex 2 after 0.49
par1 0 after 0.5
nex 1 after 0.52
nex 0 after 0.55
Done a b c 0 1 2 0 1 2 3 4 4 3 2 1 0
Jobs begin
Job 1 begin
Job 2 begin
Jobs begun
next should be invoked only once at demo_all.pl line 99.
Job 2 done
Job 1 done
Jobs done
Cir1 1 begin
One shot!
Cir2 1 begin
Cir1 1 second
Cir1 1 repeat
Cir1 2 begin
Cir2 1 second
Cir1 2 second
Cir1 2 repeat
Cir1 3 begin
Cir2 1 repeat
Cir2 2 begin
Cir1 3 second
Cir1 3 repeat
Cir1 4 begin
Cir1 4 second
Cir2 2 second
Cir1 4 repeat
Cir1 5 begin
Cir1 5 second
Cir2 2 repeat
Cir2 3 begin
Cir1 5 repeat
Cir1 6 begin
Cir1 6 second
Cir1 6 repeat
Cir1 7 begin
Cir2 3 second
Cir1 7 second
Cir1 7 repeat
Cir1 8 begin
Cir1 8 second
=cut