• 検索結果がありません。

COP ライブラリ

ドキュメント内 九州大学学術情報リポジトリ (ページ 50-58)

第 3 章 RTCOP: C++ ベースのコンテキスト指向プ ログラミングフレームワークログラミングフレームワーク

3.4 実装

3.4.2 COP ライブラリ

COP

ライブラリの主な役割として,メソッドディスパッチの拡張とレイ ヤアクティベーション機構の提供がある.また,オプションとしてレイヤ固 有メンバ変数やレイヤアクティベーションイベントハンドラの機能を扱う.

これらの機能を実現するために,レイヤによって振る舞いを変わる可能性の あるクラスをインスタンス化する際の工夫がある.本論文では,このような クラスのことをレイヤードなクラスと呼ぶ.

これらの実現方法について述べるために,レイヤードなクラスのインスタ ンス化の仕組み,メンバ変数の扱い,メソッドディスパッチの仕組み,レイ ヤアクティベーションの仕組みについて述べる.また,提案フレームワーク は

C++

を用いたネイティブな実装であるため,ターゲットとなるコンパイ ラや

OS

などに依存する実装部分が存在する.これについても本項の最後に 述べる.

3

RTCOP: C++

ベースのコンテキスト指向プログラミングフレーム

ワーク

40

䝺䜲䝲グ㏙䛛䜙⮬ື

⏕ᡂ䛥䜜䜛䜽䝷䝇

㻴㼑㼘㼘㼛 Ͳ ͙

нWƌŝŶƚ;Ϳ

㻨㻨㻌㼠㼑㼙㼜㼘㼍㼠㼑㻨㼀㻩㻴㼑㼘㼘㼛㻪㻌㻪㻪 㻸㼍㼥㼑㼞㼐㻻㼎㼖㼑㼏㼠 Ͳ ͙

н䝺䜲䝲䞊䝗䛺䜽䝷䝇䛾䛯䜑䛾 䝕䝇䝖䝷䜽䝍;Ϳ

㻶㼍㼜㼍㼚㼑㼟㼑㻴㼑㼘㼘㼛

Ͳఱ䜒↓䛧

нWƌŝŶƚ;Ϳ нKŶĐƚŝǀĂƚŝŶŐ;Ϳ н&ŝŶĂůŝnjĞ;Ϳ 㻶㼍㼜㼍㼚㼑㼟㼑㻴㼑㼘㼘㼛䛾

䝯䞁䝞ኚᩘ⩌

Ͳ ͺŽƵŶƚ

䝟䞊䝅䝱䝹䜽䝷䝇䛾 䝯䞁䝞ኚᩘ⩌

Ͳ WƌŽĐĞĞĚᐇ⌧䛾䛯䜑䛾 ௬᝿㛵ᩘ䝔䞊䝤䝹䜈䛾ཧ↷

Ͳ䜲䝧䞁䝖䝝䞁䝗䝷䛾䜰䝗䝺䝇

ϭ Ύ

䝴䞊䝄グ㏙䛾䝧䞊䝇䜽䝷䝇 ᐇ㝿䜲䞁䝇䝍䞁䝇

໬䛥䜜䜛䜽䝷䝇 䝧䞊䝇䜽䝷䝇䛻

ྛ✀せ⣲䜢㏣ຍ

䝃䝤䜽䝷䝇䛺䛾䛷䝯䞁䝞 ኚᩘ䜈䛾䜰䜽䝉䝇䛜ྍ⬟

͙

͙

䛣䛾䜽䝷䝇䛿

䜲䞁䝇䝍䞁䝇໬䛥䜜䛺䛔

3.3 レイヤードなクラスの構造

レイヤードなクラスのインスタンス化の仕組み

提案フレームワークにおいて,レイヤードなクラスのインスタンス化で は,ベースクラスの代わりに,

COP

実現のための変数やメソッドを追加し たテンプレートクラスのインスタンス化を行っている.このように,実際に インスタンス化するクラスを違うものに置き換える方法は,

LOOM.NET

の ようなベース言語のメタレベル機能を用いる言語で良く使われている.代わ りのクラスをどのように実現するかの選択肢はベース言語により異なる.提 案フレームワークでは,

C++

においてテンプレートがメタプログラミング のために用いられやすいため採用することとした.

レイヤードなクラスの構造を図

3.3

のクラス図に示す.レイヤードなクラ スは図中の

LayerdObject

テンプレートクラスで実現している.このクラス はベースクラスの

Hello

を型パラメータとして受け取り,さらに継承するこ とで,COP実現のために必要なメンバ変数やメソッドを追加している.レ イヤードなクラスの実現をベースクラスの継承によって行うことで,ベー

3

RTCOP: C++

ベースのコンテキスト指向プログラミングフレーム

ワーク

41

㻮㼍㼟㼑㻴㼑㼘㼘㼛 Ͳ ͙

нWƌŝŶƚ;Ϳ

㻿㼡㼎㻴㼑㼘㼘㼛 Ͳ ͙

