Skip to content

Commit

Permalink
Added class methods for managing all children
Browse files Browse the repository at this point in the history
  • Loading branch information
exodist committed Jul 22, 2010
1 parent 02661d5 commit 7e164d8
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
14 changes: 13 additions & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,23 @@ SYNOPSIS

my $message1 = $child->read(1);

METHODS
CLASS METHODS
@children = Child->all_children()
Get a list of all the children that have been started. This list is
cleared in children when they are started.

@pids = Child->all_child_pids()
Get a list of all the pids of children that have been started.

Child->wait_all()
Call wait() on all children.

CONSTRUCTOR
$class->new( sub { ... } )
$class->new( sub { ... }, pipe => 1 )
Create a new Child object. Does not start the child.

OBJECT METHODS
$child->start()
Start the child process.

Expand Down
47 changes: 44 additions & 3 deletions lib/Child.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use strict;
use warnings;
use Carp;

our $VERSION = "0.002";
our $VERSION = "0.003";
our %META;
our @CHILDREN;

for my $reader ( qw/pid ipc exit code parent/ ) {
my $prop = "_$reader";
Expand Down Expand Up @@ -48,6 +49,19 @@ sub child(&;@) {
return __PACKAGE__->new($code, %{$META{$caller}}, %params )->start;
}

sub all_children { @CHILDREN }

sub all_child_pids {
my $class = shift;
map { $_->pid } $class->all_children;
}

sub wait_all {
my $class = shift;
$_->wait() for $class->all_children;
1;
}

sub new {
my ( $class, $code, %params ) = @_;
my %proto = ( _code => $code );
Expand All @@ -61,9 +75,11 @@ sub start {
my $parent = $$;
if ( my $pid = fork() ) {
$self->_pid( $pid );
push @CHILDREN => $self;
$self->_init_ipc if $self->ipc;
}
else {
@CHILDREN = ();
$self->_parent( $parent );
$self->_init_ipc if $self->ipc;
my $code = $self->code;
Expand Down Expand Up @@ -107,7 +123,7 @@ sub _wait {
my $x = 1;
do {
sleep(1) if defined $ret;
$ret = waitpid( $self->pid, &POSIX::WNOHANG );
$ret = waitpid( $self->pid, $block ? 0 : &POSIX::WNOHANG );
} while ( $block && !$ret );
return 0 unless $ret;
croak( "wait returned $ret: No such process " . $self->pid )
Expand Down Expand Up @@ -271,7 +287,26 @@ How child() behaves regarding IPC is lexical to each importing class.
my $message1 = $child->read(1);
=head1 METHODS
=head1 CLASS METHODS
=over 4
=item @children = Child->all_children()
Get a list of all the children that have been started. This list is cleared in
children when they are started.
=item @pids = Child->all_child_pids()
Get a list of all the pids of children that have been started.
=item Child->wait_all()
Call wait() on all children.
=back
=head1 CONSTRUCTOR
=over 4
Expand All @@ -281,6 +316,12 @@ How child() behaves regarding IPC is lexical to each importing class.
Create a new Child object. Does not start the child.
=back
=head1 OBJECT METHODS
=over
=item $child->start()
Start the child process.
Expand Down
29 changes: 29 additions & 0 deletions t/Manage.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/perl;
use strict;
use warnings;

use Test::More;
our $CLASS = 'Child';
require_ok( $CLASS );

my @all = map { $CLASS->new(sub { 1 }) } 1 .. 4;
my @get = $CLASS->all_children;
is( @get, 0, "0 children started" );

$_->start for @all;

@get = $CLASS->all_children;
is( @get, 4, "4 children" );
is_deeply( \@get, \@all, "Exact list" );

is_deeply(
[ $CLASS->all_child_pids ],
[ map { $_->pid } @all ],
"pids"
);

is( $_->exit(), undef, "Not waited " . $_->pid ) for @all;
$CLASS->wait_all();
ok( defined($_->exit()), "waited " . $_->pid ) for @all;

done_testing;

0 comments on commit 7e164d8

Please sign in to comment.