Managing Your Own Heap Using ILE Bindable APIs

You can isolate the dynamic storage used by some programs and procedures within an activation group by creating one or more user-created heaps. For information on creating a user-created heap refer to ILE Concepts.

The following example shows you how to manage dynamic storage for a run-time array with a user-created heap from an ILE RPG procedure. In this example, the procedures in the module DYNARRAY dynamically allocate storage for a practically unbounded packed array. The procedures in the module perform the following actions on the array:

DYNARRAY performs these actions using the three ILE bindable storage APIs, CEECRHP (Create Heap), CEEGTST (Get Storage), and CEEDSHP (Discard Heap), as well as the REALLOC operation code. For specific information about the storage management bindable APIs, refer to the CL and APIs section of the Programming category in the i5/OS Information Center at this Web site - http://www.ibm.com/systems/i/infocenter/.

Figure 56 shows the /COPY file DYNARRI containing the prototypes for the procedures in DYNARRAY. This /COPY file is used by the DYNARRAY module as well as any other modules that call the procedures in DYNARRAY.

DYNARRAY has been defined for use with a (15,0) packed decimal array. It could easily be converted to handle a character array simply by changing the definition of DYNA_TYPE to a character field.

Figure 56. /COPY file DYNARRI containing prototypes for DYNARRAY module
      *=================================================================
      * DYNARRAY :     Handle a (practically) unbounded run-time
      *                Packed(15,0) array.   The DYNARRAY module contains
      *                procedures to allocate the array, return or set
      *                an array value and deallocate the array.
      *=================================================================
     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

Figure 57 shows the beginning of module DYNARRAY containing the Control specification, and Definition specifications.

Figure 57. Global variables and local prototypes for DYNARRAY
      *=================================================================
      * DYNARRAY :     Handle a (practically) unbounded run-time
      *                Packed(15,0) array.   This module contains
      *                procedures to allocate the array, return or set
      *                an array value and deallocate the array.
      *=================================================================
     H NOMAIN
      *-----------------------------------------------------------------
      * Prototypes for the procedures in this module.
      *-----------------------------------------------------------------
      /COPY DYNARRI
      *-----------------------------------------------------------------
      * Interface to the CEEGTST API (Get Heap Storage).
      *  1) HeapId = Id of the heap.
      *  2) Size   = Number of bytes to allocate
      *  3) RetAddr= Return address of the allocated storage
      *  4) *OMIT  = The feedback parameter.  Specifying *OMIT here
      *              means that we will receive an exception from
      *              the API if it cannot satisfy our request.
      *              Since we do not monitor for it, the calling
      *              procedure will receive the exception.
      *-----------------------------------------------------------------
     D CEEGTST         PR
     D   HeapId                      10I 0       CONST
     D   Size                        10I 0       CONST
     D   RetAddr                       *
     D   Feedback                    12A         OPTIONS(*OMIT)
      *-----------------------------------------------------------------
      * Interface to the CEECRHP API (Create Heap).
      *  1) HeapId     = Id of the heap.
      *  2) InitSize   = Initial size of the heap.
      *  3) Incr       = Number of bytes to increment if heap must be
      *                  enlarged.
      *  4) AllocStrat = Allocation strategy for this heap.  We will
      *                  specify a value of 0 which allows the system
      *                  to choose the optimal strategy.
      *  5) *OMIT      = The feedback parameter.  Specifying *OMIT here
      *                  means that we will receive an exception from
      *                  the API if it cannot satisfy our request.
      *                  Since we do not monitor for it, the calling
      *                  procedure will receive the exception.
      *-----------------------------------------------------------------
     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)
      *-----------------------------------------------------------------
      * Interface to the CEEDSHP API (Discard Heap).
      *  1) HeapId     = Id of the heap.
      *  2) *OMIT      = The feedback parameter.  Specifying *OMIT here
      *                  means that we will receive an exception from
      *                  the API if it cannot satisfy our request.
      *                  Since we do not monitor for it, the calling
      *                  procedure will receive the exception.
      *-----------------------------------------------------------------
     D CEEDSHP         PR
     D   HeapId                      10I 0
     D   Feedback                    12A         OPTIONS(*OMIT)
      *-----------------------------------------------------------------
      * Global variables.
      *-----------------------------------------------------------------
     D HeapVars        DS
     D   HeapId                      10I 0
     D   DynArr@                       *
      *-----------------------------------------------------------------
      * Define the dynamic array.  We code the number of elements
      * as the maximum allowed, noting that no storage will actually
      * be declared for this definition (because it is BASED).
      *-----------------------------------------------------------------
     D DynArr          S                   DIM(32767) BASED(DynArr@)
     D                                     LIKE(DYNA_TYPE)
      *-----------------------------------------------------------------
      * Global to keep track of the current number of elements
      * in the dynamic array.
      *-----------------------------------------------------------------
     D NumElems        S             10I 0 INZ(0)

      *-----------------------------------------------------------------
      * Initial number of elements that will be allocated for the
      * array, and minimum number of elements that will be added
      * to the array on subsequent allocations.
      *-----------------------------------------------------------------
     D INITALLOC       C                   100
     D SUBSALLOC       C                   100