нWƌŝŶƚ;Ϳ 㻸㼍㼥㼑㼞㼐㻻㼎㼖㼑㼏㼠 Ͳ ͙

н͙

㻸㼍㼥㼑㼞㼐㻻㼎㼖㼑㼏㼠 Ͳ ͙

н͙

ྠ䛨䜒䛾

஧䛴⥅ᢎ 䛹䛱䜙䜒

KW䛷

᣺䜛⯙䛔 ኚ᭦䛥䜜 䛖䜛

㻮㼍㼟㼑㻴㼑㼘㼘㼛 Ͳ ͙

нWƌŝŶƚ;Ϳ

㻿㼡㼎㻴㼑㼘㼘㼛 Ͳ ͙ нWƌŝŶƚ;Ϳ

㻮㼍㼟㼑㻴㼑㼘㼘㼛䛾 㻸㼍㼥㼑㼞㼐㻻㼎㼖㼑㼏㼠 Ͳ ͙

н͙

㻿㼡㼎㻴㼑㼘㼘㼛䛾 㻸㼍㼥㼑㼞㼐㻻㼎㼖㼑㼏㼠 Ͳ ͙

н͙

ᣑᙇෆᐜ 䛜⿕䜙䛺䛔

;ĂͿ>ĂLJĞƌĚKďũĞĐƚ䜽䝷䝇䜢⥅ᢎ䛩䜛ᙧ䠄୙᥇⏝䠅 ;ďͿ䝧䞊䝇䜽䝷䝇䜢

>ĂLJĞƌĚKďũĞĐƚ䛷⥅ᢎ䛩䜛ᙧ䠄᥇⏝䠅 3.4 LayerdObjectの継承ツリーの案

スクラスの元々の継承関係を壊すことなく機能追加を行っている.図

3.4

(a)

のようにベースクラスから

LayerdObject

を継承すると多重継承となり,

問題である.

JapaneseHello

は,パーシャルクラスの振る舞いを実装するた めに,レイヤ記述から自動生成されるクラスである.パーシャルメソッドを 実装することのみが目的であり,このクラスのインスタンスが作られること はない.

3.4

(b)

において,SubHelloの

LayerdObject

から

BaseHello

Lay-erdObject

をスーパークラスのメソッド呼び出しにより実行した場合,

LayerdObject

メンバのアドレスが

SubHello

のサイズ分だけずれる.このよ うな問題を解決するため,

LayerdObject

のメンバへのアクセスは,継承元 のクラスサイズからアドレスを求めることで行う.

メンバ変数の扱い

レイヤ記述において定義されたレイヤ固有のメンバ変数は,図

3.3

のよう にパーシャルクラスのメンバ変数を管理するためのクラスに持たせる.この 理由は,

JapaneseHello

に直接変数を追加すると,

LayerdObject

クラスのイ ンスタンスの有効範囲外のアドレスにアクセスする必要があるためである.

このクラスはレイヤードなクラスで持つべき共通の要素を扱うためのクラス を継承している.

パーシャルクラスのメンバ変数群クラスの内容は,表

3.1

の各種機能の有

3

RTCOP: C++

ベースのコンテキスト指向プログラミングフレーム

ワーク

42

㻨㻨㻌㼠㼑㼙㼜㼘㼍㼠㼑㻨㼀㻩㻴㼑㼘㼘㼛㻪㻌㻪㻪 㻸㼍㼥㼑㼞㼐㻻㼎㼖㼑㼏㼠 Ͳ௬᝿㛵ᩘ䝔䞊䝤䝹䛾䝫䜲䞁䝍

΂WƌŝŶƚ䝯䝋䝑䝗䛾䝫䜲䞁䝍΃

Ͳ ͙ нWƌŝŶƚ;Ϳ

௬᝿㛵ᩘ䝔䞊䝤䝹䛾⟶⌮

Ͳ䝺䜲䝲䞊䝗䛺䜽䝷䝇䛾䛯䜑䛾 ௬᝿㛵ᩘ䝔䞊䝤䝹⩌

΂,ĞůůŽ䛾௬᝿㛵ᩘ䝔䞊䝤䝹΂WƌŝŶƚ΃͕͙΃

н௬᝿㛵ᩘ䝔䞊䝤䝹䛾᭩䛝᥮䛘;㛵ᩘ䝫䜲䞁䝍Ϳ нн䛷௬᝿㛵ᩘ䛜䛒䜛䜽䝷䝇䛻

⮬ື䛷ᬯ㯲ⓗ䛻స䜙䜜䜛

,ĞůůŽ䜽䝷䝇䛿ඖ䛾௬᝿

㛵ᩘ䝔䞊䝤䝹䛷䛿䛺䛟䚸 ZdKW䛷⟶⌮䛩䜛௬᝿

㛵ᩘ䝔䞊䝤䝹䜢ཧ↷

䝺䜲䝲䜰䜽䝔䜱䝧䞊䝍 Ͳ ͙

