07.2複数の非同期事象をFIFOで処理する(EVENTS)-1
非同期事象(「いつ来るかわからない」「いつ終わるかわからない」と言った事象)の待ち合わせを行うAPIとして基礎編では WAIT マクロを解説しました。1つ、あるいは数個のイベントを待ち合わせる場合はWAITマクロが利用できます。
しかしWAITマクロで複数のイベントを待ち合わせる場合、どのECBに対応したイベントが最初に終了したかはわかりません。ECBLISTにはイベントが完了したことを示すPOSTビットは立ちますが、複数のイベントが完了していても、イベントが完了した(POSTされた)順番はわかりません。そのためオンライン・システムのTPモニターやTCP/IPによるサービスを提供するサーバープログラムなど、接続された端末やクライアントのデータ受信などに対応してECBを用意しデータ受信が完了した順にトランザクション・サービスを提供するようなプログラムなどでは、受信データが到着した順番がわからないので正確なFIFOでの処理ができません。
マルチイベントの待ち合わせ処理では、イベントに優先度がある場合を除けば事象が完了した順に対応した処理を行うのが一般的です。先着順にFIFOで処理をすることで均一のサービスを提供できます。しかしWAITマクロのECBLISTではどのイベントが完了したかはわかりますがその順番はわかりません。たいていはECBLISTの先頭から完了したECBを探したりしますので、複数の端末やクライアントからデータ受信が集中しても、実際の先着順ではなくECBLISTの順番で処理することになったりします。そこで前回POSTビットの立っていたECBの次のECBから探索を行う、などの工夫が考えられます。それでも不公平さ(LISTの先頭にいるほど見つけてもらいやすい)が少しは解消されますがFIFOになるわけではありません。
WAITマクロの代わりにEVENTSマクロを使うと、事象の完了した順番でECBを通知してもらえるので、オンラインやサーバーなどのプログラムでは、トランザクションが到着した順に処理をして、公平なサービスを提供することが容易になります。使用するECBの数が処理に応じて増減するような場合もEVENTSマクロは向いています。
また待ち合わせの対象となるECBが多い場合(数個ではなく数十、数百)、EVENTSマクロの方が少ないオーバーヘッドで処理されます。VOS3のマニュアルではEVENTSマクロを”高速多重ウェイト機能”と解説しています。
EVENTSテーブルの作成(初期設定処理)
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- EVENTS ENTRIES=1000 INITIALIZE EVENTS TABLE ST R1,AEVTAB SAVE EVENTS TABLE ADDRESS : : AEVTAB DC A(0) POINTER TO EVENTS TABLE
まず最初にEVENTSテーブルを作成します。ENTRIESパラメーターで、このタスクがある一時点で同時に使用するECBの数を指定します。EVENTSマクロで処理できるECB数は最大32767個です。EVENTSテーブルの作成はタスクが開始して最初のECBを使い始めるまでに1回だけ行います。
ECBの初期化(ECBの登録)
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- EVENTS TABLE=AEVTAB, ADD ECB1 TO EVENTS TABLE + ECB=AECB1 ←ECBを直接指定するのではなく、 ECBアドレスの格納フィールドを指定する LA R0,WKUPECB LOAD ECB ADDRESS EVENTS TABLE=AEVTAB, ADD IT TO EVENTS TABLE + ECB=(0) STIMER REAL,TIMREXIT, SET TIMER + BINTVL=INTERVAL WKUPECB WILL BE POSTED BY + TIMREXIT WHEN TIMER EXPIRED. : : : AECB1 DC A(ECB1) POINTER TO ECB1 ECB1 DC F'0' ECB1 FIELD WKUPECB DC F'0' ECB FOR WAKE-UP MAINLINE
ECBを使用する非同期イベントの実行に合わせてECBを初期化します。ECBの初期化とはECBをEVENTSマクロで待ち合わせに使えるようにすることで、ECBのWAITビットをONにし、下位3バイトにEVENTSテーブルのアドレスを設定します(実際には+1した奇数アドレス)。
初期化されたECBの内容 0 1 2 31 +---+---+--------------------//-------------------+ | 1 | 0 | EVENTSテーブルのアドレス+1 | +---+---+--------------------//-------------------+
一度初期化したECBの内容は誤って書き換えないようにします。WAITのつもりでMVI命令でECBの先頭バイトをクリアーする、などを安易に行ってはなりません。すでにPOST済みのECBを指定してもかまいません。EVENTSマクロ(ECB初期化)を発行する前にすでにPOST済みかどうかをチェックする必要はありません。ECBの初期化は、非同期イベントの開始前にECBのWAITビットおよびPOSTビットをクリアーすることに相当します。
完了事象の待ち合わせ
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- EVENTS TABLE=AEVTAB, WAIT FOR NEXT COMPLETION EVENT + WAIT=YES L R2,0(,R1) LOAD COMPLETION EVENT ECB : : 初期化済みのECBがPOSTされると、そのECBアドレスが : EVENTSテーブルに登録される。POST順に登録されるので : 事象が完了した順にECBを知ることができる。 : ECBにはEVENTSテーブルのアドレスが設定されているから : WAIT=YES指定のEVENTSマクロの発行とは無関係にPOSTされ : たタイミングでテーブルに登録される。 : すでにPOST済みのECBであれば、ECBの初期化時に同時に : テーブルにも登録される。 : :
実際にECBへのPOSTを待ち合わせるには、WAIT=YES指定のEVENTSマクロを発行します。初期化済み(登録済み)のECBのうち、どれか1つでも完了すればWAITが解け制御が戻ってきます。すでにPOST済みのECBがあれば直ちに制御は戻されます。この点はWAITマクロと同じです。複数のECBがある場合、先着順に通知されます。
GR1には最初に完了したECBのアドレスが格納されたフィールドのアドレスが入っています。ECBそのもののアドレスではありません。続けてWAIT=YES指定のEVENTSマクロを発行すると次に完了したECBが通知されます。
一度完了したECBは、WAITマクロと異なりそのままでは次のEVENTSマクロでは通知されません。同じECBで再度非同期事象を待ち合わせる場合は、再度適当なタイミングでECBの初期化を行う必要があります。この点がWAITマクロと異なります。
EVENTSテーブルの削除
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- EVENTS ENTRIES=DEL, DELETE EVENTS TABLE + TABLE=AEVTAB : : AEVTAB DC A(0) POINTER TO EVENTS TABLE
作成したEVENTSテーブルは使い終わったら削除しなければなりません。タスクを終了する前に行えばいいでしょう。
EVENTSマクロではWAITマクロよりやらねばならない手続きが増えます。しかしEVENTSテーブルの作成と削除はタスクの開始時と終了時に行えばいいので、実際にプログラム内で都度都度必要なのはECBの初期化です。WAITマクロでもECB内のWAIT/POSTビットのクリアーはプログラム自身で行うことになりますから、その代わりにECB指定のEVENTSマクロを発行する、と考えればいいでしょう。WAITに比べると一見面倒そうですが、一回書いてしまえばどうということはありません。
POSTする側の処理は、待っている側がWAITを使おうがEVENTSを使おうが違いを意識する必要はありません。