Figure 58 shows the subprocedures in DYNARRAY.

Figure 58. DYNARRAY Subprocedures
      *=================================================================
      * DYNA_INIT: Initialize the array.
      *
      * Function: Create the heap and allocate an initial amount of
      *           storage for the run time array.
      *=================================================================
     P DYNA_INIT       B                   EXPORT
      *-----------------------------------------------------------------
      * Local variables.
      *-----------------------------------------------------------------
     D Size            S             10I 0
      *
      * Start with a pre-determined number of elements.
      *
     C                   Z-ADD     INITALLOC     NumElems
      *
      * Determine the number of bytes needed for the array.
      *
     C                   EVAL      Size = NumElems * %SIZE(DynArr)
      *
      * Create the heap
      *
     C                   CALLP     CEECRHP(HeapId : Size : 0 : 0 : *OMIT)

      *
      * Allocate the storage and set the array basing pointer
      * to the pointer returned from the API.
      *
      * Note that the ALLOC operation code uses the default heap so
      * we must use the CEEGTST API to specify a different heap.
      *
     C                   CALLP     CEEGTST(HeapId : Size : DynArr@ : *OMIT)

      *
      * Initialize the storage for the array.
      *
     C     1             DO        NumElems      I                 5 0
     C                   CLEAR                   DynArr(I)
     C                   ENDDO
     P DYNA_INIT       E

      *=================================================================
      * DYNA_TERM: Terminate array handling.
      *
      * Function: Delete the heap.
      *=================================================================
     P DYNA_TERM       B                   EXPORT
     C                   CALLP     CEEDSHP(HeapId : *OMIT)
     C                   RESET                   HeapVars
     P DYNA_TERM       E
      *=================================================================
      * DYNA_SET: Set an array element.
      *
      * Function: Ensure the array is big enough for this element,
      *           and set the element to the provided value.
      *=================================================================
     P DYNA_SET        B                   EXPORT
      *-----------------------------------------------------------------
      * Input parameters for this procedure.
      *-----------------------------------------------------------------
     D DYNA_SET        PI
     D   Element                             VALUE LIKE(DYNA_TYPE)
     D   Index                        5I 0   VALUE
      *-----------------------------------------------------------------
      * Local variables.
      *-----------------------------------------------------------------
     D Size            S             10I 0
      *-----------------------------------------------------------------
      * If the user selects to add to the array, then first check
      * if the array is large enough, if not then increase its
      * size. Add the element.
      *-----------------------------------------------------------------
     C     Index         IFGT      NumElems
     C                   EXSR      REALLOC
     C                   ENDIF
     C                   EVAL      DynArr(Index) = Element
      *=================================================================
      * REALLOC: Reallocate storage subroutine
      *
      *         Function: Increase the size of the dynamic array
      *                   and initialize the new elements.
      *=================================================================
     C     REALLOC       BEGSR

      *
      *  Remember the old number of elements
      *
     C                   Z-ADD     NumElems      OldElems          5 0

      *
      *  Calculate the new number of elements.  If the index is
      *  greater than the current number of elements in the array
      *  plus the new allocation, then allocate up to the index,
      *  otherwise, add a new allocation amount onto the array.
      *
     C                   IF        Index > NumElems + SUBSALLOC
     C                   Z-ADD     Index         NumElems
     C                   ELSE
     C                   ADD       SUBSALLOC     NumElems
     C                   ENDIF
      *
      * Calculate the new size of the array
      *
     C                   EVAL      Size =  NumElems * %SIZE(DynArr)
      *
      * Reallocate the storage.  The new storage has the same value
      * as the old storage.
      *
     C                   REALLOC   Size          DynArr@
      *
      * Initialize the new elements for the array.
      *
     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: Return an array element.
      *
      * Function: Return the current value of the array element if
      *           the element is within the size of the array, or
      *           the default value otherwise.
      *=================================================================
     P DYNA_GET        B                   EXPORT
      *-----------------------------------------------------------------
      * Input parameters for this procedure.
      *-----------------------------------------------------------------
     D DYNA_GET        PI                    LIKE(DYNA_TYPE)
     D   Index                        5I 0   VALUE
      *-----------------------------------------------------------------
      * Local variables.
      *-----------------------------------------------------------------
     D Element         S                     LIKE(DYNA_TYPE) INZ
      *-----------------------------------------------------------------
      * If the element requested is within the current size of the
      * array then return the element's current value.  Otherwise
      * the default (initialization) value can be used.
      *-----------------------------------------------------------------
     C     Index         IFLE      NumElems
     C                   EVAL      Element = DynArr(Index)
     C                   ENDIF
     C                   RETURN    Element
     P DYNA_GET        E

