Hatena::Groupsubtech

名称未設定♥

 | 

2009-06-17

AnyEvent::FastPing 解体新書

15:40 |  AnyEvent::FastPing 解体新書 - 名称未設定♥ を含むブックマーク はてなブックマーク -  AnyEvent::FastPing 解体新書 - 名称未設定♥

多ノードにすばやくpingpongする必要があったのでAnyEvent::FastPingを使ってみたんですが、内部的にどういう処理をしてるのか気になってメモったので残しておきたいと思います。

f:id:hirose31:20090617151700j:image

  • pipe(2)を2回実行して、2ペア、都合4つのfdを作る
  • BOOTブロック(=useされたタイミング?)でpthread_create(3)してワーカースレッドを作る
  • メインスレッドとワーカースレッドは、最初に作ったpipe(2)なfdを介して互いのイベントを発火させる(図の左上と、下部の緑色の箱と矢印)
    • 例: メインスレッドが、pipe(2)なfdにwriteすると、繋がってる他方のfd(こっちはワーカスレッドが持ってる)がread可能になる。ほんで、これらのfdはepoll(7)やselect(2)で監視しているので、非同期にそのコールバックを実行可能になるわけです。
  • あと、ICMP用のSOCK_RAWなsocketも作ってて、これもepoll(7)で監視してる
    • ワーカースレッドの中でpingを送りまくる (sendto(2)しまくる)。応答は待たない。気にせず送りまくる。
    • ほどなくしてpongが返ってくると、read可能になるのでメインスレッドのそのコールバックでrecvfrom(2)しまくって結果を表示しまくる

追記。

「epoll(7)やselect(2)で監視している」のepoll(7)だとかselect(2)だとかは AnyEvent が隠蔽してくれるので、epoll(7)だとかselect(2)だとかのAPIの違いは気にする必要がないです。

こんな感じ:

our $THR_RES_W = AnyEvent->io (fh => $THR_RES_FH, poll => 'r', cb => sub {
   my $sv = _read_res
      or return;

   $sv->();
});

に、AnyEventのI/O監視のAPIを使うだけで OK です。

自分の環境 (Linux) では、use AnyEvent だけだと select(2) が使われて、

use AnyEvent;
use EV;

するとepoll(7)が使われました。


(港区在住 非同期野郎Pチーム 31)

トラックバック - http://subtech.g.hatena.ne.jp/hirose31/20090617
 |