現在進行中の処理と未来の値を指し示すfuture/promise/deferred
Future::Qモジュールを書いた時に他のfuture実装についてもいくつか調べたのでメモ。
futureは(バックグラウンドで)現在進行中の処理と、それが終わったあかつきに得られるであろう結果の値を指し示す(というか保持する)オブジェクト。
言語によってfutureとかpromiseとかdeferredとか呼ばれるけど、コンセプトとしてはどれも同じようなものなのだと思う。ここでは総称して"future"という言葉を使うことにする。
futureの使い方には主に次の2種類がある。
- ブロッキングスタイル
- futureから値を取り出すAPIが存在する(get()メソッドなど)。処理が進行中で値が未確定の場合、処理が終わるまでブロックする。
- ノンブロッキングスタイル
- futureにコールバック関数を登録するAPIが存在する(then()メソッドなど)。処理が終了したらコールバック関数が実行される。登録時に既に処理が終了していたらコールバック関数はすぐに実行される。
futureによっては、これらのスタイルをどちらも利用可能なAPIが設定されていたりする。
このスタイルによっていくつかのfuture実装を分類してみると、以下のような感じだろうか。
- ブロッキングスタイル
- ノンブロッキングスタイル
- (Perl) Future, Future::Q
- (Perl) Promises
- (JavaScript) Q
- (JavaScript) jQuery.Deferred
- (JavaScript) jsDeferred
- (Ruby) em-promise, celluloid-promise
- 両対応
Qは"Promises/A+仕様"を実装したJavaScriptモジュール。em-promise, celluloid-promiseはQと同等の機能をRubyのEventMachineやCelluloidの枠組みで使えるようにしたもの(だと思う)。
IO::Async::FutureはFutureのサブクラスで、IO::Asyncのイベントループを使ってget()メソッドをブロックさせるようにしたもの。元のFutureにはget()時にブロックする機能は無い。
Scalaはさっぱり分からないけど、APIリファレンスを見るかぎり、com.twitter.util.Futureは両対応型のオブジェクトだと思う。もしかすると、PerlのFutureモジュールはこれのAPIを参考にしたのかもしれない。