POE: Perl Object Environment についてちょこちょこと調べたり、スクリプトを書いたりしてますが、面白いです。そして強力。
POE って何? と聞かれても応用範囲が広すぎるとか、僕自身まだ一部しか理解していないということもあって、一言で説明するのは難しいのですが、Perl でデーモンを書いたり、ネットワーキング、マルチタスクな処理をしたりする時に使うと便利なフレームワークと言ったところでしょうか。(実際は「Object Environment」という言葉が表すとおり「環境」というもっと大きな枠組みとしてのコードの集合体、のような気がします。)
例えば、socket と select を使って fork しないマルチスレッドな echo サーバを書けと言われた場合、低レベルな API を使って非ブロッキング処理を考慮しつつ、各セッション毎の領域を侵害しないように書いていったりすることを考えると結構めんどくさかったりします。
ところが POE だと、
#!/usr/local/bin/perl
use warnings;
use strict;
use POE;
use POE::Component::Server::TCP;
POE::Component::Server::TCP->new
(
Port => 12345,
ClientInput => \&client_input,
);
POE::Kernel->run;
exit;
sub client_input {
my ( $heap, $input ) = @_[HEAP, ARG0];
$heap->{client}->put("echo: $input");
}
と、わずかこれだけのコードでマルチスレッドな echo サーバとして動いてくれます。便利でしょう。もちろん、これは POE の応用例のごく一部でしかありません。
POE は「perl で書かれた小さな OS であると言っても過言ではない」と言われたりします。POE のアーキテクチャは非常に汎用的な設計になっていて、その作りが OS のそれにそっくりだったりするところから来ているようです。
POE を使ったプログラミングでは、一つのタスクを Session (POE::Session インスタンス) として扱います。すべての Session は Kernel (POE::Kernel) によって管理されます。POE::Session がプロセス、POE::Kernel がカーネルだと見れば、OS のアーキテクチャにそっくりです。
POE::Kernel が複数の POE::Session インスタンスを同時に動かすことでマルチスレッドが実現できます。各 Session には heap と呼ばれる、Session に固有のデータ保持領域が割り当てられます。POE::Session は POE::Kernel を通すことで他の Session と通信することができます。これは、プロセス間通信に相当しますね。また、生存期間を終えた Session は POE::Kernel がガベージコレクトにより回収し、リソース解放などの面倒を見てくれます。
こういった POE のアーキテクチャは OO により抽象化されていて、先のコードのように自然な形で応用することができるようになっています。
ある程度定型化された処理は、POE::Component::Server::TCP (TCP ベースのサーバ用のコンポーネント)や POE::Wheel::SocketFactory (non-blocking なソケットを作るための車輪)のように高度に抽象化されて、モジュールとして CPAN で配布されていたりするので、わざわざ車輪を再開発する必要もありません。
僕が手始めに読んだのは perl.com: A Beginner's Introduction to POE 。POE の概要がざっくり説明されている文書です。POE::Wheel::SocketFactory や POE::Wheel::ReadWrite を使った、eval による計算式実行デーモンのコードが載ってます。(ここで扱ってるコードにおける POE のインタフェースはちょっと古いので注意です。) POE のイメージを掴むとっかかりとして丁度いいです。
次は、POE: Evolution of a POE Server。POE のアーテクチャに軽く触れた後、POE を使わずに書かれた echo サーバデーモンを POE を使って書き直していきながら解説するというチュートリアルになってます。IO::Socket、IO::Select を使った従来型のサーバが POE を利用することによって華麗に昇華していく様がとてもエキサイティングです。
今は POE: POE Cookbook で色々なコードを眺めつつ、いろいろ試したりしています。なかなか楽しいです。
POE::Component::IRC は IRC クライアント (IRC bot) を書くための POE コンポーネント、POE::Component::Server::XMLRPC は XMLRPC over HTTP なサーバを書くための POE コンポーネントです。これらを組み合わせて使うことで、Weblogs.Com Ping を受信して、更新状況を喋る IRC bot なんてのが簡単に書けたりします。今度の Shibuya.pm でのデモはこれでいこうかなと思ってたりします。すでに動くものはできてます。
実は、最初 Net::IRC を使ってせこせこと書いていて、Ping サーバと bot の通信はどうしようかなあとか考えていたところ、宮川さんから POE を使うと良いと教えてもらって、POE って何ですか!? ってところから始めたのがつい先日の出来事だったりしてます。
一つのスクリプトで XMLRPC サーバと IRC bot という性格の異なる二つのタスクが同時に実現できて、且つそれが協調動作するという、なんか素で書いたらかなり厄介そうなものが POE ならほんの数十行です。素晴らしい。これなんかは、まさに perl でかかれた小さな OS そのものかもしれません。