Sign in

docs Examples

DYNMEMCEE

DYNMEMCEE

**FREE

///
// Dynamic Memory Example using CEE API
//
// This example shows how to allocate, reallocate and deallocate memory from
// a user-created heap storage from the Common Execution Environment (CEE).
//
// The advantage of using a user-created heap instead of the default heap storage
// is that not every allocation needs to be tracked as the system does it for you.
// After finishing the processing only the heap needs to be discarded and not 
// every single allocation separately.
//
// See "Managing Your Own Heap Using ILE Bindable APIs" at 
// http://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_73/rzasc/dynarr.htm .
//
// For any memory operation the CEE API is used. The DSPLY opcode is used to 
// output any result.
//
// By using the CEE API "Mark Heap" and "Release Heap" a range of allocations
// beginning from the mark can be freed/released.
//
// \author Mihael Schmidt
// \date 2016-12-17
///


ctl-opt main(main) dftactgrp(*no) actgrp(*caller);


//-------------------------------------------------------------------------------------------------
// Prototypes
//-------------------------------------------------------------------------------------------------
dcl-pr main extpgm('DYNMEMCEE') end-pr;

dcl-pr cee_getStorage extproc('CEEGTST');
  heapId int(10) const;
  size int(10) const;
  retAddr pointer;
  feedback char(12) options(*omit);
end-pr;

dcl-pr cee_freeStorage extproc('CEEFRST');
  address pointer;
  feedback char(12) options(*omit);
end-pr;

dcl-pr cee_reallocateStorage extproc('CEECZST');
  address pointer;
  size int(10) const;
  feedback char(12) options(*omit);
end-pr;

dcl-pr cee_createHeap extproc('CEECRHP');
  heapId int(10);
  initSize int(10) const options(*omit);
  increment int(10) const options(*omit);
  allocStrat int(10) const options(*omit);
  feedback char(12) options(*omit);
end-pr;

dcl-pr cee_discardHeap extproc('CEEDSHP');
  heapId int(10);
  feedback char(12) options(*omit);
end-pr;


//-------------------------------------------------------------------------------------------------
// Program Entry Point
//-------------------------------------------------------------------------------------------------
dcl-proc main;
  // heap id
  dcl-s heapId int(10);
  // this pointer is the access point to the allocated memory
  dcl-s ptr pointer;
  dcl-s firstName char(10) based(ptr);
  dcl-s fullName char(20) based(ptr);

  // get a heap via CEE API
  cee_createHeap(heapId : *omit : *omit : *omit : *omit);

  // now we are taking 10 bytes from the user-created heap. 
  //
  // From the ILE RPG Language Reference:
  // "%ALLOC returns a pointer to newly allocated heap storage of the length specified.
  //  The newly allocated storage is uninitialized."
  cee_getStorage(heapId : 10 : ptr : *omit);

  // The %str built-in function lets us assign a value to the storage to which the pointer points
  %str(ptr : 9) = 'William';
  // the %str built-in function is normally used in conjunction with the C language and
  // adds a NULL (x'00') at the end of the value.
  dsply firstName;

  // To not have this NULL value at the end we could use the "memcpy" C function
  // but if we are working with fixed length fields (which is the common case in
  // RPG) it is much easier to access the value by using a variable which is
  // based on the pointer (ptr) by using the BASED keyword on the variable declaration
  firstName = 'William';

  // no more NULL value
  dsply firstName;


  // The difference is more obvious in the debugger:
  // With %str : E6899393 89819400 0000.... ........   - William.........
  // With BASED: E6899393 89819440 4040.... ........   - William   ......


  // we use the CEE API CEECZST to enlarge the space we previously allocated the 
  // value we previously assigned to the memory will remain after the reallocation.
  cee_reallocateStorage(ptr : 20 : *omit);

  // reassure that we still have the same value
  dsply firstName;

  // using the enlarged space by using a bigger variable which is based on the pointer
  fullName = 'William Shakespeare';
  dsply fullName;

  // Never forget to free/deallocate the taken memory from the heap. Not freeing
  // the memory will cause a memory leak as it is allocated but you have no
  // pointer to the memory any more.
  //
  // It will automatically be freed with the ending of the job.
  //
  // When using a user-created heap it is enough to just discard the heap for
  // freeing the allocated storage.
  cee_discardHeap(heapId : *omit);
end-proc;