Help - Search - Member List - Calendar
Full Version: fork() and returning hash / strings to the parent
WorkTheWeb Forums > Webmaster Resources > Perl Beginner Help
Support our Sponsors!
Tielman Koekemoer \
Hi all,

I have some subroutines that return information. Since the each
subroutine takes a snapshot of data on networked servers that should
be compared, I want the subroutines to execute in the shortest time
possible - I'd like to get all the subroutines running at the same
time. I thought of using fork() but I have not seen any code that
shows me how a forked process returns data to the parent process. And
from what I've read in the Camel book, "everything else (except file
descriptors) is copied" to the child process when fork()ed, so passing
the reference ta a hash will not work. But what if the child was
generating hashes and wanted to pass it to the parent?

Q: How can I pass info (hashes / strings) from a child process to a
parent when the child is done processing?

Currently my code looks like:

BEGIN
#!/usr/bin/perl -w

use strict;

my ($val, $val2, %opc01, %opr01, %opd01);

sub q_db;
sub build_hash;

build_hash("db1", %opc01); # This should be forked or something
build_hash("db2", %opr01); # This should be forked or something
build_hash("db3", %opd01); # This should be forked or something

sub build_hash {
for( q_db("$_[0]") ) {
# extract fields with regex
$_[1]{"$val"} = ("$val2");
}
}

sub q_db {
# Execute "db" query on another host
}
END

TIA



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This e-mail and its contents are subject to the Telkom SA Limited
e-mail legal notice available at

http://www.telkom.co.za/TelkomEMailLegalNotice.PDF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Zentara
On Thu, 30 Jun 2005 10:32:07 +0200, [Email Removed] (Tielman
Koekemoer ) wrote:
QUOTE

I have some subroutines that return information. Since the each
subroutine takes a snapshot of data on networked servers that should
be compared, I want the subroutines to execute in the shortest time
possible - I'd like to get all the subroutines running at the same
time. I thought of using fork() but I have not seen any code that
shows me how a forked process returns data to the parent process. And
from what I've read in the Camel book, "everything else (except file
descriptors) is copied" to the child process when fork()ed, so passing
the reference ta a hash will not work. But what if the child was
generating hashes and wanted to pass it to the parent?

Q: How can I pass info (hashes / strings) from a child process to a
parent when the child is done processing?

When you want to fork and return information, it is a good place to
use threads and threads:shared.

If you are stuck with forking, you can
use pipes (child writes to pipe, parent reads it)
use sockets
use shared memory segments (probably the fastest, but trickier)
write to a database
write to a temp file

Personally I would go with threads and threads:shared

This is the way I do it, but I stick to basics and do everything
manually. There are other, (probably better) ways. If you use threads,
you can pass scalar data. You could serialize your hash if you wanted,
or setup as many shared scalars as you need to pass the info.

A thread must go to the end of it's code block before it can be
"joined", so that is the reason for the funky FINISH: label.

You will have to work out some scheme for detecting when your
thread is finished, and read the results before joining it. I normally
use threads in conjunction with a gui like Tk or Gtk2, so I have more
tools to setup timers to watch the threads.

Anyways, here is a simple commandline example, notice there is some
time consumed while looping thru the tests, so some threads will
return a value higher than the cutoff of 5. But that is one of the
design problems for you to work out. You could have the thread
code "stop and hold" at a certain value, waiting to be joined.

#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;

$| = 1;

my %threads;

foreach (1..10){
share $threads{$_}{'die'};
share $threads{$_}{'data'};
$threads{$_}{'die'} = 0;
$threads{$_}{'data'} = 0;
}

foreach (1..10) {
$threads{$_}{'thread'} = threads->new('StartTest');
}

#while(1){} #if you just want to watch them count up :-)
my @threads = (1..10);
while(1){
foreach my $t (@threads){
if($threads{$t}{'data'} > 5){
$threads{$t}{'die'} = 1;
$threads{$t}{'thread'}->join;
@threads = grep { $_ != $t } @threads;
}
}
if(scalar @threads == 0){last}
}

print "n", "All threads donen";
##########################################################

sub StartTest {
my $self = threads->self;

print "Thread ", $self->tid, " startedn";

while(1){
if( $threads{$_}{'die'} == 1){goto FINISH}
else{
print "From thread $self->",$threads{$_}{'data'}++,"n";
sleep 1;
};
}
FINISH:
print "Thread ", $self->tid, " endingn";
}

__END__












--
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html

Wiggins d'Anconia
zentara wrote:
QUOTE
On Thu, 30 Jun 2005 10:32:07 +0200, [Email Removed] (Tielman
Koekemoer ) wrote:

I have some subroutines that return information. Since the each
subroutine takes a snapshot of data on networked servers that should
be compared, I want the subroutines to execute in the shortest time
possible - I'd like to get all the subroutines running at the same
time. I thought of using fork() but I have not seen any code that
shows me how a forked process returns data to the parent process. And

from what I've read in the Camel book, "everything else (except file

descriptors) is copied" to the child process when fork()ed, so passing
the reference ta a hash will not work. But what if the child was
generating hashes and wanted to pass it to the parent?

Q: How can I pass info (hashes / strings) from a child process to a
parent when the child is done processing?


When you want to fork and return information, it is a good place to
use threads and threads:shared.

If you are stuck with forking, you can
use pipes  (child writes to pipe, parent reads it)
use sockets
use shared memory segments (probably the fastest, but trickier)
write to a database
write to a temp file

[snip threads discussion]


If you are stuck with forking and need to do some of the above I would
switch to POE and let it handle the setting up of pipes and and the I/O.
Using its filters you can return arbitrarily structured data through
references (freeze/thaw model) or just simple strings (among others, or
write your own). POE::Wheel::Run will handle the fork, and you can pass
a subroutine for it to fork/exec just as you mentioned. POE has a
learning curve, a relatively steep one at that, but it will save you
time in the end.

http://poe.perl.org

Good luck,

http://danconia.org


PHP Help | Linux Help | Web Hosting | Reseller Hosting | SSL Hosting
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2005 Invision Power Services, Inc.