Parallel::ForkManager pass a variable to global scope?
am 01.09.2006 20:44:39 von ToMeK
Hello!
My question is about Parallel::ForkManager. Is this possible to manipulate
on global variable from inside the forked process ?
#!/usr/local/bin/perl -w
use strict;
use Parallel::ForkManager;
my $pm=new Parallel::ForkManager(5);
my $counter=0;
for (1..10) {
$pm->start and next;
$counter++;
$pm->finish;
}
$pm->wait_all_children;
print $counter;
I would like such script to print 10 instead of 0?
What solution would you recommend?
Best regards, Tomasz Kraus
Re: Parallel::ForkManager pass a variable to global scope?
am 01.09.2006 22:40:46 von xhoster
Tomek wrote:
> Hello!
>
> My question is about Parallel::ForkManager. Is this possible to
> manipulate on global variable from inside the forked process ?
No, global variables are global within a process. Child processes are
separate processes, so changes they make are not reflected in the parent.
More generally, Parallel::ForkManager does not provide for back talk from
the child to the parent (except to the extent you can sneak information
into the child's exit status.). You would have to roll your own back
communication with pipes/sockets/temp files, or use a different module.
Parallel::Jobs can allow communication, but is much harder to use.
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
Re: Parallel::ForkManager pass a variable to global scope?
am 02.09.2006 01:16:34 von xhoster
Tomek wrote:
> Hello!
>
> My question is about Parallel::ForkManager. Is this possible to
> manipulate on global variable from inside the forked process ?
>
....
> What solution would you recommend?
I have whipped up something that seems to work for me. Only tested on linux
and then not thoroughly. I'm pretty sure it will *not* work as written on
Windows. Basically, you give "finish" an extra argument, and this extra
argument gets passed up to the parent via the 6th (last) argument to the
run_on_finish callback.
use strict;
use ForkManager2;
my $pm=new ForkManager2(5);
my $counter=0;
$pm->run_on_finish( sub { $counter+=$_[-1]});
for (1..10) {
$pm->start and next;
my $message="+1";
$pm->finish(0,$message);
}
$pm->wait_all_children;
print $counter;
__END__
__ForkManager2.pm__
package ForkManager2;
use Parallel::ForkManager;
use POSIX ":sys_wait_h";
use IO::Pipe;
use IO::Select;
use base qw(Parallel::ForkManager);
sub start {
my $s=shift;
my $pipe=new IO::Pipe;
my $result = $s->SUPER::start(@_);
if ($result) {
$pipe->reader();
$s->{select}=new IO::Select unless $s->{select};
$s->{select}->add($pipe);
$s->{select_hash}{$pipe}=$result;
} else {
$pipe->writer();
$s->{pipe}=$pipe;;
}
return $result;
}
sub finish { my ($s, $x,$message)=@_;
if ( $s->{in_child} ) {
print $_ $message foreach $s->{pipe};
}
$s->SUPER::finish($x);
}
sub wait_one_child { my ($s,$par)=@_;
my $kid;
while (1) {
($kid,my $message) = $s->_waitpid(-1,$par||=0);
last if $kid == 0 || $kid == -1; # AS 5.6/Win32 returns negative PIDs
redo if !exists $s->{processes}->{$kid};
my $id = delete $s->{processes}->{$kid};
$s->on_finish( $kid, $? >> 8 , $id, $? & 0x7f, $? & 0x80 ? 1 : 0,$message);
last;
}
$kid;
};
# OS dependant code follows...
sub _waitpid { # Call waitpid() in the standard Unix fashion.
die "Don't know what to do when called with other than -1" unless $_[1]==-1;
my ($s,undef,$wait)=@_;
my ($canread) = $s->{select}->can_read($wait==&WNOHANG ? 0 : undef);
return 0 unless $canread;
local $/;
my $message = <$canread>;
$s->{select}->remove($canread);
my $pid = delete $s->{select_hash}{$canread} or die;
waitpid $pid,0;
return ($pid,$message);
}
1;
>
> Best regards, Tomasz Kraus
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
Re: Parallel::ForkManager pass a variable to global scope?
am 02.09.2006 14:48:40 von ToMeK
On Sat, 02 Sep 2006 01:16:34 +0200, wrote:
> Tomek wrote:
>> What solution would you recommend?
>
> I have whipped up something that seems to work for me. Only tested on
> linux
> and then not thoroughly. I'm pretty sure it will *not* work as written
> on
> Windows. Basically, you give "finish" an extra argument, and this extra
> argument gets passed up to the parent via the 6th (last) argument to the
> run_on_finish callback.
>
>
Thank you very much for this tip, I will try using run_on_finish method!
My developing environment is FreeBSD so this should work
Regards