# 追記: 2010 19 Feb - このコード何回も書くの面倒くさくなったので、
# CPANにモジュールアップロードしてしまいました
# http://search.cpan.org/dist/AnyEvent-FIFO/
コールバック$cbの最初の引数をguard変数にしておき、キューの1スロットを使用している間はこのguard変数をundefしないようにしておく感じです。
use strict;
use AnyEvent;
use AnyEvent::Util;
my @q; # 実際にコールバックを入れておくところ
my $ACTIVE = 0; # 現在の使用中スロット
my $MAX_ACTIVE = 1; # 最大何個のコールバックを「同時」に行うか(もちろん本当に同時じゃないよ!)
sub drain_queue {
while ( @q && $ACTIVE < $MAX_ACTIVE ) {
if (my $cb = shift @q) {
$ACTIVE++;
$cb->( AnyEvent::Util::guard {
$ACTIVE--;
drain_queue();
});
}
}
}
デモ程度に 1から10までの数字を(最低)0.5秒あけてから表示するコード:
my $cv = AE::cv;
# XXX - 12/1: よくよく考えたらここはbegin()/end()使うところだったので
# 修正しておいた
for my $x (1..10) {
$cv->begin;
push @q, sub {
my $guard = shift;
my $w; $w = AE::timer 0.5, 0, sub {
undef $guard;
undef $w;
warn $x;
$cv->end;
};
};
}
drain_queue();
$cv->recv;
これ以外の実装の仕方もあるんだけれども、これだと次のqueue popとかを自前で呼ぶ必要がないのが素敵です。
コメント