Greetings,
I'm a former hardware guy (embedded C & C++ experience mainly) trying to get up to speed with Java and Perl for a set of graduate courses.
I've written up a Perl script that simulates a scheduling algorithm, the script consists of two primary loops the first to parse process/event info from a file, the second to schedule each event. The first loop executes fine, but I'm having issues getting the script to run with my second loop - since I'm doing this in Perl (with no main block) I'm concerned it may have something to do with the scope of my vars (my three primary data structures are a 2d array used as an array of stacks, and two hashes used to reference event dependencies.
I am using Eclipse/EPIC/ActiveState Perl 5.8.6 to debug my script. I'm a noob at this, although I've had some experience using regular expressions/Perl in a Unix environment, admittedly at the moment I'm completely stuck...
Parse loop (appears to work fine):
foreach $line (<FILE>)
{
chomp $line;
if ($line =~ m/(\d)-(\d)->(\d)-(\d)/)
{
#create local sender and receiver vars
my $sp = "$1-$2";
my $rp = "$3-$4";
#update sender and receiver hashes
$sender{$sp} = $rp;
$receiver{$rp} = $sp;
print "enter $sender{$sp}->$receiver{$rp} in dependency hashes\n";
}
elsif($line =~ m/(\d)-(\d)/)
{
#create local process var
my $p = "$1-$2";
#queue process on @p_s multi-dimensional array
unshift (@{$p_s[$1]},$p);
print "unshift $p_s[$1][0] onto process array\n";
$numevents++;
}
else
{
print "\nunmatched line: $line \n";
chomp($line); #remove empty newlines in input file
}
}
Scheduling loop (script produces no output with this included)
while($timestamp <= $numevents)
{
print "\ntimestamp: $timestamp, numevents: $numevents\n";
foreach $pid (@p_s)
{
my $p_e = 0, $p_t = 0;
#for every process pop the first event and examine it
if($p_e = pop @{$p_s[$pid]})
{
#if process-event has receiver-dependency then push it back on the stack
if($receiver{$p_e})
{
push (@{$p_s[$pid]},$p_e);
}
else
{
my $s_o = 0;
#else if process-event has sender-obligation then update sender and reciever hashes
if($s_o = $sender{$p_e})
{
delete $sender{$p_e};
delete $receiver{$s_o};
}
#and then enqueue process-event with process-timestamp in schedule hash
if($p_e =~ m/(\d)-(\d)/)
{
$p_t = "$timestamp.$1"
}
else
{
print "\nerror parsing processor-event signature\n";
}
$schedule{$p_e} = $p_t;
unshift (@totalorder, $p_t);
}
}
}
$timestamp++;
}
Since the timestamp of each event is it's occurance relative to every other event, I don't need any abosolute means of stamping each event, and I can say that my $timestamp < $numevents always. I do need to output the total order of events, as well as each event and it's timestamp, hence I create a third and fourth hash and array respectively, %schedule and @totalorder. I have created a subroutine check_data() that outputs all of the data stored in all of my major data structures, the definition for this is located after all of the code I have in what would be my main() block in C/C++.
Sorry for the lengthy description - anyone here have an idea why the first loop would execute but not the second?
Do I need to initialize my vars prior to use, ex:
$pid = 0; #process index
@p_s = (); #2d process array/stack
%sender = (); #sending event hash
%receiver = (); #receiving event hash
$numevents = 0; #total number of events in all processes
$timestamp = 0; #timestamp for event scheduler
%schedule = (); #hash of each event with timestamp
@totalorder = (); #final order of each event
Should be declared before the first loop (I've tried this already w/o success but maybe I'm missing something)?
Will vars declared on the fly in the first loop be visible in the second loop?
I will append the full script at the end of this post for the reference of the more experienced perl-sons who are hopefully perusing this forum...
###################Lamport.pl
###################
#!/usr/bin/perl -w
#begin main routine
#$pid = 0; #process index
#@p_s = (); #process stack
#%sender = (); #sending event hash
#%receiver = (); #receiving event hash
#$numevents = 0; #total number of events in all processes
#$timestamp = 0; #timestamp for event scheduler
#%schedule = (); #= Tie::IxHash->new();
#@totalorder = ();
#read process/event input from file
open FILE, $ARGV[0]
or die "$ARGV[0] can't be opened:\n$!";
#local $/; # Set input to "slurp" mode.
#initialize process/event stack/hash from input file
print "\nbegin Lamport's algorithm for input file $ARGV[0]\n";
foreach $line (<FILE>)
{
chomp $line;
if ($line =~ m/(\d)-(\d)->(\d)-(\d)/)
{
#create local sender and receiver vars
my $sp = "$1-$2";
my $rp = "$3-$4";
#update sender and receiver hashes
$sender{$sp} = $rp;
$receiver{$rp} = $sp;
print "enter $sender{$sp}->$receiver{$rp} in dependency hashes\n";
}
elsif($line =~ m/(\d)-(\d)/)
{
#create local process var
my $p = "$1-$2";
#queue process on @p_s multi-dimensional array
unshift (@{$p_s[$1]},$p);
print "unshift $p_s[$1][0] onto process array\n";
$numevents++;
}
else
{
print "\nunmatched line: $line \n";
chomp($line); #remove empty newlines in input file
}
}
print "\ncompleted $ARGV[0] parsing\n";
close FILE;
check_data();
#schedule process events according to Lamport's algorithm
while($timestamp <= $numevents)
{
print "\ntimestamp: $timestamp, numevents: $numevents\n";
foreach $pid (@p_s)
{
my $p_e = 0, $p_t = 0;
#for every process pop the first event and examine it
if($p_e = pop @{$p_s[$pid]})
{
#if process-event has receiver-dependency then push it back on the stack
if($receiver{$p_e})
{
push (@{$p_s[$pid]},$p_e);
}
else
{
my $s_o = 0;
#else if process-event has sender-obligation then update sender and reciever hashes
if($s_o = $sender{$p_e})
{
delete $sender{$p_e};
delete $receiver{$s_o};
}
#and then enqueue process-event with process-timestamp in schedule hash
if($p_e =~ m/(\d)-(\d)/)
{
$p_t = "$timestamp.$1"
}
else
{
print "\nerror parsing processor-event signature\n";
}
$schedule{$p_e} = $p_t;
unshift (@totalorder, $p_t);
}
}
}
$timestamp++;
}
check_data();
#create "totalorder" copy of schedule hash
#pop totalorder as stack and print
#sort and print schedule hash
#end MAIN routine
#begin subroutine definitions
sub check_data
{
#print "numprocs = $numprocs\n";
print "\ntimestamp = $timestamp\n";
print "numevents = $numevents\n";
print "\ncontents of process stack:\n";
foreach my $r (@p_s)
{
my $j=0;
foreach my $c (@{$r})
{
print "P$i j: $j Value: $c\n";
$j++;
}
$i++;
print "\n";
}
print "\nsender key/value pairs:\n";
foreach my $k (sort keys %sender)
{
print "$k => $sender{$k}\n";
}
print "\nreceiver key/value pairs:\n";
foreach my $k (sort keys %receiver)
{
print "$k => $receiver{$k}\n";
}
print "\nschedule key/value pairs:\n";
foreach my $k (sort keys %schedule)
{
print "$k => $schedule{$k}\n";
}
print "\ncontents of totalorder queue:\n";
foreach my $r (@totalorder)
{
print "$r, ";
}
print "\n\n";
}