%MEM_PROC

Implement memory management functions

WSupported on Windows
USupported on Unix
VSupported on OpenVMS
NSupported in Synergy .NET
result = %MEM_PROC(subfunction, arg[, ...])

Return value

result

The result of the defined operation.

Arguments

subfunction

One of the following:

DM_ALLOC

Allocate memory.

DM_FREE

Release a memory handle.

DM_GETSIZE

Return the size of memory allocated to a memory handle.

DM_REG

Register an external memory segment and assign a new memory handle.

DM_RESIZ

Reallocate (change the size of) a memory handle.

DM_TRIMSIZE

Return the trimmed size of a memory handle.

arg

One or more arguments specific to subfunction.

Discussion

%MEM_PROC implements memory management functions such as allocating memory, releasing or reallocating a memory handle, and registering an external memory segment.

The subfunction value always has the function code in the low-order eight bits. You can specify additional qualifiers in subfunction, with the constraint that the qualifier information be in the low eight bits. See the individual subfunctions for details on what, if any, additional qualifiers are allowed.

Note that all dynamic memory, static or otherwise, is constrained to the scope of the executing program. When you terminate one program and start another (for example, when you use a STOP chain), the memory allocated by %MEM_PROC is freed.

The following Synergy DBL definition file is assumed:

.define DM_ALLOC       ,^X(01)   ;Subfunctions
.define DM_REG         ,^X(02)
.define DM_RESIZ       ,^X(10)
.define DM_FREE        ,^X(11)
.define DM_GETSIZE     ,^X(12)
.define DM_TRIMSIZE    ,^X(13)
.define DM_STATIC      ,^X(0100) ;Qualifiers
.define DM_BLANK       ,^X(0200)
.define DM_NULL        ,^X(0400)
.define DM_ZERO        ,^X(0800)

Examples

The following example uses the %MEM_PROC dynamic memory function to allocate a dynamically sized array, which will be resized as needed. The routine reads the records from a customer file into memory and then sorts the records in memory and prints them out in sorted order. This example presumes that the developer can supply the local routine “print” and the QSORT sort routine “sort_by_past_due.” (See QSORT for more information.) Note that this routine does no error trapping, so it presumes that the customer records will all fit into available memory.

.align
.define D_INITIAL_ALLOC ,10	;Initially allocate for 10 records max
.define D_INCR_ALLOC    ,5	;If we need to resize, go up by 5
.define D_CUST_CHAN     ,12	;Customer channel number
.define D_FMT_MONEY     ,"Z,ZZZ,ZZZ,ZZX.XX-"
record
    handle              ,i4    ;Handle to dynamic memory
    nmalloc             ,i4    ;Number of records allocated
    nmloaded            ,i4    ;Number of records actually loaded
    ix                  ,i4    ;A scratch index
structure customer             ;Customer record structure
    group rec           ,a      
      number            ,d6
      name              ,a30
      address           ,[3]a30
      current_due       ,d12.2
      over_30           ,d12.2
      over_60           ,d12.2
      over_90           ,d12.2
    endgroup
record pline                   ;Print line buffer
    pcust               ,a6
                        ,a2
    pname               ,a30
                        ,a2
    pover90             ,a17
                        ,a2
    pover60             ,a17
                        ,a2
    pover30             ,a17
proc
;First, allocate an array and read in the customer records
    nmalloc = D_INITIAL_ALLOC             ;Allocate for 10 records
    handle = %mem_proc(DM_ALLOC, nmalloc)
    clear nmloaded                        ;None loaded yet
    open(D_CUST_CHAN, "I:I", "DAT:customers")  ;Open customer file
    repeat
      begin
        if (nmloaded .ge. nmalloc)        ;Need to increase array size?
          begin
            nmalloc += D_INCR_ALLOC       ;Bump it by 5
            handle = %mem_proc(DM_RESIZ, nmalloc, handle)
          end
        incr nmloaded                     ;Loading one now
        reads(D_CUST_CHAN, ^m(customer[nmloaded].rec, handle), eof)
      end
eof,
    close D_CUST_CHAN                     ;Close customer file
    decr nmloaded                         ;EOF on the last one
;Now do an in-memory sort based on some complex criteria
    xcall qsort(^m(customer.rec, handle), nmloaded, "sort_by_past_due")
;Now print them out in that order
    for ix from 1 thru nmloaded
      begin
        clear pline
        pcust = ^m(customer[ix].number, handle), "XXXXXX"
        pname = ^m(customer[ix].name, handle)
        pover90 = ^m(customer[ix].over_90, handle), D_FMT_MONEY
        pover60 = ^m(customer[ix].over_60, handle), D_FMT_MONEY
        pover30 = ^m(customer[ix].over_30, handle), D_FMT_MONEY
        call print
      end
    xreturn      ;Because the allocation was not static, this releases it
end

DM_ALLOC

result = %MEM_PROC(DM_ALLOC[.bor.DM_STATIC][.bor.DM_BLANK|DM_NULL|DM_ZERO], size)

Return value

result

The identifying handle associated with the allocated memory. This value is positive if DM_STATIC was specified; otherwise, it is negative. (D_HANDLE)