н䜰䜽䝔䜱䝧䞊䝖;䝺䜲䝲Ϳ

௬᝿㛵ᩘ䝔䞊䝤䝹 䛾᭩䛝᥮䛘 㻯㻗㻗䜸䝸䝆䝘䝹䛾

௬᝿㛵ᩘ䝔䞊䝤䝹 Ͳ䝧䞊䝇䝺䜲䝲䛾௬᝿㛵ᩘ䝔䞊䝤䝹⩌

΂,ĞůůŽ䛾௬᝿㛵ᩘ䝔䞊䝤䝹΂WƌŝŶƚ΃͕͙΃

Ͳ䝺䜲䝲ɲ䛾௬᝿㛵ᩘ䝔䞊䝤䝹⩌΂͙΃

н௬᝿㛵ᩘ䝔䞊䝤䝹䛾᭩䛝᥮䛘;㛵ᩘ䝫䜲䞁䝍Ϳ

䜸䝸䝆䝘䝹䛾௬᝿㛵ᩘ䝔䞊䝤䝹䛾䝁䝢䞊 ཧ↷

3.5 メソッドディスパッチのための機構

効・無効で変わる.例えば,

proceed

が必要ない場合,そのために必要なメ ンバを含めないようにする.また,レイヤ固有のメンバ変数が必要ない場合 は,パーシャルクラス固有のメンバ変数群クラスを定義しない.

メソッドディスパッチの仕組み

3.5

にメソッドディスパッチのための機構を示す.

3.3.1

項で述べた通 り,メソッドディスパッチは仮想関数テーブルを書き換えることにより実現 する.

C++

など多くの

OOP

言語では,ポリモーフィズムを実現するため の手段として,インスタンスごとに仮想関数テーブルを持っており,メソッ ドディスパッチの際にテーブルから対応するメソッドのアドレスを取得する ことで,切り替えを行っている.提案フレームワークでは,

copnew

による インスタンス化の際に,仮想関数テーブルのポインタの参照先を提案フレー ムワークが管理する仮想関数テーブルのアドレスに変更する.提案フレーム ワークの持つ仮想関数テーブルは,C++オリジナルの仮想関数テーブルを コピーしたものである.この専用の仮想関数テーブルをアクティベーショ ンの際に書き換えることで,実行するメソッドの切り替えを実現している.

copnew

の手順としては,初めに

C++

new

でインスタンス化を行い,そ

の後に生成したインスタンスの仮想関数テーブルの先頭を指すポインタを変 更する.

3

RTCOP: C++

ベースのコンテキスト指向プログラミングフレーム

ワーク

43

オリジナルをコピーした仮想関数テーブルを用いる理由は,直接オリジナ ルの仮想関数テーブルを書き換えることによって中身を破壊しないためであ る.COPシステムでは,実行中のレイヤアクティベーション・ディアクティ ベーションによって,ディスパッチするメソッドが動的に変化するため,オ リジナルの仮想関数テーブルは元の状態のまま保持する必要がある.

提案フレームワークでは,上記の仮想関数テーブルのほかに,レイヤごと

proceed

を実現するための仮想関数テーブルが別にある.これらの仮想

関数テーブルも

C++

オリジナルの仮想関数テーブルをコピーしたものであ る.この仮想関数テーブルは

proceed

実行時に参照され,テーブル中のアド レスで示されるメソッドを実行する.

レイヤアクティベーションの仕組み

3.3.1

項で述べた通り,レイヤアクティベーションは決定的なアクティベー

ションを採用している.そのため,アクティベーション命令が発行された時 点で,仮想関数テーブルの書き換えが全体に及ぼされる.本項では,レイヤ アクティベーション時の仮想関数テーブル書き換えの実装方法を示す.この 方法は

C++

以外でも実現可能である.

COP

実現のための全体の仮想関数テーブルと,

proceed

のためのレイヤ ごとの仮想関数テーブルの書き換えのルールを明らかにするために,図

3.6

にアクティベーション前後の上記仮想関数テーブルを示す.図の例では,

L1

というレイヤがすでにアクティブであり,

L2

というレイヤを新たにアク ティベートした際の仮想関数テーブルの変化を表している.各仮想関数テー ブルは,メソッド

M1

M2

のアドレスを持っており,アクティベート順序と パーシャルメソッドの有無に基づいて変化する.

これらのレイヤは

Layer

クラスとして,アクティベート順に基づきリス ト構造で連結される.L2 のアクティベーション時に,前の

Layer

クラスを 辿っていき,

proceed

用の仮想関数テーブルや,全体の仮想関数テーブルの 書き換えを行う.全体の仮想関数テーブルは,一番初めに実行されるメソッ ドのアドレスを保持する.パーシャルメソッド中で

proceed

命令が実行さ れた場合は,

Layer

クラスの

proceed

用仮想関数テーブルを見ながら,次の

ドキュメント内 九州大学学術情報リポジトリ (ページ 50-58)