Reputation: 69
I'm writing a multi threaded perl script and storing the output in a csv file. I'm trying to insert a field called sl.no. in the csv file for each row entered but as I'm using threads, the sl. no. overlaps in most. Below is an idea of my code snippet.
for ( my $count = 1 ; $count <= 10 ; $count++ ) {
my $t = threads->new( \&sub1, $count );
push( @threads, $t );
}
foreach (@threads) {
my $num = $_->join;
}
sub sub1 {
my $num = shift;
my $start = '...'; #distributing data based on an internal logic
my $end = '...'; #distributing data based on an internal logic
my $next;
for ( my $x = $start ; $x <= $end ; $x++ ) {
my $count = $x + 1;
#part of code from which I get @data which has name and age
my $j = 0;
if ( $x != 0 ) {
$count = $next;
}
foreach (@data) {
#j is required here for some extra code
flock( OUTPUT, LOCK_EX );
print OUTPUT $count . "," . $name . "," . $age . "\n";
flock( OUTPUT, LOCK_UN );
$j++;
$count++;
}
$next = $count;
}
return $num;
}
I need the count to be incremented which is the serial number for the rows that would be inserted in the csv file. Any help would be appreciated.
Upvotes: 1
Views: 71
Reputation: 385789
You're already providing mutual exclusion using flock
, so might as well take advantage of it if that's the only place $count
is used.
my $counter :shared; # Once for all threads
for (@data) {
...
flock( OUTPUT, LOCK_EX );
print OUTPUT ++$count . "," . $name . "," . $age . "\n";
flock( OUTPUT, LOCK_UN );
}
Or we can switch to just using Perl locks.
my $counter :shared; # Once for all threads
for (@data) {
...
{
lock $counter;
print OUTPUT ++$count . "," . $name . "," . $age . "\n";
}
}
In both cases, the lines in the output file will be numerical order.
Upvotes: 1
Reputation: 17155
You'll want to do something like this:
use threads;
use threads::shared;
my $counter :shared;
$counter = 1;
sub nextValue() {
lock $counter;
return $counter++;
}
And then just call nextValue()
in your code. This will insure that only one thread at a time increments the shared counter.
Upvotes: 2