非同期事象(「いつ来るかわからない」「いつ終わるかわからない」といった事象)の待ち合わせを行う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マクロの方が少ないオーバーヘッドで処理されます。
EVENTSテーブルの作成(初期設定処理)
1 2 3 4 5 6 |
----+----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 8 9 10 11 12 13 14 15 16 17 |
----+----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した奇数アドレス)。
1 2 3 4 |
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 |
----+----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を待ち合わせるには、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 |
----+----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を使おうが違いを意識する必要はありません。