Mercurial > hg > Papers > 2021 > anatofuz-master
changeset 74:e6e62457048e
...
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 04 Feb 2021 16:33:44 +0900 |
parents | e1842c36937e |
children | d94a41940586 |
files | paper/chapter/03-gears.tex paper/master_paper.pdf |
diffstat | 2 files changed, 52 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/paper/chapter/03-gears.tex Thu Feb 04 15:39:15 2021 +0900 +++ b/paper/chapter/03-gears.tex Thu Feb 04 16:33:44 2021 +0900 @@ -206,19 +206,66 @@ GearsOSのモジュール化の仕組みとしてInterfaceがある。 InterfaceはCodeGearと各CodeGearで使う入出力のDataGearの集合である。 Interfaceに定義されているCodeGearは、各Interfaceが満たすこと期待するAPIである。 -GearsOSに実装されているQueueのInterfaceの定義をソースコード\ref{src:queue}に示す。 -\lstinputlisting[label=src:queue, caption=QueueのInterface]{src/queue.h} Intefaceは仕様(Interface)と、実装(Implement, Impl)を別けて記述する。 Interfaceを呼び出す場合は、Interfaceに定義されたAPIに沿ってプログラミングをすることで、Implの内容を隠蔽することができる。 これによってメタ計算部分で実装を入れ替えつつInterfaceを使用したり、 ふるまいを変更することなく具体的な処理の内容のみを変更することが容易にできる。 これはJavaのInterface、Haskellの型クラスに相当する機能である。 -GearsOSではStackやQueueがInterfaceとして定義済みであり、 SingleLinkedStackなどが実装として提供されている。 -また、WorkerやTaskManagerもInterfaceであり、 コンストラクタを呼び出している箇所を切り替えれば様々な用途に応じたWorkerなどを呼び出すことが可能である。 + +\subsection{Interfaceの定義} +GearsOSに実装されているQueueのInterfaceの定義をソースコード\ref{src:queue}に示す。 +\lstinputlisting[label=src:queue, caption=QueueのInterface]{src/queue.h} +Interfaceの定義は、前半に入出力で利用するDataGearを列挙する。 +ここでは\texttt{queue}と\texttt{data}を利用する。 +4行目からはAPIの宣言である。 +各APIはCodeGearであるので\texttt{\_\_code}で宣言する。 +各CodeGearの第1引数は\texttt{Impl*}型の変数になっている。 +これはInterfaceと対応するImplementのDataGearのポインタである。 +Javaなどのオブジェクト指向言語ではselfやthisのキーワードで参照できるものとほぼ等しい。 +Interface宣言時には具体的にどの型が来るかは不定であるため、 キーワードを利用している。 +ImplはInterfaceのAPI呼び出し時に、メタレベルの処理であるStubCodeGearで自動で入力される。 +その為ユーザーはInterfaceのAPIを呼び出す際は、 このImplに対応する引数は設定しない。 +すなわち実際にいれるべき引数は、 Implを抜いたものになる。 + +第1引数にImplが来ないCodeGearとして\texttt{whenEmpty}と\texttt{next}がQueueの例で存在している。 +これらはAPIの呼び出し時に継続として渡されるCodeGearであるため、 Interfaceの定義時には不定である。 +その為\texttt{...}を用いて、不定なCodeGearとDataGearのClosureが来ると仮定している。 +8行目で定義している\texttt{whenEmpty}はQueueの状態を確認し、空でなければ\texttt{next}、空であれば\texttt{whenEmpty}に継続する。 +これらは呼び出し時にCodeGearを入力して与えることになる。 + +\subsection{Interfaceの呼び出し} +Interfaceで定義したAPIは\texttt{interface->method}の記法で呼びだすことが可能である。 +ソースコード\ref{src:queueTake}では、 Queue Interfaceのtake APIを呼び出している。 +takeは\texttt{\_\_code next}を要求しているので、 CodeGearの名前を引数として渡している。 +これはノーマルレベルではenumの番号として処理される。 +takeは出力を1つ出すCodeGearである為、継続で渡された\texttt{odgCommitCUDAWorker4}はStubでこの出力を受け取る。 +\lstinputlisting[label=src:queueTake, caption=InterfaceのAPIの呼び出し]{src/queueTake.cbc} + +\subsection{Interfaceのメタレベルの実装} +Interface自身もDataGearであり、実際の定義はcontextのunion Data型に記述されている。 +メタレベルではIntefaceのDataGearのGearsOS上の実装である構造体自身にアクセス可能である。 +Queue Interfaceに対応する構造体の定義をソースコード\ref{src:queueStruct}に示す。 +\lstinputlisting[label=src:queueStruct, caption=QueueのInterfaceに対応する構造体]{src/queueStruct.h} + +Interfaceの実装は、この構造体に代入されている値で表現される。 +Interfaceの定義(ソースコード\ref{src:queue})と、 実際の構造体(ソースコード\ref{src:queueStruct})を見比べると、 CodeGearは\texttt{enum Code}として表現し直されている。 +\texttt{enum Code}はGearsOSで使うすべてのCodeGearに割り振られた番号である。 +InterfaceはAPIに対応するenum Codeに、Impl側のenumCodeを代入することで、実装を表現している。 +InterfaceのImpl側のDataGearは、 各Interfaceに存在する、Interface名の最初の一文字が小文字になったunion Data型のポインタ経由で取得可能である。 + +\subsection{InterfaceのImplの実装} +実際にInterfaceの初期化をしている箇所を確認する。 +Queue Interfaceに対応するSingleLinkedQueueの実装を\ref{src:SingleLinkedQueueOld}に示す。 \lstinputlisting[label=src:SingleLinkedQueueOld, caption=SingleLinkedQueueの実装]{src/SingleLinkedQueueOld.cbc} -Interface自身もDataGearであり、実際の定義はcontextのunion Data型に記述されている。 +\texttt{createSingleLinkedQueue}はSingleLinkedQueueで実装したQueue Interfaceのコンストラクタである。 +これは関数呼び出しで実装されており、 返り値はInterfaceのポインタである。 +コンストラクタ内ではQueueおよびSingleLinkedQueueのアロケーションを行っている。 +\texttt{new}演算子が使われているが、 これはGearsOSで拡張されたシンタックスの1つである。 +newはGearsOSのビルド時にPerlスクリプトによって、contextが持つDataGearのヒープ領域の操作のマクロに切り替わる。 +ノーマルレベルではcontextにアクセスできないので、 Javaの様なアロケーションのシンタックスを導入している。 + Interfaceで定義したCodeGearの出力は必ずDataGearでなければならない。 OutputDataGear自体はInteface自身のDataGearにメタレベルで書き込まれる。