%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:
Allocate memory.
Release a memory handle.
Return the size of memory allocated to a memory handle.
Register an external memory segment and assign a new memory handle.
Reallocate (change the size of) a memory handle.
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
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
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.
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.
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))
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)
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)