The Dynamic Memory Manager (DMM) consists of a library of subroutines for dynamic memory allocation intended for the Fortran, specifically the Fortran77, programming environment. DMM also supports the link between MemCom data objects and the dynamic memory. DMM allows for
Run-time dynamic allocation of memory, i.e no need for
reserving space during compilation (i.e by Fortran
dimension
or common
statements).
Access of memory segments (datasets or DMM objects) by identifier (address) or by name (symbolically).
Automatic management of memory segments (carried out by the system).
Dynamic reallocation of memory suggests the use of address pointers. Since pointers are not supported by the Fortran77 language a another mechanism must be applied. This is achieved by specifying the DMM reference address, i.e an array serving as reference for calculating offsets to the subsequently allocated memory blocks.
Addresses returned by DMM will then always refer to the current
DMM reference address. When the user requests a segment of memory, DMM
will return an identifier that points to the integer*4 word offset of
the segment with respect to the reference address. Note that the
reference address can be changed dynamically. In addition, the integer*4
word offset with respect to any reference address variable can be
obtained. The identifier returned by DMM points to an entry in the DMM
address table dmmptr
. Fortran77 example:
integer iad iad=dmmptr(ident)
iad
contains the reference address with respect
to refad(iad)
. It points to the start address of the
memory segment. The integer*4 word offset is computed with respect to
the user-specified reference address (see routine
dmmope
and it is automatically updated when a new
reference address is given. If an object is deleted, the corresponding
slot will be free and the reference address is set to 0. The address
table function dmmptr
is contained in insert file
memcom.ins
(f77 API) or
memcom.inc
(ftn API).
DMM data objects (pure memory objects or MemCom datasets) are uniquely identified by the identifier. The identifier is assigned to an object upon the object's creation in memory, and it remains until the object is explicitly deleted from the Dynamic Memory buffer or until the Dynamic Memory buffer is cleared or DMM is closed. Any other attributes, such as object name, type, size, memory address, etc. may change during the existence of an object, but the identifier remains the same. Thus, the application program design must be such that any reallocation of memory will not create conflicts with already allocated addresses (by calls to a subprogram).
Data objects are internally described by the data object description tables. These tables are transparent to the application program. They contain information on the data object name (if any), the associated database handle (if any), the data type (if specified), the size of the data object and the absolute address. In addition, classes of data objects can be defined.
DMM is accessed exclusively via subroutine (procedure) calls. The
ident
parameter, as already emphasized above, is a
unique positive integer returned by the DMM memory allocation routines
dmmall
or dmmget
. Example to
allocate an array of F floats (f77 API):
subroutine demo(refad) c integer refad(*) c #include "memcom.ins" c integer nwords,ident c nwords=1000 call mcf_dmm_allocate('F',nwords,ident,istat) c c refad(dmmptr(ident)) now points to start address of array
If not stated otherwise, the parameter nwords
always refers to the number of machine words. A machine word is the
space required to store a Fortran real or an integer number. Some
routines require idiv
to be specified. The parameter
idiv
has the same signification as in the database
manager module (see routines getdb
and
putdb
). idiv
should be set to 0,
except if the memory object has been saved on the database with
idiv
> 0 and if a sub-set is required. The latter
case requires the object to be defined on database with the
dssdb
(define super-set) routine. The database
handle may be assigned to a memory object. It is only signification if
MM is closed with an active save flag in function
dmmcls
. Objects with the attribute
handle
> 0 will then automatically be copied to
unit iu
. By default handle
is set
to 0. A dataset name may be assigned to a memory object. The name may be
used to identify the object or to save it to a database. Labeled memory
objects have the advantage that the identifier can be retrieved if the
memory object name is given. Fortran example:
subroutine demo() call mcf_dmm_get_ident(handle,'COORDINATES',ident) if(ident.le.0) then print*,'***ERROR*** Set not found' else print*,'ident of COORDINATES = ',ident endif
By default a DMM object contains no attributes. The data object
precision type prec
may be assigned to a memory
object. The attribute prec
is used for copying
objects to database only. The user code iucode
may be
assigned to memory objects. User codes are particularly useful if
classes of memory objects must be defined. Memory objects of a
particular class (constant user code) can the be manipulated. Example:
Allocate a user code to all memory objects that point to graphical
display lists. There may be 10 such objects in DMM. If no longer needed,
all objects of that class can be removed by a single call to
dmmdel
, indicating the class. It is thus much
easier to control the Dynamic Memory buffer.
The following Fortran program illustrates the use of DMM for the allocation of dynamic memory during run-time. DMM objects without name are created, filled with data, and subsequently de-allocated (f77 API).
program dmm_ex1 c #include "memcom.ins" c c DMM reference address c real*8 iwork(1) c integer*4 status mcf_size is1,is2,is3 c c open dmm c call mcf_dmm_open(iwork(1),status) c c Allocate space for 3 memory sets of size is1,is2,is3 call mcf_dmm_allocate('E',is1,ident1,status) call mcf_dmm_allocate('E',is2,ident2,status) call mcf_dmm_allocate('E',is3,ident3,status) c transfer addresses to kernel routine call sub( is1,iwork(dmmptr(ident1)),is2,iwork(dmmptr(ident2)), 1 is3,iwork(dmmptr(ident1)) ) c close call mcf_dmm_close(0,istat) end subroutine sub(na,a,nb,b,nc,c) c process data transmitted by address real*4 a(na),b(nb),c(nc) c process here... return end
The next examples explains how MemCom
datasets are loaded from the database to the Dynamic Memory buffer (f77
API example): The call to dmmget
is similar to the
call to getdb
, but instead of copying data into
user-specified areas the data are copied into a memory segment created
by DMM. In addition, scratch memory space is reserved (f77 API).
program dmm_ex2 c #include "memcom.ins" c c DMM reference address c real*8 work(1) c mcf_size nnode(3) !! number of nodes table mcf_site nnmax integer*4 idnode(3),idnnmax !! DMM idents integer*4 status integer*4 handle c c Open dmm c call dmmope(iwork(1),istat) c c Open MemCom database c handle=3 !! MemCom database unit call mcf_db_open('test.db','o',status) handle=status c c Suppose that these parameters are known c nnode(1)=500 nnode(2)=1200 nnode(3)=450 c c Get MemCom datasets. Idents idnode(i) are assigned by DMM. c call mcf_dmm_get_set(handle,'COOR.1',nnode(1),'E',idnode(1),status) call mcf_dmm_get_set(handle,'COOR.2',nnode(2),'E',idnode(2),status) call mcf_dmm_get_set(handle,'COOR.3',nnode(3),'E',idnode(3),status) c Reserve scratch space for aux vector nnmax=max(nnode(1),nnode(2),nnode(3)) call dmmall(nnmax,idnnmax,status) c Operate on sets, transfer addresses to kernel routine. c Delete sets not needed. do i=1,3 call sub(nnode(i),iwork(dmmptr(idnode(i)), 1 nnmax,iwork(dmmptr(idnnmax)) call mcf_dmm_delete(nnode(i),status) enddo c c Remove DMM sets c call mcf_dmm_delete(idnnmax,status) end subroutine sub(nn,a,nnmax,vect) c Routine processes data transferred by address real*4 a(nn),vect(nntot) c process here... return end