ELMのもととなったプログラムは、非常に多くの単純な動作をする 要素が互いに影響を及ぼしあう環境をシミュレーションするために 作成されています。ここで、ELM環境内の要素の身になって考えてみ てください。以下にあげられるような機能は必須であることが想像で きるはずです。しかしJavaのデフォルトのオブジェクトはそのような 機能がないのです。そして、この機能は、近年注目されるAgent指向 コンピューティングと非常に親和性があります。 以下ELM環境内のELMオブジェクトの機能を見ていきます。
オブジェクト指向言語では、各オブジェクトにはメソッドが あり、メソッドの中にそのオブジェクトの動作が記述されます。 Javaのオブジェクトもメソッドをもちますが、普通にプログラム すると、各オブジェクトのメソッドが実行されるかどうかは、 ほとんどの場合、他のオブジェクトからそのメソッドが呼び 出されるかどうかにかかっています。もちろんオブジェクト 内のメソッドから自分自身のメソッドを呼び出すことも可能 ですが、そのような場合は、主となるメソッドの細かい動作を 記述してあるサブルーチン的なメソッドであることがほとんど です。
そこで、オブジェクトの身になって考えてみてください。 自分のどのメソッドを実行して、自分がどのように動作 するか自分で決めたい、つまりどのメソッドを実行するか 決める部分のプログラムも自分自身の中に持ち独自に 実行したいと、思いませんか?このようなことを可能に するには、スレッドのような仕組みがどうしても 必要です。ELMでは、これを実現する方法を提案しています。
上で説明したように、自分のメソッドを自分で、 呼び出す機能があっても、やはり、他のオブジェクトから の要求を受けることができなければ意味がありません。 ここでは、他のオブジェクトからの要求を受ける場合を 考えます。
たくさんの同じタイプのオブジェクトをつくり それらの間での相互作用をシミュレーションする場合を 考えてみてください。オブジェクト指向言語では オブジェクトは全てクラスから生成されます。もし、 これらのオブジェクトが一つのクラスから生成された ものだとすると、Javaのオブジェクトではこまった ことが起こります。Javaのメソッドにはprivate, protected,publicなどの種類がありますが、 同じクラスから生成されたオブジェクトどうし ならば、他のオブジェクトのprivateやprotectedの メソッドをも呼び出せてしまうのです。
それに、Javaのオブジェクトは他のオブジェクトから メソッドを呼び出されたときに、どのオブジェクトから 呼び出されたのかを知る一貫した方法がありません。つまり、 なんの工夫もない通常のプログラムでは、誰から呼び出された としても、同じように答えるしか方法がなく、呼び出された相手に よって要求を拒否したり、返答の内容を変更することが できません。もしくはそのような仕組みを自分で作成する 必要があるでしょう。ELM上でのメッセージの伝達を用いれば この問題を克服できます。
何の工夫もされていないJavaのオブジェクトは、 自分の置かれた状況を把握することができません。 そもそも、自分の周りの状況というものが存在 しないのです。つまり、デフォルトのJavaオブジェクトは 目も見えないし耳も聞こえないのです。
一方ELMのオブジェクトは必ずElmSetオブジェクトの 中にいます(一番トップのElmSetオブジェクトは例外)。 この自分のいるElmSetのことを"親"と呼び、 ELMオブジェクトのいる場所のデータを持っています。 ELMオブジェクトは自分の親に対して、周りに誰が いるのかをたずねることができるし、自分のいるばしょ についてのさまざまな状況を調べることができます。 どのようなことが調べられるかはElmSetの機能に よります。基本的な機能はElmSetにすでにあるはずですが、 ElmSetはユーザが自由に拡張することも可能です。
前章で述べたようにELMのオブジェクトはElmSetクラスから 生成されるElmSetオブジェクトの 中に存在しています。そして実は、ElmSetクラスはElmクラスの サブクラスです。するどい人はこの事実からすぐ予想できる と思いますが、ELMでは仮想空間を階層的に構築し、 計算機のファイルシステムのように木構造を作ることができます。 これには2つの利点があります。1つは、文字どうり階層的な 仮想空間を作成できるということです。仮想的なバーチャル シティを構築する場合を考えてみて下さい。そのバーチャル シティには学校、病院、役所などのいろいろな建物を建てる ことができます。学校を建てるならばその学校の中に図書館、 体育館、音楽室、教室などの部屋を作ることができます。 もう一つの利点は、なにか複雑なオブジェクトを作成する場合に 既存の単純なオブジェクトを組合せて、それを ElmSetオブジェクトでまとめることによって、簡単に作成 できるということです。将来的には十分な量の 基本ELMオブジェクトを提供することによって、 Javaのプログラミングの知識が無い人でもELM上で複雑な オブジェクトを作成できるようにしていきたいと 考えています。
上で述べたように、オブジェクトに能動的な動作をさせるためには、 スレッドのような機能が必要になってきます。しかし、JavaのThread はコストがかかります。つまり、Threadを一つ生成するたびにそれを 維持するために、スタック領域が必要だし、Javaのデフォルトの 動作では、計算機資源からネイティブなスレッドを一つ消費します。 数百、数千のスレッドを生成するのは、非現実的であり下手な プログラミングです。
このような状況を簡単に克服するには、一つのスレッドを 用いて、複数(数百、数千)のオブジェクトのメソッドを順番 に呼び出すようなプログラミングが考えられます。しかし、 この方法はさまざまな状況に対応するために、多くの拡張を 必要とするでしょう。例えば、時間が経過するにつれてオブジェクト の個数が増減する場合や、全てのオブジェクトが常に動作するの ではなく、実際に動作するオブジェクトと休眠状態のオブジェクト が混在しており、個々のオブジェクトが独自に休眠状態から 覚めたり入ったりするような場合です。 もし研究者に十分な時間がなければ、自分の本当に やりたかったことをあきらめて制限されたプログラムを組む ことになりかねません。また、そのようなプログラムを書く プログラマは、それぞれのオブジェクトを自律的に動作 させるための仕組みも独自に考案する必要があるかもしれません。
以上さまざまな問題点を上げて、ELMではそれが克服できると述べてきました が、その克服方法は次節で説明する待ち行列(キュー)を用いたメッセージの処理 によって実現されています。ELMのこの方法は、Swingパッケージのイベント処理 や、Java3Dのオブジェクトの挙動制御やイベントを処理の手法と少し似ています。 これらの手法とELMの違いはELMの待ち行列はオブジェクトごとに用意されている 点です。Java3Dはコンピュータゲームなども作れるように設計されていますが、 コンピュータゲームをやったことのある人ならば、そのゲームの中では様々なキャ ラクタが突然表われて、それぞれに複雑な動きをし、消えゆくと言ったようなこ とが当然のように行なわれていることを知っているでしょう。これはELMの目指 していることと同じです。これらが似たような方法を採用しているのは偶然では ありません。しかし、Java3DやSwingのそれは目的の制限されたものであるし、 ELMの方法のほうがより簡単で拡張性があり理解もしやすいと思います。そして トランザクション機構を実現するための便利な機能も提供しています。ELMを使 いこなすために次節は、しっかり理解して下さい。
ELMシステムは多くのクラスから構成されるJavaのパッケージですが、 最も重要な クラスはElmクラスで、仮想空間内のオブジェクト、ユーザ、 部屋などの全ての クラスのスーパクラスです。Elmクラスは待ち行列 (キュー)を持っており、この中にメッセージを格納することができます。 下の図はElmServer内で活動している複数のElmオブジェクトを 模式的に表しています。
上の図を見て下さい。この図にはELMの仕組みの重要な概念の多くが 示されています。この図の全ての要素について適切な説明ができるよう になれば、ELMの仕組みの基礎を理解できていると言えるでしょう。 一番外側の四角はElmServerを表わしています。 その中に"root(ElmSet)"とラベルのある四角があります。これはrootという 名前のElmSetオブジェクトを表わしています。?節でも説明 したように、このElmSetオブジェクトは中に複数のElmオブジェクトやElmSet オブジェクトを含むことができます。ElmやElmSetを拡張した、エージェント や独自のオブジェクトを含むこともできます。始めてElmServerを単独で 起動した時にはElmServerの中にはrootと名の着いたElmSetオブジェクトが 一つだけ存在する状態で起動します。
この図はデフォルトで用意されるrootのElmSetの中に、 "Object1"、"Object2"、"Object3"を作成した状態を表わしています。 Object1とObject2は通常のElmオブジェクトですが、 Object3はElmSetオブジェクトですので、その中にまた他のElmオブジェクト を作成できます。この図ではObject3の中には"ObjectA"と"ObjectB"があります。 これはELMが仮想環境を階層的に作成できることを図で表現しています。
図の中には灰色の小さな四角がいくつも示されています。これらはメッセー ジです。メッセージはElmオブジェクトやElmSetオブジェクトの中で生成され、 オブジェクト間で交換され、オブジェクトの中で処理され消滅します。各オブジェ クトはELMのグラフィカルなクライアントで見ることができますが、メッ セージはクライアントで見えるものではありません。
メッセージの一部は、横長の四角の中に描かれているものがあります。この 横長の四角が"待ち行列(キュー)"です。これはメッセージを受け取ったオブジェ クトが一時的にメッセージを保存しておく場所です。待ち行列の中にメッセージ が格納されるとElmは待ち行列の先頭から一つメッセージを取り出し、自動的に そのメッセージに対応するメソッドを呼出すようななっています。Elmシステム では、全ての動作がメッセージの送信とそれに対応するメソッドの実行のプロセ スで行われます。
メッセージには、4つの要素が含まれます。それらは、メッセージの送り主、 受け手、メソッド名、引数です。よってメッセージを受け取ったElmオブジェク トは、処理の内容をメッセージの送り主によって変えることができます。また、 引数はObject型なので、メッセージを使ってあらゆる種類のデータを伝達す ることが可能です。
以下に実際にメッセージを送信するためのソースコードの例を挙げます。 メッセージの実体はOrderというクラスを用いて実装されます。
import ac.hiu.j314.elm.*; // method1というメッセージを処理できるElmクラス public class TestElm extends Elm { // 自分自身を呼出すメソッド(無限ループになる) public void method1(Order o) { System.out.println(o.getStringArgAt(0)); System.out.println(o.getDoubleArgAt(1)); System.out.println(o.getIntArgAt(2)); Object args[] = {"arg1",W.p(2.0),W.p(3)}; sendMessage(makeOrder(this,"method1",args)); } }
詳しい説明はサンプルを参照して下さい。
基本的にはメッセージの伝達の仕組みを用いればELMの全ての機能を実現可能 ですが、不便な点があります。一つは他のオブジェクトにメッセージを送り処理 を依頼するだけではなく、処理結果を返事として受け取りたい場合です。もう一 つは多くのオブジェクトが同期を取って動作しなければならない場合です。ELM では、この二つの場合を次のような同じ一つのテクニックで処理します。
まず、今までメッセージと呼んできたものをOrderとRequestの二つに分類し ます。この二つのクラスはどちらもMessageクラスのサブクラスで、機能はまっ たく同じです。しかしELMシステムはRequestにはそれに対応する返事が必ず存在 すると仮定します。一方Orderは返事を返す必要のないメッセージであるとして 処理します。
実際にRequestを送り返事を受け取るためのソースコードの例を下に示します。
private Elm elmObjectB; public void method1(Order o) { Request r = makeRequest(elmObjectB,"cubicContent",W.p(2.0)); prepareForReply(r,"method2",null); sendMessage(r); } public void method2(ReplySet sr) { System.out.println(sr.getReplyAt(0).getDoubleArgAt(0)); }
以下のソースファイルは上のソースファイルから呼出されるメソッドです。
// 立方体の体積を求めるメソッド public void cubicContent(Request r) { double d = r.getDoubleArgAt(0); sendMessage(makeReply(r,W.p(d*d*d))); }
先程、メッセージをOrderとRequestの二種類に分類しました。さらに それぞれにプライベートな目的に使用するメッセージを表わすクラスを 用意してあります。Orderに対してはMyOrder、Requestに対しては MyRequestです。
さらに詳しい説明はサンプルを見て下さい。
ELMはローカルマシンだけで動作させることができますが、ELMサーバをリモー トマシンに立ち上げれば計算機ネットワークを越えて複数のユーザが共有する仮 想空間を構築することが可能です。そして、ELMのサーバ内のデータをクライア ントに伝達するためにモバイルエージェントを用いています。
VESMAのサーバは、三次元の仮想環境を生成・維持し、クライアントから計算 機ネットワークを通して送られてくるモバイルエージェントを受け入れサーバ内 の仮想環境に導き入れます。クライアントは仮想環境内のモバイルエージェントを 操作するリモートコントロールシステムの役割とモバイルエージェントが仮想環 境内で見ている風景をユーザにも見せる働きを持ちます。
モバイルエージェントを用いたことにより、ユーザインタフェースの機能の 拡張が非常に容易になります。ELMにはデフォルトのクライアントとして、テキ ストベースのクライアント、Swingベースのクライアント、Java3Dベースのクラ イアントの3種類のクライアントが用意されていますが、これもモバイルエージェ ントがサーバからクライアントに送り返すデータの種類をコントロールすること によって実現されています。
ELM仮想空間内のオブジェクトは独自のカスタマイザを設定できます。ELMの Swingベースの2次元クライアントも、Java3Dベースの3次元クライアントもその クライアントの画面だけでは多くの情報を表示するのに十分な広さを持っていま せん。また、常に全ての情報を表示しておくと逆に見にくくなります。Swingベー スのクライアントではオブジェクトをダブルクリックすることによりカスタマイ ザを開くことができます。カスタマイザと名前がついていますが、そのカスタマ イザに表示するものは自由です。これはいくつかの必要なメソッドが実装された JComponentクラスのサブクラスで、その中に様々なSwingコンポーネントを使っ て複雑なユーザインタフェースを作成できます。特にカスタマイザを設定しなけ ればデフォルトのカスタマイザが使用されます。
実際のカスタマイザの作成法はこちらのサンプルを見て下さ い。
以上のようなアーキテクチャを使用することにより3つの利点が得られる。こ れは並列プログラミングのテクニックとして常に問題となる事項である。一つ目 はプログラミングの設計上の見通しの改善、二つ目は複数のスレッドによるデー タ整合性の破壊の回避、三つ目はデッドロック問題の発生の軽減である。
ELMの欠点を述べる前に、基本的に並列処理のプログラムを組む という場合に避けることのできない問題点がある。まずは、自分の プログラムしようとしている問題は並列処理が向いているのか、 並列処理する必要があるのかを判断する必要がある。 例えば普通、CPUが1つの計算機では並列アルゴリズムにしても 処理スピードが早くなるわけではない。問題の構造が並列処理に 合わないものは並列処理でプログラミングするのは単に物事を 繁雑にするだけである。
0.データが分散されてしまうために、それらをまとめて 処理したい場合は分散されたデータを集めなければならない 場合がある。 1.並列処理では他のスレッドの処理状態を調べる必要性が あるかもしれず、それは繁雑な処理になる可能性がある。 2.ELMの仕組だけで、デッドロックを完全に避けることは できない。