Mercurial > hg > Papers > 2021 > anatofuz-master
changeset 73:e1842c36937e
...
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 04 Feb 2021 15:39:15 +0900 |
parents | 951cb9681030 |
children | e6e62457048e |
files | paper/chapter/03-gears.tex paper/master_paper.pdf paper/src/SingleLinkedQueueOld.cbc paper/src/queue.h |
diffstat | 4 files changed, 79 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/paper/chapter/03-gears.tex Thu Feb 04 14:54:44 2021 +0900 +++ b/paper/chapter/03-gears.tex Thu Feb 04 15:39:15 2021 +0900 @@ -148,10 +148,25 @@ \section{TaskManager} +TaskManagerはGearsOS上で実行されるTaskの管理を行う。 +GearsOS上のTaskとはContextのことであり、 各Contextには自分の計算に必要なDataGearのカウンタなどが含まれている。 +TaskManagerは、CodeGearの計算に必要な入力のDataGear(InputDataGear)が揃っているかの確認、揃っていなかったら待ち合わせを行う処理がある。 +すべてのDataGearが揃った場合、 TaskをWorkerのQueueに通知しTaskを実行させる。 +この処理はGearsOSを並列実行させる場合に必要な機能となっている。 + TaskManagerは性質上シングルトンである。 その為、複数Workerを走らせた場合でも1全体で1つのみの値を持っていたいものはTaskManagerが握っている必要がある。 例えばモデル検査用の状態保存用のデータベース情報は、 TaskManagerが所有している。 +\section{TaskQueue} +GearsOSのTaskQueueはSynchronizedQueueで表現されている。 +TaskQueueはWorkerが利用するQueueとなっている。 + +WorkerのQueueは、TaskManagerに接続してTaskを送信するスレッドと、 Taskを実行するWorker自身のスレッドで扱われる。 +さらにWorkerが複数走る可能性もある。 +その為SynchronizedQueueは、マルチスレッドでもデータの一貫性を保証する必要がある。 +GearsOSではCAS(Check and Set, Compare and Swap)を利用して実装が行われている。 + \section{Worker} WorkerはWorkerの初期化にスレッドを作る。 GearsOSではスレッドごとにそれぞれContextが生成される。 @@ -186,6 +201,29 @@ Contextから取り出してきたunion DataからDataGearの型への変換はメタ計算で行われる。 GearsOSの場合は、計算したいCodeGearの直前で実行されるStubCodeGearで値のキャストが行われる。 + +\section{Interface} +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などを呼び出すことが可能である。 + +\lstinputlisting[label=src:SingleLinkedQueueOld, caption=SingleLinkedQueueの実装]{src/SingleLinkedQueueOld.cbc} + +Interface自身もDataGearであり、実際の定義はcontextのunion Data型に記述されている。 + +Interfaceで定義したCodeGearの出力は必ずDataGearでなければならない。 +OutputDataGear自体はInteface自身のDataGearにメタレベルで書き込まれる。 + + \section{GearsOSのビルドシステム} GearsOSではビルドツールにCMakeを利用している。 ビルドフローを図\ref{fig:gearsbuild1}に示す。
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/src/SingleLinkedQueueOld.cbc Thu Feb 04 15:39:15 2021 +0900 @@ -0,0 +1,31 @@ +#include "../context.h" +#include <stdio.h> +#interface "Queue.h" + +Queue* createSingleLinkedQueue(struct Context* context) { + struct Queue* queue = new Queue(); + struct SingleLinkedQueue* singleLinkedQueue = new SingleLinkedQueue(); + queue->queue = (union Data*)singleLinkedQueue; + singleLinkedQueue->top = new Element(); + singleLinkedQueue->last = singleLinkedQueue->top; + queue->take = C_takeSingleLinkedQueue; + queue->put = C_putSingleLinkedQueue; + queue->isEmpty = C_isEmptySingleLinkedQueue; + queue->clear = C_clearSingleLinkedQueue; + return queue; +} + +__code clearSingleLinkedQueue(struct SingleLinkedQueue* queue, __code next(...)) { + queue->top = NULL; + goto next(...); +} + +__code putSingleLinkedQueue(struct SingleLinkedQueue* queue, union Data* data, __code next(...)) { + Element* element = new Element(); + element->data = data; + element->next = NULL; + queue->last->next = element; + queue->last = element; + goto next(...); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/paper/src/queue.h Thu Feb 04 15:39:15 2021 +0900 @@ -0,0 +1,10 @@ +typedef struct Queue<Impl>{ + union Data* queue; + union Data* data; + __code whenEmpty(...); + __code clear(Impl* queue, __code next(...)); + __code put(Impl* queue, union Data* data, __code next(...)); + __code take(Impl* queue, __code next(union Data*, ...)); + __code isEmpty(Impl* queue, __code next(...), __code whenEmpty(...)); + __code next(...); +} Queue;