読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

perlでforkしたプロセスとの通信を簡単に行う方法が知りたい

今作っているもので、「forkした後、子プロセスの実行の結果を最後に親プロセスに通知し、親プロセスは子プロセス群の状態をまとめて取得する」、ということがやりたいのですが、モダンかつ簡単な方法って何があるんでしょうか?

具体的には

use Parallel::ForkManager;

$pm = Parallel::ForkManager->new(5);

foreach $data (@all_data) {
  # Forks and returns the pid for the child:
  my $pid = $pm->start and next;

  # ... do some work with $data in the child process ...

  # 実行結果のサマリーを親プロセスに投げておく

  $pm->finish; # Terminates the child process
}

$pm->wait_all_children;

# 最後に親プロセスは実行した子プロセス群の実行結果のサマリーを取得する

少し調べてみたところ、名前付きパイプを使ったり、ファイルを使ったり、Parallel::Scoreboardを使ったりといろいろやり方がありそうな感じでしたが、どういうものを使うのがベストなのかいまいちわかりません。もし、こういうのがいいよというのがあれば、教えていただけると嬉しいです...

追記

fujiwaraさんに方法を教えてもらいました。なるほどー。ありがとうございます。

追記2

run_on_finishのサンプルコード書いてみました。今回の要件だったらこれだけで十分な感じでした!

#!/usr/bin/env perl
use strict;
use warnings;

use Parallel::ForkManager;

my $pm = Parallel::ForkManager->new(3);
my $result = {};
$pm->run_on_finish(
    sub {
        my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data) = @_;
        if (defined $data) {
            $result->{$pid} = $$data;
        }
    }
);

for my $id (0..10) {
    my $pid = $pm->start and next;

    $pm->finish(0, \"finished $id");
}

$pm->wait_all_children;
use Data::Dumper;
warn Dumper($result);
# $VAR1 = {
#   '77493' => 'finished 10',
#   '77490' => 'finished 7',
#   '77487' => 'finished 4',
#   '77488' => 'finished 5',
#   '77491' => 'finished 8',
#   '77486' => 'finished 3',
#   '77492' => 'finished 9',
#   '77483' => 'finished 0',
#   '77489' => 'finished 6',
#   '77485' => 'finished 2',
#   '77484' => 'finished 1'
# };