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 } }
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 b +ack 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 up +date 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-timesta +mp 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
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 b +ack 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 up +date 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-timesta +mp 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"; }
In reply to simple script question scope/structure for Perl noob by scotchfx
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |