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.