Perl threads - capturing value returned from sub

E

Eric

Hello,

I am using Perl threads to launch multiple executions of a command in
parallel. The code to do this is:

foreach my $Machine ($self->Machines) {
my $thr = threads->new(\&doPowerAction, $Machine);
}
foreach my $t (threads->list()) {
$t->join;
}

The sub referenced is:

sub doPowerAction
{
my $machine = shift;

my $runScript = `power.exp $machine`;

if ($runScript =~ m/SUCCESS/) {
return "SUCCESS";
} elsif ($runScript =~ m/FAILURE/) {
return "FAILURE";
} else {
return "INTERNAL_ERROR";
}
}

The problem is that I don't seem to be able to figure out how to
capture the return value in the calling routine. Does anyone know how
to do this?

Thanks in advance to all that respond.

Eric
 
A

A. Sinan Unur

I am using Perl threads to launch multiple executions of a command in
parallel. The code to do this is:

Please read the posting guidelines for this group. Code you post should
be readily runnable by copying and pasting.

.... code snipped ... edited version below
The problem is that I don't seem to be able to figure out how to
capture the return value in the calling routine. Does anyone know how
to do this?

You need to store the returned values in a shared data structure.

I had to write and auxillary script to simulate the external
application.

#!/usr/bin/perl

use strict;
use warnings;

my @retvals = qw( SUCCESS FAILURE SOMETHING_ELSE );
print $retvals[ @retvals * rand ], "\n";

__END__

Then, replace your script with:

#!/usr/bin/perl

use strict;
use warnings;

use threads;
use threads::shared;

my %status;
share %status;

my @machines = qw( apple orange banana pineapple cherry );

for my $machine ( @machines ) {
my $t = threads->new( \&action, $machine );
$t->join;
}

use Data::Dumper;
print Dumper \%status;

sub action {
my ($machine) = @_;

my $output = `s.pl`;
if ( $output =~ /SUCCESS/ ) {
$status{ $machine } = 'SUCCESS';
}
elsif ( $output =~ /FAILURE/ ) {
$status{ $machine } = 'FAILURE';
}
else {
$status{ $machine } = 'INTERNAL ERROR';
}

return;
}

__END__

C:\DOCUME~1\asu1\LOCALS~1\Temp\2> r
$VAR1 = {
'cherry' => 'SUCCESS',
'banana' => 'SUCCESS',
'apple' => 'FAILURE',
'orange' => 'INTERNAL ERROR',
'pineapple' => 'FAILURE'
};
 
E

Eric

Hello,

I am using Perl threads to launch multiple executions of a command in
parallel. The code to do this is:

foreach my $Machine ($self->Machines) {
my $thr = threads->new(\&doPowerAction, $Machine);
}
foreach my $t (threads->list()) {
$t->join;
}

The sub referenced is:

sub doPowerAction
{
my $machine = shift;

my $runScript = `power.exp $machine`;

if ($runScript =~ m/SUCCESS/) {
return "SUCCESS";
} elsif ($runScript =~ m/FAILURE/) {
return "FAILURE";
} else {
return "INTERNAL_ERROR";
}

}

The problem is that I don't seem to be able to figure out how to
capture the return value in the calling routine. Does anyone know how
to do this?

Thanks in advance to all that respond.

Eric

Cancel this one; I found the answer, which was to just assign a
variable to the join:

my $result = $t->join;

Seems like I always have a breakthrough immediately after I post to
this site! :)

Eric
 
E

Eric

I am using Perl threads to launch multiple executions of a command in
parallel. The code to do this is:

Please read the posting guidelines for this group. Code you post should
be readily runnable by copying and pasting.

... code snipped ... edited version below
The problem is that I don't seem to be able to figure out how to
capture the return value in the calling routine. Does anyone know how
to do this?

You need to store the returned values in a shared data structure.

I had to write and auxillary script to simulate the external
application.

#!/usr/bin/perl

use strict;
use warnings;

my @retvals = qw( SUCCESS FAILURE SOMETHING_ELSE );
print $retvals[ @retvals * rand ], "\n";

__END__

Then, replace your script with:

#!/usr/bin/perl

use strict;
use warnings;

use threads;
use threads::shared;

my %status;
share %status;

my @machines = qw( apple orange banana pineapple cherry );

for my $machine ( @machines ) {
my $t = threads->new( \&action, $machine );
$t->join;

}

use Data::Dumper;
print Dumper \%status;

sub action {
my ($machine) = @_;

my $output = `s.pl`;
if ( $output =~ /SUCCESS/ ) {
$status{ $machine } = 'SUCCESS';
}
elsif ( $output =~ /FAILURE/ ) {
$status{ $machine } = 'FAILURE';
}
else {
$status{ $machine } = 'INTERNAL ERROR';
}

return;

}

__END__

C:\DOCUME~1\asu1\LOCALS~1\Temp\2> r
$VAR1 = {
'cherry' => 'SUCCESS',
'banana' => 'SUCCESS',
'apple' => 'FAILURE',
'orange' => 'INTERNAL ERROR',
'pineapple' => 'FAILURE'
};

Thanks for your response, Sinan. I'll give it a try.

I didn't want to paste the entire code as I thought it would only add
clutter.

Eric
 
Z

zentara

Cancel this one; I found the answer, which was to just assign a
variable to the join:

my $result = $t->join;

Seems like I always have a breakthrough immediately after I post to
this site! :)

Eric

Just to amplify slightly, you can return arrays too.
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;

# join() does three things: it waits for a thread to exit,
# cleans up after it, and returns any data the thread may
# have produced.

my $thr = threads->new(\&sub1);

my $return = $thr->join;

print "Thread returned @$return\n";

#hold for key input
<>;
##########################################################
sub sub1 {
my @values = ('1',2, 'ten');
print "@values\n";

while(1){sleep 1}

return \@values;
}

__END__
 
E

Eric

Just to amplify slightly, you can return arrays too.
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;

# join() does three things: it waits for a thread to exit,
# cleans up after it, and returns any data the thread may
# have produced.

my $thr = threads->new(\&sub1);

my $return = $thr->join;

print "Thread returned @$return\n";

#hold for key input
<>;
##########################################################
sub sub1 {
my @values = ('1',2, 'ten');
print "@values\n";

while(1){sleep 1}

return \@values;

}

__END__

Thanks - this is useful information.

Eric
 
A

anno4000

Eric said:
On Feb 26, 5:03 pm, "Eric" <[email protected]> wrote:
Cancel this one; I found the answer, which was to just assign a
variable to the join:

my $result = $t->join;

What you really do is, you assign the value of ->join to a variable.

This may sound like nit-picking, but taken literally (not just as
a slip of the fingers) your description would reveal a fundamental
misunderstanding of the meaning of "assign" in this usage.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top