手軽に親子プロセスで hash を共有する

手軽に親子プロセスで hash みたいに使えるデータを共有するモジュール書いてみた。

ファイルにデータを書いて親子で共有している (よって実際は親子である必要もない)。

使い方

use Shared::Hash;

my $hash = Shared::Hash->new;

my $pid = fork // die;
if ($pid == 0) {
    # child
    $hash->set(message => "from child!");
    exit;
}

sleep 1;
print $hash->get("message"); # from child!

さらにアトミック操作が簡単に書ける!

$hash->lock(sub {
    # この中で書いた $hash に対する get, set はアトミック
    # 例えば以下はちゃんと $i をインクリメントして set し直せる
    my $i = $hash->get("foo");
    $i++;
    $hash->set(foo => $i);
});

またどのファイルにデータを保存するか明示的に指定すれば、 永続的にそのデータを共有できる。

$ perl -MShared::Hash -e 'Shared::Hash->new(path => "foo.data")->set(foo => "bar")'

$ perl -MShared::Hash -e 'print(Shared::Hash->new(path => "foo.data")->get("foo"))'
bar

余談

  • 最初 tcp 通信で書いてたら TIME_WAIT が 28000 をすぐに超え死んだw
  • 次に unix domain socket で書いてたみたが汎用性にかけた。
  • $hash->wait(sub {}) なるメソッドで hash に変化があるときまで wait するやつを書きたいが、なかなかいいのが書けない。 Linux::Inotify2 の検知してる変化がよくわからず、Mac::FSEvents は ディレクトリしか指定できなかった。

追記

完全にかぶったw https://metacpan.org/release/Test-SharedObject cpan に上がってるのでこちらを使いましょう。