The logic of the subprocedures is as follows:

  1. DYNA_INIT creates the heap using the ILE bindable API CEECRHP (Create Heap), storing the heap Id in a global variable HeapId. It allocates heap storage based on initial value of the array (in this case 100) by calling the ILE bindable API CEEGTST (Get Heap Storage).
  2. DYNA_TERM destroys the heap using the ILE bindable API CEEDSHP (Discard Heap).
  3. DYNA_SET sets the value of an element in the array.

    Before adding an element to the array, the procedure checks to see if there is sufficient heap storage. If not, it uses operation code REALLOC to acquire additional storage.

  4. DYNA_GET returns the value of a specified element. The procedure returns to the caller either the element requested, or zeros. The latter occurs if the requested element has not actually been stored in the array.

To create the module DYNARRAY, type:

CRTRPGMOD MODULE(MYLIB/DYNARRAY) SRCFILE(MYLIB/QRPGLESRC)

The procedure can then be bound with other modules using CRTPGM or CRTSRVPGM.

Figure 59 shows another module that tests the procedures in DYNARRAY.

Figure 59. Sample module using procedures in DYNARRAY
      *=================================================================
      * DYNTEST: Test program for DYNARRAY module.
      *=================================================================
      /COPY EXAMPLES,DYNARRI
     D X               S                   LIKE(DYNA_TYPE)
      * Initialize the array
     C                   CALLP     DYNA_INIT
      * Set a few elements
     C                   CALLP     DYNA_SET (25 : 3)
     C                   CALLP     DYNA_SET (467252232 : 1)
     C                   CALLP     DYNA_SET (-2311 : 750)
      * Retrieve a few elements
     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

      * Clean up
     C                   CALLP     DYNA_TERM
     C                   SETON                                        LR


[ Top of Page | Previous Page | Next Page | Contents | Index ]