Forum Moderators: coopster & phranque

Message Too Old, No Replies

Parallel subroutines...

How to?

         

MonkeeSage

3:45 am on Sep 18, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm a relative newbie to Perl, but I'm doing pretty well I think, mainly because I have an OK understanding of JavaScript and in alot of places they share the same syntax (or very close to the same at least).

But I'm having a problem trying to execute a subroutine while at the same time executing a (blocking) library method, until the library method returns.

Here is what I mean ($svr is an instance of $ftp, which is a NET::FTP object)...

-----------------------

sub download { 
my ($svr, $file) = @_;
print "Downloading...";
if ($svr->get($file)) {
return 1;
}
else {
return 0;
}
}

sub dodownload {
my ($srv, $file) = @_;

&removefile($file);
$started = 1;

if (&download($srv, $file)) {
print "\n\nDownloaded file: $file\!\n\n";
$srv->quit();
}
else {
$srv->quit();
&dienice("Failed to download file: $file\!\n");
}
}

-----------------------

And I want to do this...

sub checkdone { 
print '.';
sleep(1);
&checkdone;
}

...until

$svr->get($file)

-----------------------

I tried using fork(), like so...

my $done = 0; 

sub checkdone {
print '.';
sleep(1);
if ($done ne 1) {
&checkdone;
}
}

sub download {
my ($svr, $file) = @_;
print "Downloading...";
# if called here, download never starts,
# because the sub never returns
# &checkdone;
my $forkID = fork();
if ($forkID eq 0) {
if ($svr->get($file)) {
return 1;
}
else {
return 0;
}
}
else {
# if called here, download starts,
# but sub still never returns
# (does it also get fork()'d or
# something?)
&checkdone;
}
}

sub dodownload {
my ($srv, $file) = @_;

&removefile($file);
$started = 1;

if (&download($srv, $file)) {
print "\n\nDownloaded file: $file\!\n\n";
$srv->quit();
$done = 1;
}
else {
$srv->quit();
$done = 1;
&dienice("Failed to download file: $file\!\n");
}
}

...but it just keeps on doing

&checkdone;
, even after
$done eq 1
(which I checked by printing out
$done
).

-----------------------

How can I do what I'm trying to do? Thanks in advance!

Jordan

Ps. This script will be run locally, so modules are no problem; I can install any that are needed.

MonkeeSage

3:59 am on Sep 18, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Pss. I also tried an explicit kill($forkID) (and $$) but the checkdone sub just happily continues to spit out dots...

Jordan

MonkeeSage

11:42 am on Sep 18, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I got it to work using 5.8's threads module and having
$done
as a ': shared'. Here's what I've got now...

use threads; 
use threads::shared;

my $done : shared = 0;

...

sub checkdone {
my ($file) = @_;
if ($done ne 1) {
if (-e $file) {
print substr((stat $file)[7]/1048576, 0, 4);
print " mB done...\n";
}
else {
print "Start Data...\n";
}
$count = $count + 3;
sleep(3);
return &checkdone($file);
}
else {
print substr((stat $file)[7]/1048576, 0, 4);
print " mB done...\n";
if ($count > 60) {
$count = $count/60 . " minute(s)";
}
else {
$count = $count . " second(s)";
}
}
}

sub download {
my ($svr, $file) = @_;
print "\nDownloading...\n";
if ($svr->get($file)) {
$svr->quit();
$done = 1;
return 1;
}
else {
$svr->quit();
$done = 1;
return 0;
}
}

sub dodownload {
my ($svr, $file) = @_;
&removefile($file);
$started = 1;
my $thr;
$thr = threads->new(\&download, $svr, $file);
&checkdone($file);
my ($ret) = $thr->join;
if ($ret eq 1) {
print "\nDownloaded file: $file in $count\!\n\n";
}
else {
&dienice("\nFailed to download file: $file\!\n");
}
}

Jordan