Fork::setTimeout
[g:subtech:id:cho45:detail](http://subtech.g.hatena.ne.jp/cho45//detail)さんが、AnyEventでJavaScriptのsetTimeout()的なものを書いていたので([AnyEvent::setTimeout - 冬通りに消え行く制服ガールは✖…
g:subtech:id:cho45:detailさんが、AnyEventでJavaScriptのsetTimeout()的なものを書いていたので(AnyEvent::setTimeout - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。 - subtech)、forkで同じようなことをしてみました。
use Fork::setTimeout;
my $timer = setTimeout(sub {
warn "1sec!";
}, 1000);
とか書けます。setTimeout()にわたしたcoderefをforkした子プロセスで実行しつつタイマーオブジェクトを返して、そいつがスコープを抜けるタイミングで適当にwaitpidしたりします。
が、以下のようなコードがうまくいかない。どうしたらいいんだろう。
my $i = 0;
setTimeout(sub { $i++ }, 1000);
sleep 3;
warn $i; #=> 0
$iは1になってほしい。
追記
.@antipop それ Test::SharedFork のアレでできるよ
2011-07-26 09:12:17 via Echofon
forkなんだから共有しなくていいんじゃないの。したいときだけtieとかIPC::*なんちゃらとか。
2011-07-26 10:39:59 via TweetIrcGateway
諸氏に教えをいただいた。
上記の$iは、子プロセスにコピーされるので親プロセスから見ると0になっちゃうのは当然。プロセス間でデータを共有したい場合は、たとえばIPC::Shareableを使ってshared memoryなりなんなりを通して共有するとよいようだ。というわけで、以下のように書くと期待通りにはなりました。
use IPC::Shareable;
my $handle = tie my $i, 'IPC::Shareable', undef, { destroy => 1 };
$i = 0;
my $timer5 = setTimeout(
sub {
$handle->shlock;
$i++;
$handle->shunlock;
}, 1000
);
sleep 3;
warn $i; #=> 1
参考: Parallel::ForkManager + IPC::Shareable で複数のプロセスで変数を共有する
追々記
!id:nihenさんが共有データのIPCをすることなく、いい感じにcallbackを実行するやりかたを書いてくださいました。
SIGCHLDで実行するのですねー。なるほどなるほどー。勉強になります。