スレッドライブラリをつくろう
というわけで、いきなり最初から横道に逸れたうえに、そのあと四日間何も書かないという。
いや、別に飽きたんじゃなくて。pthreadあまり知らなかったので調べてたのでした。…とかはいいか。
前回の話の続き。非同期処理ライブラリをつくろうっていう話。
非同期リクエスト-レスポンスってよーするにconcurrentのことなんじゃないかなー、とも思うのだけど、concurrentって言うともうちょっと一般的になってしまう気がする。そうではなくて、ここでは、「何かリクエストを投げると、非同期に何かが動きはじめて、最後にレスポンスを返してくる」という状況(なんて呼べばいいんだろうか)に限定する。
この「非同期処理」は、結構よく遭遇するパターンで、
- 何か別スレッドに処理させる
- I/Oが動いてる
- ネットワークの向こう側で何か
- データベースサーバが
- ASICとかコプロセッサとか
特に、ドライバとか書いてると、色々なレスポンスをぐちょぐちょしたりとかはよくあると思う。
GUIのイベント処理なんかも、「表示デバイスを使ってユーザに指示を出して、イベントが返ってくるのを待つ」というように考えれば、この「非同期処理」になるはず。
けど、この非同期処理というのは、なんていうか、インターフェースがまちまちで、やりたいことは同じなのに、なんか、デバイスとかOSとか変わるだけで、全然違うのになっちゃうのだよなー、と思う。(というか、あのミドルウェヤーがアレなんだ!とかいう私情があります。)
で、そこらへんを動機として、「向こう側の処理が何であるかに関係無く非同期処理という概念を扱えるライブラリ」というようなものを作りたい、という話。
ここで、罠としては、「どんな状況でも使えるライブラリはどんな状況にも使えないライブラリ」というなんだかなんだか。
まあいいか。ライブラリを実装しながら、色々と考察する、みたいなのが目的で。ライブラリが目的じゃないです。
まず、手始めに、スレッドライブラリでも作ろう。スレッドライブラリは色々とお手本があるので、それを参考にしつつ、とりあえず、スレッドだけでも対応できるライブラリを。んで、それを洗練しながら、非同期I/Oとかも扱えるようにして、最終的には、DMA完了割り込みから分散システムまで幅広く適用できるような感じ…にしたいのだけど、そもそも分散システム全然知らないので、それは無理なのだった。
↓とりあえず作った
http://morihyphen.hp.infoseek.co.jp/files/rr.tar.gz
java.util.concurrent.* から BlockingQueue、ThreadPool、Futureあたりのコンセプトをパクってきて、C++風にしたもの。
std::string a( std::string const &x ) { return x+x; } int main() { using namespace boost::lambda; rr::pthread::ThreadGenerator tg; ftp ft( tg, 5 ); rr::thread::Future< std::string > *f(ft.execute( boost::type<std::string>(), a, std::string("a") )); printf("%s\n",f->get().c_str()); rr::thread::Future< int > *sf(ft.execute( boost::function<int (int)>(_1 + _1), 3 )); printf("%d\n",sf->get() ); }
executeの引数に渡したのが別スレッドで計算されま。
僕のC++力が足りなかったので負けてる点。↓
- テンプレートの引数が多い
- 関数の戻り型がとれなかったので、第一引数が boost::type
- コンパイル遅いとか気にしない
あとほんとにちゃんと動くのか謎。
そこらへんは本題ではないので、問題の先送りを行うとして、さて、このスレッドライブラリのインターフェースで致命的な点は何だろか。
僕は、次の二点を挙げる。
- タイムアウトが無い
- ブロックしてるのをキャンセルできない