#!/usr/bin/perl =begin I interpret the calls of the sub spin below as ``promises''. The spin sub calls "enter" which guarantees that the block will run, but inside that block now we call spin again, which has to guarantee that another block will run... Shades of indiffernce might wash over your face, but take a look! It's cool. El Capitano, Jambo Hamon P.S In the context of the last post this is the first ``bit''. P.P.S Si =cut use strict; use warnings; use v5.20; # oh yeah use Time::HiRes qw(usleep); use Data::Dumper; use constant ITER => 200; use constant RAND_SLEEP => 200; use Mutex; my $red = Mutex->new; my $yellow = Mutex->new; my $green = Mutex->new; $red->lock; $yellow->lock; $green->lock; sub spin { # Mutex, subroutine reference, ...Jazz return shift->enter( shift, @_ ); } my $pid = fork; my %t; $t{starttime} = time; # stats data hash symbold lookup .. what scope is this in once we fork? die "$!: who knows me?" if not defined $pid; if ( $pid == 0 ) { #child: fork1 say "fork1 here: $$"; my $pid = fork; die "$!: who knows me?" if not defined $pid; my $cnt; # what scope does $cnt get thrown into... if there only were.. if ( $pid == 0 ) { #child: fork2 say "fork2 here: $$"; # sleep 1; while ( $cnt++ < ITER ) { # usleep int(rand(10)); spin( $red, sub { #say "fork2\\ waiting yellow"; spin( $yellow, sub { say "fork2: red yellow"; $t{fork2}->{r}++; $t{fork2}->{ry}++; $t{fork2}->{y}++; usleep int( rand(RAND_SLEEP) ); } ); } ); spin( $red, sub { spin( $green, sub { say "fork2: red green"; $t{fork2}->{r}++; $t{fork2}->{rg}++; $t{fork2}->{g}++; usleep int( rand(RAND_SLEEP) ); } ); } ); } } else { # fork1 # sleep 2; while ( $cnt++ < ITER ) { # usleep int(rand(5)); spin( $red, sub { # say "fork1\\ waiting green"; spin( $green, sub { say "fork1: red green"; $t{fork1}->{r}++; $t{fork1}->{rg}++; $t{fork1}->{g}++; usleep int( rand(RAND_SLEEP) ); } ); } ); spin( $red, sub { spin( $yellow, sub { say "fork1: red yellow"; $t{fork1}->{r}++; $t{fork1}->{ry}++; $t{fork1}->{y}++; usleep int( rand(RAND_SLEEP) ); # not necessary but thoughtful } ); } ); } wait; } } else { #mothersbaugh ship my $cnt; # sleep works wonders # sleep 2; while ( $cnt++ < 1 ) { # no one can get red, cos it's locked until i unlock it. PID based switch. # only true on the first iteration. spin( $red, sub { spin( $green, sub { spin( $yellow, sub { say "mothersbaugh: red green yellow"; sleep 1; $t{mothersbaugh}->{r}++; $t{mothersbaugh}->{rg}++; $t{mothersbaugh}->{g}++; $t{mothersbaugh}->{gy}++; $t{mothersbaugh}->{rgy}++; # aw shgucks usleep int( rand(RAND_SLEEP) ); # not necessary but thoughtful } ); } ); } ); # you can have similar loops here: # now race for red, then wait for yellow # spin($red, sub { #say "mother\\ waiting yellow"; # spin($yellow, sub {say "mother: red yellow"; usleep int(rand(10));} ) }); #now race for red, then wait for green # spin($red, sub { #say "mother\\ waiting green"; # spin($green, sub {say "mother: red green"; usleep int(rand(10));} ) }); } wait; } END { # Let the GLOBBLING BEGIN print Dumper( \%t ); }