# 追記: 2010 19 Feb - このコード何回も書くの面倒くさくなったので、
# CPANにモジュールアップロードしてしまいました
# http://search.cpan.org/dist/AnyEvent-FIFO/

まぁ考えてみれば単純な話ですけど、いわゆるGuardを使うとよいです。参考はAnyEvent::HTTP

コールバック$cbの最初の引数をguard変数にしておき、キューの1スロットを使用している間はこのguard変数をundefしないようにしておく感じです。
   use strict;
   use AnyEvent;
   use AnyEvent::Util;

   my @q; # ~_~Z~[~A~B~C~C~C~P~C~C~B~B~R~E~B~L~A~A~J~A~O~A~A~S~B~M
   my $ACTIVE = 0; # ~O~\~A使~T中~B~C~C~C~C~H
   my $MAX_ACTIVE = 1; # ~\~@大~U~@~K~A~B~C~C~C~P~C~C~B~B~R~@~L~P~L~Y~B~@~M~A~L~A~F~A~K~H~B~B~A~B~M~B~S~\~S~A~P~L~Y~B~A~X~B~C~A~A~D~B~H~A~I

  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: ~B~H~A~O~B~H~A~O~@~C~A~H~A~_~B~I~A~S~A~S~Abegin()/end()使~A~F~A~A~S~B~M~A| ~A~A~_~A~A
# 修正~A~W~A~A~J~A~D~A~_
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とかを自前で呼ぶ必要がないのが素敵です。

カテゴリ

トラックバック(1)

このブログ記事に対するトラックバックURL: http://mt.endeworks.jp/cgi-bin/mt-tb.cgi/2417

AnyEvent::HTTP では、同一ホストに対して同時に接続する数を制限している。セマフォを使うのではなく、単なるカウンタを使っていることらしいことが、AnyEvent + Coro での並行ダウンローダの習作 その 2 - 昨日知ったことに引用したコードからわかった。しかし、その意味 読む

コメントする

筆者

daisuke - a.k.a. "lestrrat", Perl hacker at Livedoor Inc, Japan Perl Association 代表理事

このブログ記事について

このページは、Dが2009年11月24日 14:01に書いたブログ記事です。

ひとつ前のブログ記事は「人生の気合いが表れるゲームです。」です。

次のブログ記事は「Perlな人たち、どこにいるの」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.1