Arguments

DM_STATIC

(optional) Classifies the returned memory handle as static. If this flag is not present, the handle is classified as volatile, or dynamic. If it is classified as volatile and the handle has not been explicitly released (by a DM_FREE call) at the time the current activation of the current routine is exited, DM_FREE for the returned handle is called automatically.

DM_BLANK | DM_NULL | DM_ZERO

(optional) Specifies that the allocated memory is to be initialized to either blanks, nulls, or zeros, respectively. Each qualifier can be used in conjunction with DM_STATIC. If none of these qualifiers are specified, the allocated memory is uninitialized.

size

An expression that specifies the size of the memory segment to allocate. (n)

Discussion

The DM_ALLOC subfunction of %MEM_PROC allocates memory. If the memory request cannot be honored, a “Not enough memory for desired operation” error ($ERR_NOMEM) is generated.

Examples

function allocate
    a_size      ,n
stack record
    hnd         ,i4
proc
    hnd = %mem_proc(DM_ALLOC.bor.DM_STATIC, a_size)
    freturn(hnd)
endfunction

DM_FREE

result = %MEM_PROC(DM_FREE, handle)

Return value

result

A null (0) value because the memory handle is now invalid.

Arguments

handle

A memory segment handle. (D_HANDLE)

Discussion

The DM_FREE subfunction of %MEM_PROC releases a memory handle. If handle is invalid, an “Invalid memory handle” error ($ERR_INVHDL) is generated.

We recommend that you equate a memory handle to the %MEM_PROC(DM_FREE) that uses that handle. For example, if hnd contains a memory segment handle, the following code should be used to release that handle:

hnd=%mem_proc(DM_FREE, hnd)

Then, any incorrect reuse of hnd as a memory handle generates a trappable error instead of causing unpredictable results.

DM_GETSIZE

result = %MEM_PROC(DM_GETSIZE, handle)

Return value

result

The size of memory allocated to the handle. (n)

Arguments

handle

An existing memory segment handle allocated with DM_ALLOC. (D_HANDLE)

Discussion

The DM_GETSIZE subfunction of %MEM_PROC returns the size of memory allocated to a memory handle.

DM_REG

result = %MEM_PROC(DM_REG[.bor.DM_STATIC], size, address)

Return value

result

The identifying memory handle that is associated with the referenced user data. This allows Synergy DBL developers to access data made available by address. (D_HANDLE)

Arguments

DM_STATIC

(optional) Classifies the memory handle as static. If this flag is not present, the handle is classified as volatile.

size

The size of an existing memory segment. (n)

address

The address of an existing memory segment. (D_ADDR)

Discussion

Your program may call external routines written in other languages or system functions that return pointers to memory segments that were allocated outside of Synergy DBL. You can reference these segments from within your program if they are registered within your program. The process of registration does not allocate memory; it makes memory segments that are allocated externally available to your program as if they had been allocated by your program. The DM_REG subfunction of %MEM_PROC registers an external memory segment and assigns a new memory handle.

Examples

static record
    hnd         ,i4
    var         ,a1024
proc
    hnd = %mem_proc(DM_REG.bor.DM_STATIC, ^size(var), ^addr(var))

DM_RESIZ

result = %MEM_PROC(DM_RESIZ[.bor.DM_BLANK|DM_NULL|DM_ZERO], size, handle)

Return value

result

The reallocated memory handle. (D_HANDLE)

Arguments

size

The new size of the memory handle. (n)

handle

An existing memory segment handle allocated with DM_ALLOC. (D_HANDLE)

DM_BLANK | DM_NULL | DM_ZERO

(optional) Specifies that if size is greater than the existing length of the memory segment associated with the handle, the extended memory will be initialized to blanks or nulls or zeros, respectively. If none of these qualifiers are specified, the extended memory is uninitialized.

Discussion

The DM_RESIZ subfunction of %MEM_PROC reallocates (changes the size of) a memory handle by extending or collapsing it. The contents of the original data area are copied to the new data area. To return unwanted memory to the system, simply specify a lesser value as the size argument. Any information that existed in the returned memory will be lost.

Examples

record
    hnd         ,i4
proc
    hnd = %mem_proc(DM_ALLOC, 1024)
    hnd = %mem_proc(DM_RESIZ, 2048, hnd)

DM_TRIMSIZE

result = %MEM_PROC(DM_TRIMSIZE[.bor.DM_BLANK|DM_NULL|DM_ZERO], handle)

Return value

result

The blank-trimmed length of the memory associated with the handle. If the entire memory is blank, a value of 1 is returned. (n)

Arguments

handle

An existing memory segment handle associated with DM_ALLOC. (D_HANDLE)

DM_BLANK | DM_NULL | DM_ZERO

(optional) Specifies that a blank or a null or a zero, respectively, will be used instead of the default blank character to determine the trimmed length.

Discussion

The DM_TRIMSIZE subfunction of %MEM_PROC returns the trimmed size of a memory handle.

Examples

The example below returns the blank-trimmed length of handle.

trim_size = %mem_proc(DM_TRIMSIZE.bor.DM_BLANK, handle)