イベントインターフェースの分類

修論ではmoshFFIとyuniSchemeから移植したFFI Threadsを使ってやっていたイベント処理だけど、フレームワーク自体は他の言語でも有用と考えられるので、C言語で書きなおしてライブラリとして整備することにした。その方がmoshにも取り込みやすいと考えられる。
イデアとしては、デバイスやネットワークを接続する"ピタゴラマシン"を作るためのライブラリということになる。"ピタゴラマシン語"として制限されたScheme(yuniScheme)を採用し、そのインタプリタも含む。これにより、GCの遅い*1moshでも、セミ-リアルタイムの処理が可能になると考えている。
難しい問題は、多岐に渡るイベントインターフェースを統合しなければならないという点で、様々なライブラリが、本当に様々なセマンティクスを提供している。
libemitでwrapしたいライブラリを3種類に分類した。libemitではコールバックスタイルAPIUNIXのシグナルを使ったI/Oは無視する。libemitを使用するアプリケーション(今回の場合mosh)を単にクライアントと呼ぶ。

Type0 : イベントを提供せず、単にemitのみを行う / 同期API

LLVMによるコードの生成やOS標準のopen()等はここに相当する。
また、多くの出力I/Oもここに分類される。つまり、送信データは一旦カーネル側のバッファにコピーされるため、多くのシチュエーションでは送信の完了を待つ必要は無い。

Type1 : マルチプレクサ

クライアントに終端されるマルチプレクサ。複数のイベントを取り纏めて同期APIに変換するための仕組みを大抵のOSは装備している。例えばWaitForMultipleObject(Win32)やselect、poll等。
この階層のAPIとしては、libeventがほぼ決定的と言える。UNIX fdに関しては十分な抽象化を提供している。問題は、UNIX fdを扱うかどうか微妙なライブラリがいくつか存在することで、例えばlibusbは専用の非同期APIを提供している。
また、libeventは時間的イベントに対する配慮が微妙という問題がある。言うまでもなく、libeventはスループット型のアプリケーションのために書かれたので、そもそもマルチメディアイベントの類を扱う需要自体が殆ど無い。

Type2 : ディスパッチ

クライアントに終端されない、データ駆動型のディスパッチ。今後はこのディスパッチ型のAPIが特に重要になると考えられる。libemitの重要な目的は、Type0やType1のAPIをType2に見せる汎用のwrapperを提供することにある。
ここにはGrand Central Dispatch(GCD)やOpenCLのようなAPIが分類される。
クライアントに終端させないことは、いくつかの重要なメリットを生む。プログラムは自然にスケールし、イベントストリームの優先度を扱うためのフレームワークを提供することができる。
Type2 APIを使う場合、クライアントは1) データ/イベントソースを生成する 2) キューや処理コードとソースを接続したグラフを生成しAPIを使用して構築する 3) 処理の開始を指示し、終わるまで指をくわえて見ている というフローになる。
Type0/1 APIとの最も大きな違いは、ソースの宣言だけでなく処理プログラムの提供も行う必要があるという点となる。GCDはC言語に対するBlocks拡張を用い、OpenCLではC99のサブセットを利用する。
既に普及しているType2 APIとして、DirectShowやGStreamerのようなメディアAPIが有る。これも、同様に、グラフを構築して指をくわえるタイプのプログラムとして実装できる。
Type 2 APIは一度構築したグラフを実行中に制御できることがある。例えば、DirectShowでは、グラフの再生中にシークしたり現在の再生時刻をクエリすることができる。

APIの考え方

これらのType分類は、そのまま抽象化レイヤの階層に対応する。つまり、

  • Level 0 Interface - パケットportの生成と、パケットの送受信
    • e.g.) USBパケットの送受信、OpenGL描画命令の発行
  • Level 1 Interface - OS毎の、対応するイベントオブジェクトの記述
  • Level 2 Interface - 処理グラフの構築と制御

のようになる。例えばLevel 0 Interfaceによる抽象化によってsend_packetという統一APIでUSBパケットの送信やGL描画命令の発行が行えるだろう。しかし、GLの描画命令は、一般にそのリストを与えて発行するのでそのための配慮も必要となる。等。

*1:Boehm GC自体はそれなりに高速(仮に正確なGCを作ったとしてもBoehm GCより高速にするのは挑戦的)だが、リアルタイム性を保証するための方法が無い。