langsmith:133
From: "HAMADA, Masaaki" <allchapters nifty.com>
Date: Wed, 29 Sep 2004 03:22:05 +0900
Subject: [langsmith:133] Re: 並行プログラミングのサポート
濱田全章です。 On Tue, 28 Sep 2004 09:09:54 +0900 Yukihiro Matsumoto <matz ruby-lang.org> wrote: > > まつもと ゆきひろです --snip-- > coroutineと併用したActiveObjectってのは面白そうですが、ちょっ > とイメージが沸きません。もしよければもうちょっと聞かせてもら > えませんか? 用語的にあまり自信がないまま使っていましたが actor と言った方が 一般的で適切なのかな。 ActiveObject と言ってしまうと ActiveObjectパターンのことになって しまいそうです。ただ actor は Schemeなどで continuationを絡めて の動作モデルの説明でも語られますが、私の頭の中ではそういったもの よりもっと具体的な (データ+手続き) + (スレッド+メッセージキュー) を備えたオブジェクト が、お互いの呼び出しをすべて非同期で行うシステム という意味でActiveObject/ActiveObjectモデルという言葉を使いました。 といってもOO的なものだけに限定するのではなくて非同期のメッセージ パッシングで通信を行うモデル全般のことをイメージしています。 Windowsのメッセージループや一般的なデバイスドライバのような イベント/割り込みドリブンなシステムも広義的に含められるんじゃ ないでしょうか。 ちなみに > |# Ioというプロトタイプベースの言語(http://www.iolanguage.com/)は > |# どうもそれっぽいことができるらしいです > > Ioは一通り見たような気がするけど、そんなのあったかなあ。並行 > は興味がないから無意識に読み飛ばしたかな。 のIoですが、ホームページから引用すると actor-based concurrency using coroutines/light weight threads とあります。syntaxとしては@をつけてメソッドを呼び出すと非同期呼び出し になるようです。任意のメソッドが同期呼び出し・非同期呼び出しと使い分け られるのがおもしろいですね。 でも結果の受け取り方がいわゆるFutureパターンを使ったもののようで私が 欲しいと思っているものとは違うようです。 # 個人的にはFutureパターンってあまり使いどころがないのでは?と思ってます。 で話をもどして、ActiveObjectですが、最近のGUIフレームワークの多くが 各GUIコンポーネントへの直接アクセスを許さずイベントループ経由で起動 することを要求しますが、これはまさにActiveObjectモデルといえますね。 これによって次のメリットを享受できます。 - デットロックを始めとするMT(マルチスレッド)プログラミング特有の問題を すべてなくせる - その結果MTセーフを実現するための、ときに過剰である排他処理が不要となり そのオーバヘッドをがなくせて、かつコードもシンプルに (排他処理が必要なところはメッセージのpost/popのところのみ) ただしやっぱりデメリットも結構大きく、他のオブジェクトの呼び出しにつき スレッドが切れる(コンテキストが切れる)ためコンテキストの保存はユーザ 任せになり、また呼び出しごとに管理しなければならないオブジェクトの 状態が増えます。 でも状態が増えることに関しては状態遷移表を作って機械的にコードに 落としていく作業だけですがまぁ力ずくですがなんとかなります。状態遷移表 からC/C++スケルトンを作成するようなコンパイラも作成可能ですし。 やはりデットロックや排他処理の不備など解析が困難なバグから逃れられる ことのメリットの方が大きいです。 とは言うもののやっぱり非同期呼び出しごとにコンテキストが切れてしまう のはやっぱり不便です。 例えば同期呼び出しのループ処理なら(以下C++っぽく書きます) void send(int i) { while (sync_call(i++)) ; // 別タスクの何かしらの処理を同期的に起動 } のように単純ですが、これが非同期になると void send(int i) { MyContext* c = new MyContext(i) // 必要なコンテキストを保存 async_call(i, &response_received_stub, c); // 別タスクの何かしらの処理を非同期的に起動 current_status = WAIT_FOR_RESPONSE; // 状態を遷移 } void response_received_stub(bool status, void* c) { // 別タスクのスレッドで動作する // 自分のスレッドで処理させるためにここはメッセージをpostするのみ Response r = new response(&response_received, status, (MyContext*)c); post(r); } void response_received(Response* r) { // ここは自分のスレッドで動く MyContext* c = r->context; if (current_status == WAIT_FOR_RESPONSE) { if (r->status) { send(c->i + 1); } else { current_status = IDLE; } } delete c; delete r; } のような感じでコード量が一気に脹らんでしまいます。 これをなるべく同期式の場合と同等に記述できるようにするにはどうしたら いいかを考えてみたところ、まず - コンテキストを複数用意して、非同期呼び出しの後はそのコンテキストを 保存して別のコンテキストでメッセージループを回し直す → non-preemptiveなスレッド(=coroutine)があればよい - やがてレスポンスが返ればもとのコンテキストを復元して処理を継続させる と考えました。つまりActiveObject自体はpreemptiveなスレッドでそれぞれ 並行動作するのですが、ActiveObjectの中身はnon-preemptiveなスレッド で並行動作するというモデルになります。 これを最初ライブラリレベルでなんとか実現できないものかなと思ったの ですが、考えてみればこれは関数呼び出しの意味を変えるというメタ操作 にあたりC/C++言語などでは実現は難しいと思いました。 というわけでこのような機能を持った言語があればなぁと思うわけです。 #実は何度か自ら作成にチャレンジしてみたもののすべて挫折しております・・ 以上のようなことを言いたかったわけですが説明できているでしょうか? 必要以上に説明してるところもあったかと思いますが、用語の不適切な 使い方なども含めてつっこみやコメントいただけるとありがたいです。 -- 濱田 全章 HAMADA, Masaaki <allchapters nifty.com> -- ML: langsmith quickml.atdot.net 使い方: http://www.atdot.net/~ko1/quickml
131 2004-09-28 00:46 [allchapters nifty.co] 並行プログラミングのサポート 132 2004-09-28 09:09 ┣[matz ruby-lang.org ] -> 133 2004-09-29 03:22 ┃┗[allchapters nifty.co] 149 2004-10-09 23:59 ┃ ┗[maeda-langsmith atus] 152 2004-10-12 21:43 ┃ ┗[allchapters nifty.co] 153 2004-10-12 23:43 ┃ ┗[maeda-langsmith atus] 157 2004-10-14 13:00 ┃ ┣[maeda-langsmith atus] 158 2004-10-15 00:30 ┃ ┗[allchapters nifty.co] 159 2004-10-15 02:08 ┃ ┗[maeda-langsmith atus] CPS (Re: 並行プログラミングのサポート) 134 2004-10-05 00:53 ┗[mas pb.highway.ne.jp] 137 2004-10-07 01:18 ┗[allchapters nifty.co]