MPI manages system memory that is used for buffering messages and for storing internal representations of various MPI objects such as groups, communicators, datatypes, etc. This memory is not directly accessible to the user, and objects stored there are opaque: their size and shape is not visible to the user. Opaque objects are accessed via handles, which exist in user space. MPI procedures that operate on opaque objects are passed handle arguments to access these objects. In addition to their use by MPI calls for object access, handles can participate in assignment and comparisons.
In Fortran, all handles have type INTEGER. In C, a different handle type is defined for each category of objects. These should be types that support assignment and equality operators.
In Fortran, the handle can be an index to a table of opaque objects in system table; in C it can be such index or a pointer to the object. More bizarre possibilities exist.
Opaque objects are allocated and deallocated by calls that are specific to each object type. These are listed in the sections where the objects are described. The calls accept a handle argument of matching type. In an allocate call this is an OUT argument that returns a valid reference to the object. In a call to deallocate this is an INOUT argument which returns with a ``null handle'' value. MPI provides a ``null handle'' constant for each object type. Comparisons to this constant are used to test for validity of the handle.
A call to deallocate invalidates the handle and marks the object for deallocation. The object is not accessible to the user after the call. However, MPI need not deallocate the object immediatly. Any operation pending (at the time of the deallocate) that involves this object will complete normally; the object will be deallocated afterwards.
MPI calls do not change the value of handles, with the exception of calls that allocate and deallocate objects, and of the call MPI_TYPE_COMMIT, in Section Commit and free .
A null handle argument is an erroneous IN argument in MPI calls, unless an exception is explicitly stated in the text that defines the function. Such exception is allowed for handles to request objects in Wait and Test calls (sections Communication Completion and Multiple Completions ). Otherwise, a null handle can only be passed to a function that allocates a new object and returns a reference to it in the handle.
An opaque object and its handle are significant only at the process where the object was created, and cannot be transferred to another process.
MPI provides certain predefined opaque objects and predefined, static handles to these objects. Such objects may not be destroyed.
This design hides the internal representation used for MPI data structures, thus allowing similar calls in C and Fortran. It also avoids conflicts with the typing rules in these languages, and easily allows future extensions of functionality. The mechanism for opaque objects used here loosely follows the POSIX Fortran binding standard.
The explicit separating of handles in user space, objects in system space, allows space-reclaiming, deallocation calls to be made at appropriate points in the user program. If the opaque objects were in user space, one would have to be very careful not to go out of scope before any pending operation requiring that object completed. The specified design allows an object to be marked for deallocation, the user program can then go out of scope, and the object itself still persists until any pending operations are complete.
The requirement that handles support
assignment/comparison is made since
such operations are common.
This restricts the domain of possible implementations.
The alternative would have been
to allow handles to have been an arbitrary, opaque type. This would
force the introduction of routines to do assignment and comparison, adding
complexity, and was therefore ruled out.
( End of rationale.)
Advice to users.
A user may accidently create a dangling reference
by assigning to a handle the value of
another handle, and then deallocating the object associated with these
handles. Conversely, if a handle variable is deallocated before the
associated object is freed, then the object becomes inaccessible (this may
occur, for example, if the handle is a local variable within a
subroutine, and the
subroutine is exited before the associated object is deallocated).
It is the user's responsibility to
avoid adding or deleting references to opaque
objects, except as a result of calls that allocate or deallocate such objects.
( End of advice to users.)
Advice to implementors.
The intended semantics of opaque objects is that each opaque object is separate
from each other; each call to allocate such an object copies all the information
required for the object. Implementations may avoid excessive copying by
substituting referencing for copying. For example, a derived datatype
references to its components, rather then copies of its components; a call to
MPI_COMM_GROUP may return a reference to the group associated with
the communicator, rather than a copy of this group. In such cases, the
implementation must maintain reference counts, and allocate and deallocate
objects such that the visible effect is as if the objects were copied.
( End of advice to implementors.)