読者です 読者をやめる 読者になる 読者になる

AnyEvent

perl cpan

イベント駆動プログラミングのためのツールキットAnyEventをWeb+DB Vol59のAnyEventの記事読みながら試してみる。

WEB+DB PRESS Vol.56

WEB+DB PRESS Vol.56


まずは動かしてみようってことで、AnyEventとEVをインストールする。

cpanm AnyEvent
cpanm EV

ほかのモジュールに依存してなかったのが意外。

タイマーウォッチャーを書いてみる

$| = 1;
use strict;
use warnings;
use AnyEvent;
use Time::HiRes qw(time);

my $cv = AnyEvent->condvar;

my $cnt = 0;
my $t0  = time;
 
my $w; $w  = AnyEvent->timer(
    after    => 2, # はじめは2秒後に
    interval => 5, # その後は5秒間隔で
    cb => sub {
        $cnt++;
        printf "%.2f\n", time - $t0;
        if ($cnt > 5) {
            $w = undef;
            $cv->send;
        }
    },
);

$cv->recv;

### 実行結果
kotaro@mdev1:~/script> perl anyevent.pl
2.10
7.25
12.25
17.23
22.23
27.57

時間間隔はだいたい合ってるかな、くらい。

I/Oウォッチャーを書いてみる

use AnyEvent;

my $cv = AnyEvent->condvar;

my $io = AnyEvent->io(
    fh   => \*STDIN,
    poll => 'r',
    cb   => sub {
        my $line = <STDIN>;
        chomp $line;
        $cv->send($line);
    }
);

print "input something\n";
my $got = $cv->recv;
print "got($got)\n";

### 実行結果
kotaro@mdev1:~/script> perl anyevent2.pl
input something
hoge
got(hoge)

複数のイベントを発生させる

$| = 1;
use AnyEvent;

my $cv = AnyEvent->condvar;

for my $i (1..5) {
    $cv->begin;
    my $w; $w = AnyEvent->timer(after=>$i, cb => sub{
        print "timer $i\n";
        undef $w;
        #$cv->send; # これだとすぐにevent loopが終わる
        $cv->end;   # 複数のevent待つときはこっち
    });
}
$cv->recv;

# 実行結果
kotaro@mdev1:~/script> perl anyevent3.pl
timer 1
timer 2
timer 3
timer 4
timer 5

callbackを試してみる

use AnyEvent;
my $cv = AnyEvent->condvar;

my $cnt = 0;
my $w1; $w1  = AnyEvent->timer(
    after    => 1,
    interval => 1,
    cb => sub {
        $cnt++;
        if ($cnt >= 10) {
            $w1 = undef;
            $cv->send("timer:$cnt");
        }
    },
);

print "input somthing\n"; 
my $w2; $w2 = AnyEvent->io(
    fh   => \*STDIN,
    poll => 'r',
    cb   => sub {
        my $line = <STDIN>;
        chomp $line;
        $cv->send("io:$line");
    }
);

$cv->cb(sub {
   my $str = $_[0]->recv;
   print "$str\n";
});

# 実行結果
# input somthing
# hoge
# io:hoge  # 10秒以内にhoge入力
# timer:10 # 10秒経過

まとめ

AnyEventの基本をWeb+DB Pressの記事を元に試してみた(というかほぼトレース)。使いこなせればプログラムの幅が広がりそう。