# 追記: 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とかを自前で呼ぶ必要がないのが素敵です。
コメント