ILE バインド可能 API を使用したユーザー独自のヒープ管理
1 つ以上のユーザー作成ヒープを作成することによって、 活動化グループ内の一部のプログラムおよびプロシージャーで使用される動的記憶域を分離することができます。 ユーザー作成ヒープの作成については、「ILE 概念」を参照してください。
- 配列の初期化
- 配列への要素の追加
- 要素の値の戻し
- 配列用の記憶域の解放
DYNARRAY は、REALLOC 命令コードだけでなく、CEECRHP (ヒープ作成)、CEEGTST (記憶域取得)、 および CEEDSHP (ヒープ廃棄) という 3 つの ILE バインド可能記憶域 API を使用してこれらの処置を行います。記憶域管理バインド可能 API に特有の情報は、Web サイト http://www.ibm.com/systems/i/infocenter/ で IBM® i Information Center の中の『プログラミング』カテゴリーの『CL および API』の節を参照してください。
図 1 では、DYNARRAY 内のプロシージャーのプロトタイプを含む、/COPY ファイル DYNARRI を示します。 この /COPY ファイルは、DYNARRAY にプロシージャーを呼び出す その他のモジュールだけでなく、DYNARRAY モジュールによって使用されます。
DYNARRAY は、(15,0) パック 10 進数配列で使用されるように定義されています。 これは、単に DYNA_TYPE の定義を文字フィールドに変更することによって、 文字配列の処理を容易に変換することができます。
*=================================================================
* DYNARRAY : (実際には) バインドされていない実行時パック (15,0)
* 配列の処理。DYNARRAY モジュールには、配列を割り振り、
* 配列値を戻すか設定し、配列を割り振り解除する
* プロシージャーが含まれています。
*=================================================================
D DYNA_TYPE S 15P 0
D DYNA_INIT PR
D DYNA_TERM PR
D DYNA_SET PR
D Element VALUE LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
D DYNA_GET PR LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
図 2 は、制御仕様書と定義仕様書を含むモジュール DYNARRAY の最初の部分を示します。
*=================================================================
* DYNARRAY : (実際には) バインドされていない実行時パック (15,0)
* 配列の処理。このモジュールには、配列を割り振り、
* 配列値を戻すか設定し、配列を割り振り解除する
* プロシージャーが含まれています。
*=================================================================
H NOMAIN
*-----------------------------------------------------------------
* このモジュール内のプロシージャー用のプロトタイプ
*-----------------------------------------------------------------
/COPY DYNARRI
*-----------------------------------------------------------------
* CEEGTST API (ヒープ記憶域取得) へのインターフェース
* 1) HeapId = ヒープの ID。
* 2) Size = 割り振るバイト数
* 3) RetAddr= 割り振られた記憶域の戻りアドレス
* 4) *OMIT = フィードバック・パラメーター。ここに *OMIT を指定
* することは、要求が満たされなかった時に API から
* 例外を受け取ることを意味します。
* これを監視しているわけではないので、呼び出し
* プロシージャーが例外を受け取ることになります。
*-----------------------------------------------------------------
D CEEGTST PR
D HeapId 10I 0 CONST
D Size 10I 0 CONST
D RetAddr *
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------
* CEECRHP API (ヒープ作成) へのインターフェース
* 1) HeapId = ヒープの ID。
* 2) InitSize = ヒープの初期サイズ。
* 3) Incr = ヒープを拡大する必要がある場合に
* 増分するバイト数。
* 4) AllocStrat = このヒープの場合の割り振り方法。値を
* 0 に設定すると、システムが
* 最適な方法を選択することができます。
* 5) *OMIT = フィードバック・パラメーター。ここに *OMIT を指定
* することは、要求が満たされなかった時に API から
* 例外を受け取ることを意味します。
* これを監視しているわけではないので、呼び出し
* プロシージャーが例外を受け取ることになります。
*-----------------------------------------------------------------
D CEECRHP PR
D HeapId 10I 0
D InitSize 10I 0 CONST
D Incr 10I 0 CONST
D AllocStrat 10I 0 CONST
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------
* CEEDSHP API (ヒープ廃棄) へのインターフェース
* 1) HeapId = ヒープの ID。
* 2) *OMIT = フィードバック・パラメーター。ここに *OMIT を指定
* することは、要求が満たされなかった時に API から
* 例外を受け取ることを意味します。
* これを監視しているわけではないので、呼び出し
* プロシージャーが例外を受け取ることになります。
*-----------------------------------------------------------------
D CEEDSHP PR
D HeapId 10I 0
D Feedback 12A OPTIONS(*OMIT)
*-----------------------------------------------------------------
* グローバル変数
*-----------------------------------------------------------------
D HeapVars DS
D HeapId 10I 0
D DynArr@ *
*-----------------------------------------------------------------
* 動的配列の定義。要素数を使用可能な最大数でコーディングしますが、
* この定義には実際には記憶域は宣言されないことに注意して
* ください (これが BASED であるため)。
*-----------------------------------------------------------------
D DynArr S DIM(32767) BASED(DynArr@)
D LIKE(DYNA_TYPE)
*-----------------------------------------------------------------
* 動的配列の要素の現在数を、
* 常にグローバルに記録しておきます。
*-----------------------------------------------------------------
D NumElems S 10I 0 INZ(0)
*-----------------------------------------------------------------
* 配列に割り振られる要素の初期数および
* 後続の割り振りで配列に追加される
* 要素の最小数。
*-----------------------------------------------------------------
D INITALLOC C 100
D SUBSALLOC C 100
図 3 は DYNARRAY にあるサブプロシージャーを示したものです。
*=================================================================
* DYNA_INIT: 配列を初期化します。
*
* 機能: ヒープを作成し、実行時配列に記憶域の初期量を
* 割り振ります。
*=================================================================
P DYNA_INIT B EXPORT
*-----------------------------------------------------------------
* ローカル変数。
*-----------------------------------------------------------------
D Size S 10I 0
*
* 事前に定義された要素数で開始します。
*
C Z-ADD INITALLOC NumElems
*
* 配列に必要なバイト数を決定します。
*
C EVAL Size = NumElems * %SIZE(DynArr)
*
* ヒープの作成
*
C CALLP CEECRHP(HeapId : Size : 0 : 0 : *OMIT)
*
* 記憶域を割り振り、配列の基底ポインターを、API から
* 戻されたポインターに設定します。
*
* ALLOC 命令コードがデフォルト・ヒープを使用するため、CEEGTST API を
* 使用して別のヒープを指定する必要があることに注意してください。
*
C CALLP CEEGTST(HeapId : Size : DynArr@ : *OMIT)
*
* 配列の記憶域の初期化
*
C 1 DO NumElems I 5 0
C CLEAR DynArr(I)
C ENDDO
P DYNA_INIT E
*=================================================================
* DYNA_TERM: 配列処理を終了させます。
*
* 機能: ヒープを削除します。
*=================================================================
P DYNA_TERM B EXPORT
C CALLP CEEDSHP(HeapId : *OMIT)
C RESET HeapVars
P DYNA_TERM E
*=================================================================
* DYNA_SET: 配列要素を設定します。
*
* 機能: この要素に対して配列が十分な大きさであることを確認して、
* 要素を指定された値に設定します。
*=================================================================
P DYNA_SET B EXPORT
*-----------------------------------------------------------------
* このプロシージャーの入力パラメーター。
*-----------------------------------------------------------------
D DYNA_SET PI
D Element VALUE LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
*-----------------------------------------------------------------
* ローカル変数。
*-----------------------------------------------------------------
D Size S 10I 0
*-----------------------------------------------------------------
* 配列への追加を選択した場合には、配列が十分に大きいかどうかが
* 最初に検査され、十分でない場合にはそのサイズが増やされます。
* 要素を追加します。
*-----------------------------------------------------------------
C Index IFGT NumElems
C EXSR REALLOC
C ENDIF
C EVAL DynArr(Index) = Element
*=================================================================
* REALLOC: 記憶域再割り振りサブルーチン
*
* 機能: 動的配列のサイズを増やして、
* 新しい要素を初期化します。
*=================================================================
C REALLOC BEGSR
*
* 元の要素の数を記憶
*
C Z-ADD NumElems OldElems 5 0
*
* 新しい要素の数を計算します。指標が配列内の現在の要素数に
* 新しい割り振り数を加えたものより大きい場合には、その
* 指標まで割り振り、そうでない場合には
* 配列に新しい割り振り量を加算します。
*
C IF Index > NumElems + SUBSALLOC
C Z-ADD Index NumElems
C ELSE
C ADD SUBSALLOC NumElems
C ENDIF
*
* 配列の新しいサイズを計算します
*
C EVAL Size = NumElems * %SIZE(DynArr)
*
* 記憶域を再割り振りします。新しい記憶域の値は、元の記憶域と
* 同じです。
*
C REALLOC Size DynArr@
*
* 配列の新しい要素を初期化します。
*
C 1 ADD OldElems I
C I DO NumElems I 5 0
C CLEAR DynArr(I)
C ENDDO
C ENDSR
P DYNA_SET E
*=================================================================
* DYNA_GET: 配列要素を戻します。
*
* 機能: 配列要素が配列のサイズ内である場合には、この要素の
* 現在の値を戻します。そうでない場合には、
* デフォルト値を戻します。
*=================================================================
P DYNA_GET B EXPORT
*-----------------------------------------------------------------
* このプロシージャーの入力パラメーター。
*-----------------------------------------------------------------
D DYNA_GET PI LIKE(DYNA_TYPE)
D Index 5I 0 VALUE
*-----------------------------------------------------------------
* ローカル変数。
*-----------------------------------------------------------------
D Element S LIKE(DYNA_TYPE) INZ
*-----------------------------------------------------------------
* 要求した配列が現行サイズ内であれば、この要素の現行値を
* 戻します。そうでない場合には、デフォルト (初期化) の値を
* 使用することができます。
*-----------------------------------------------------------------
C Index IFLE NumElems
C EVAL Element = DynArr(Index)
C ENDIF
C RETURN Element
P DYNA_GET E
- DYNA_INIT は、ILE バインド可能 API CEECRHP (ヒープ作成) を使用してヒープを作成し、グローバル変数 HeapId にヒープ ID を保管する。これは、ILE バインド可能 API CEEGTST (ヒープ記憶域取得) を呼び出すことによって、 配列の初期値 (この場合は 100) に基づいてヒープ記憶域を割り振ります。
- DYNA_TERM は、ILE バインド可能 API CEEDSHP (ヒープ廃棄) を使用してヒープを破棄する。
- DYNA_SET は要素の値を配列に設定する。
要素を配列に追加する前に、プロシージャーは十分なヒープ記憶域があるかどうかを調べます。 十分でない場合には、命令コード REALLOC を使用して追加の記憶域を取得します。
- DYNA_GET は指定された要素の値を戻す。 プロシージャーは、要求された要素かゼロのいずれかを呼び出し元に戻します。 ゼロが戻されるのは、要求された要素が実際には配列に保管されていない場合です。
CRTRPGMOD MODULE(MYLIB/DYNARRAY) SRCFILE(MYLIB/QRPGLESRC)
このプロシージャーは、この後で CRTPGM または CRTSRVPGM を使用してその他の モジュールとバインドすることができます。
図 4 DYNARRAY 内のモジュールをテストする、別のモジュールを示します。
*=================================================================
* DYNTEST: DYNARRAY モジュールのテスト・プログラム
*=================================================================
/COPY EXAMPLES,DYNARRI
D X S LIKE(DYNA_TYPE)
* 配列の初期化
C CALLP DYNA_INIT
* 一部要素の設定
C CALLP DYNA_SET (25 : 3)
C CALLP DYNA_SET (467252232 : 1)
C CALLP DYNA_SET (-2311 : 750)
* 一部要素の検索
C EVAL X = DYNA_GET (750)
C '750' DSPLY X
C EVAL X = DYNA_GET (8001)
C '8001' DSPLY X
C EVAL X = DYNA_GET (2)
C '2' DSPLY X
* 終結処理
C CALLP DYNA_TERM
C SETON LR