第 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
のアドレスを持っており,アクティベート順序と パーシャルメソッドの有無に基づいて変化する.これらのレイヤは