CLab_??-????????
第9章  活動化グループ
RPGプログラマーの為のC言語講座

活動化グループを使用すると、同一JOB内に複数のプログラム実行環境を作成することができます。

RPGを呼び出した場合に、SETON LRをせずにRETURNすると、プログラムはそのまま常駐します。
何度も同じRPGを呼び出す場合に、意識的にLRを立てずにRETURNすることで、呼び出しに掛かる オーバーヘッドを策なくするテクニックは割と一般的に使用されてきたのではないでしょうか。

SETON LR しないで RETRUN するプログラム ACT1R

     H            Y/                                    1
     H*------------------------------------------------------------*
     H* PROGRAM-ID    :    ACT1R                                   *
     H* REMARKS       :    SETON LRしないプログラム                *
     H* AUTHOR        :    Y.IDE                                   *
     H* DATE-WRITEN   :    98/08/31                                *
     H* VERSION       :    01.00 ORIGINAL                          *
     H*------------------------------------------------------------*
     FACT1FM  CF  E                    WORKSTN
     FCLAB2P  IF  E                    DISK
     C*
     C           CNT       ADD  1         CNT     70
     C                     READ CLAB2P                   99
     C                     EXFMTSC01
     C                     RETRN
     C*

画面ファイル ACT1FM

     A                                      DSPSIZ(24 80 *DS3)
     A          R SC01
     A                                  3  2'COUNT :'
     A            CNT            7Y 0B  3 10

CALL ACT1R を実行してください。

もう一度、CALL ACT1R を実行してください。

カウントアップして行きます。これは、LRを立てずにRETURNした為、PGMが常駐しており
前回呼び出したPGMの内容(FILEのオープン,変数の値)がそのまま残っているからです 外部PGMがコールされると、初期設定ルーチンのなかで、ファイルオープン、変数の初期化などが行われ、 PGMスタックに登録されます。 PGMの終了時には、ファイルのクローズ,メモリーの開放など一連の終了処理が行われてプログラムスタック から除去されます。

ILEでは、PGMをモジュールに細かく分けて、1つのプログラムとしてバインドする方法が 採用されました。

そのため、外部プログラムの呼び出し時に掛かるオーバーヘッドを極力少なくするような工夫が 必要になりました。その中で登場したのが、活動化グループです。

活動化グループ単位で、PGMの実行環境を制御するので、活動化グループの中でPGMを活動化し 実行が終わっても活動化グループが存在する間は、PGMの状態が保持されます。

活動化グループを削除することで、活動化されたプログラムが占有しているメモリーなどを開放します

従来の環境と互換をとるため、*DFTACTGRPがあり、ILE以外のPGMはこの活動化 グループに属します。

ILEのPGMは、その作成時にactgrp *NEW/*CALLERを選択します *NEWは、実行時に新たにアクセスグループを作成し、実行が完了したら、そのアクセスグループを 削除します。

*CALLERは、呼び出し元のPGMと同じアクセスグループで活動します

この他に、ユーザーで固有の名前をつけてアクセスグループを作成することも可能です

1JOBでアクセスグループを複数保つことの利点は、何度も呼びたされるPGMが、呼び出された時の オーバーヘッドを減らせることです。

下記のCのコードを使用して、いくつかのパターンを検証してみましょう。

以下のコードをすべて、CRTCMODでモジュールとして作成してください

CRTCMOD ACT1C

/*--------------------------------------------------------------*/
/* PROGRAM-ID  : ACT1C                  */  
/* REMARKS     :活動化グループ 単体テスト
/* AUTHOR      : Y.Ide                  */
/* DATE-WRITEN : 98/08/31               */
/* VERSION     : 01.00 ORIGINAL         */
/*--------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <decimal.h>
#include <xxcvt.h>

#pragma mapinc("REC","CLAB/CLAB2P(CLAB2R)","both","d z")
#include "REC"

#pragma mapinc("SC01","CLAB/ACT1FM(*ALL)","both"," ")
#include "SC01"

int main(void)
{
  _RFILE                            *fp0;
  _RFILE                            *dspf;
  _RIOFB_T                          *fb; /*オープンフィードバック*/
  CLAB_CLAB2P_CLAB2R_both_t         rec;
  CLAB_ACT1FM_SC01_both_t           sc01;
  int cnt;

    if (( fp0 = _Ropen("CLAB2P", "ar" )) == NULL )
    {
        printf ( "OPEN ERROR\n" );
        exit ( 1 );
    }

    if (( dspf = _Ropen("ACT1FM", "ar+" )) == NULL )
    {
        printf ("OPEN ERROR\n" );
        exit ( 1 );
    }
/*カウントアップと設定*/
    cnt = cnt + 1;   /* 通常では++cntかcnt++と書きます */
    QXXITOZ(sc01.CNT, 7, 0, cnt);

/*レコード様式を設定する*/
    _Rformat(dspf,"SC01" );

/* EXFMTに同じ*/
    fb = _Rwriterd(dspf, &sc01, sizeof(sc01) );

  _Rclose (fp0);
  _Rclose (dspf);

}

