The semantics of the member functions constituting the C++ language binding for MPI are specified by the MPI function description itself. Here, we specify the semantics for those portions of the C++ language interface that are not part of the language binding. In this subsection, functions are prototyped using the type MPI::<CLASS> rather than listing each function for every MPI class; the word <CLASS> can be replaced with any valid MPI class name (e.g., Group), except as noted.
Construction / Destruction The default constructor and destructor are prototyped as follows:
MPI::<CLASS>()
MPI::<CLASS>()
In terms of construction and destruction, opaque MPI user level objects behave like handles. Default constructors for all MPI objects except MPI::Status create corresponding MPI::*_NULL handles. That is, when an MPI object is instantiated, comparing it with its corresponding MPI::*_NULL object will return true. The default constructors do not create new MPI opaque objects. Some classes have a member function Create() for this purpose.
Example
In the following code fragment, the test will return true and
the message will be sent to cout.
void foo() { MPI::Intracomm bar; if (bar == MPI::COMM_NULL) cout << "bar is MPI::COMM_NULL" << endl; }
The destructor for each MPI user level object does not invoke the corresponding MPI_*_FREE function (if it exists).
Rationale.
MPI_*_FREE functions are not automatically invoked for the following reasons:
2. The model put forth in MPI makes memory allocation and
deallocation the responsibility of the user, not the implementation.
3. Calling MPI_*_FREE upon destruction could have
unintended side effects, including triggering collective
operations (this also affects the copy, assignment, and
construction semantics). In the following example, we would want
neither foo_comm nor bar_comm to automatically invoke
MPI_*_FREE upon exit from the function.
void example_function() { MPI::Intracomm foo_comm(MPI::COMM_WORLD), bar_comm; bar_comm = MPI::COMM_WORLD.Dup(); // rest of function }
Copy / Assignment The copy constructor and assignment operator are prototyped as follows:
MPI::<CLASS>(const MPI::<CLASS>& data)
MPI::<CLASS>& MPI::<CLASS>::operator=(const MPI::<CLASS>& data)
In terms of copying and assignment, opaque MPI user level objects behave like handles. Copy constructors perform handle-based (shallow) copies. MPI::Status objects are exceptions to this rule. These objects perform deep copies for assignment and copy construction.
Advice
to implementors.
Each MPI user level object is likely to contain, by value or by
reference, implementation-dependent state information. The
assignment and copying of MPI object handles may simply copy this
value (or reference).
( End of advice to implementors.)
Example
Example using assignment operator. In this example,
MPI::Intracomm::Dup() is not called for foo_comm. The
object foo_comm is simply an alias for
MPI::COMM_WORLD. But bar_comm is created with a call to
MPI::Intracomm::Dup() and is therefore a different communicator
than foo_comm (and thus different from
MPI::COMM_WORLD).
baz_comm becomes an alias for bar_comm. If one
of bar_comm or baz_comm
is freed with MPI_COMM_FREE it will be set to
MPI::COMM_NULL. The state of the other handle will be
undefined --- it will be invalid, but not
necessarily set to MPI::COMM_NULL.
MPI::Intracomm foo_comm, bar_comm, baz_comm; foo_comm = MPI::COMM_WORLD; bar_comm = MPI::COMM_WORLD.Dup(); baz_comm = bar_comm;
Comparison
The comparison operators are prototyped as follows:
bool MPI::<CLASS>::operator==(const MPI::<CLASS>& data) const
bool MPI::<CLASS>::operator!=(const MPI::<CLASS>& data) const
The member function operator==() returns true only when the handles reference the same internal MPI object, false otherwise. operator!=() returns the boolean complement of operator==(). However, since the Status class is not a handle to an underlying MPI object, it does not make sense to compare Status instances. Therefore, the operator==() and operator!=() functions are not defined on the Status class.
Constants Constants are singleton objects and are declared const. Note that not all globally defined MPI objects are constant. For example, MPI::COMM_WORLD and MPI::COMM_SELF are not const.