/*--------------------------------------------------------------*/
/* PROGRAM-ID  : ACT3C                                          */
/* REMARKS     :活動化グループ バインド・テスト
/* AUTHOR      : Y.Ide                                          */
/* DATE-WRITEN : 98/08/31                                       */
/* VERSION     : 01.00 ORIGINAL                                 */
/*--------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <decimal.h>
#include <xxcvt.h>

int dspio1(void);
int dspio2(void);

int main(void)
{
int rc;
rc = dspio1();
rc = dspio2();
}

/*--------------------------------------------------------------*/
/* PROGRAM-ID  : ACT3SRV                                        */
/* REMARKS     :活動化グループ サービスプログラムその1
/* AUTHOR      : Y.Ide                                          */
/* DATE-WRITEN : 98/08/31                                       */
/* VERSION     : 01.00 ORIGINAL                                 */
/*--------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <decimal.h>
#include <xxcvt.h>

#pragma mapinc("REC","CLAB/CLAB2P(CLAB2R)","both","d z") #include "REC" #pragma mapinc("SC01","CLAB/ACT1FM(*ALL)","both"," ") #include "SC01" int dspio1(void) { _RFILE *fp0; _RFILE *dspf; _RIOFB_T *fb; /*オープンフィードバック*/ CLAB_CLAB2P_CLAB2R_both_t rec; CLAB_ACT1FM_SC01_both_t sc01; int cnt; if (( fp0 = _Ropen("CLAB2P", "ar" )) == NULL ) { printf ( "OPEN ERROR\n" ); exit ( 1 ); } if (( dspf = _Ropen("ACT1FM", "ar+" )) == NULL ) { printf ("OPEN ERROR\n" ); exit ( 1 ); } /*カウントアップと設定*/ cnt = cnt + 1; /* 通常では++cnt,cnt++と書きます*/ QXXITOZ(sc01.CNT, 7, 0, cnt); /*レコード様式を設定する*/ _Rformat(dspf,"SC01" ); /* EXFMTに同じ*/ fb = _Rwriterd(dspf, &sc01, sizeof(sc01) ); _Rclose (fp0); _Rclose (dspf); }

CRTCMOD ACT4SRV

/*--------------------------------------------------------------*/
/* PROGRAM-ID  : ACT4SRV                                        */
/* REMARKS     :活動化グループ サービスプログラムその2
/* AUTHOR      : Y.Ide                                          */
/* DATE-WRITEN : 98/08/31                                       */
/* VERSION     : 01.00 ORIGINAL                                 */
/*--------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <recio.h>
#include <decimal.h>
#include <xxcvt.h>

#pragma mapinc("REC","CLAB/CLAB2P(CLAB2R)","both","d z")
#include "REC"

#pragma mapinc("SC01","CLAB/ACT1FM(*ALL)","both"," ")
#include "SC01"

int dspio2(void)
{
  _RFILE                            *fp0;
  _RFILE                            *dspf;
  _RIOFB_T                          *fb; /*オープンフィードバック*/
  CLAB_CLAB2P_CLAB2R_both_t         rec;
  CLAB_ACT1FM_SC01_both_t           sc01;
  int cnt;

    if (( fp0 = _Ropen("CLAB2P", "ar" )) == NULL )
    {
        printf ( "OPEN ERROR\n" );
        exit ( 1 );
    }

    if (( dspf = _Ropen("ACT1FM", "ar+" )) == NULL )
    {
        printf ("OPEN ERROR\n" );
        exit ( 1 );
    }
/*カウントアップと設定*/
    cnt = cnt + 1;   /* 通常では++cnt,cnt++と書きます*/
    QXXITOZ(sc01.CNT, 7, 0, cnt);

/*レコード様式を設定する*/
    _Rformat(dspf,"SC01" );

/* EXFMTに同じ*/
    fb = _Rwriterd(dspf, &sc01, sizeof(sc01) );

  _Rclose (fp0);
  _Rclose (dspf);
}

  • ACT1Cモジュールより作成
      1. CRTPGM ACT1CA ACT1C *CALLER
      2. CRTPGM ACT1CB ACT1C *NEW
      3. CRTPGM ACT1CC ACT1C ACT1GRP
  • ACT3SRVモジュールより作成
      1. CRTSRVPGM ACT3SRVA ACT3SRV *CALLER
      2. CRTSRVPGM ACT3SRVB ACT3SRV *NEW
      3. CRTSRVPGM ACT3SRVC ACT3SRV ACT3GRP
  • ACT4SRVモジュールより作成
      1. CRTSRVPGM ACT4SRVA ACT4SRV *CALLER
      2. CRTSRVPGM ACT4SRVB ACT4SRV *NEW
      3. CRTSRVPGM ACT4SRVC ACT4SRV ACT4GRP
  • ACT3Cモジュールより作成
      1. CRTPGM ACT3CA ACT3SRVA ACT4SRVA *CALLER
      2. CRTPGM ACT3CB ACT3SRVB ACT4SRVB *NEW
      3. CRTPGM ACT3CC ACT3SRVC ACT4SRVC ACT3GRP
      4. CRTPGM ACT4CA ACT3SRVA ACT4SRVA *CALLER
      5. CRTPGM ACT4CB ACT3SRVB ACT4SRVB *NEW
      6. CRTPGM ACT4CC ACT3SRVC ACT4SRVC ACT3GRP

    それぞれの実行結果をみていくと、その動作の違いに気がつくかと思います。