1
1
openmpi/ompi/mpi/cxx/comm.h

464 строки
13 KiB
C
Исходник Обычный вид История

// -*- c++ -*-
//
// Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
// University Research and Technology
// Corporation. All rights reserved.
// Copyright (c) 2004-2005 The University of Tennessee and The University
// of Tennessee Research Foundation. All rights
// reserved.
// Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
// University of Stuttgart. All rights reserved.
// Copyright (c) 2004-2005 The Regents of the University of California.
// All rights reserved.
Fixes trac:817 The C++ bindings were not tracking keyvals properly -- they were freeing some internal meta data when Free_keyval() was called, not when the keyval was actually destroyed (keyvals are refcounted in the C layer, just like all other MPI objects, because they can live for long after their corresponding Free call is invoked). This commit fixes this problem and several other things: * Add infrastructure on the ompi_attribute_keyval_t for an "extra" destructor pointer that will be invoked during the "real" constructor (i.e., when OBJ_RELEASE puts the refcount to 0). This allows calling back into the C++ layer to release meta data associated with the keyval. * Adjust all cases where keyvals are created to pass in relevant destructors (NULL or the C++ destructor). * Do essentially the same for MPI::Comm, MPI::Win, and MPI:Datatype: * Move several functions out of the .cc file into the _inln.h file since they no longer require locks * Make the 4 Create_keyval() functions call a common back-end keyval creation function that does the Right Thing depending on whether C or C++ function pointers were used for the keyval functions. The back-end function does not call the corresponding C MPI_*_create_keyval function, but rather does the work itself so that it can associate a "destructor" callback for the C++ bindings for when the keyval is actually destroyed. * Change a few type names to be more indicative of what they are (mostly dealing with keyvals [not "keys"]). * Add the 3 missing bindings for MPI::Comm::Create_keyval(). * Remove MPI::Comm::comm_map (and associated types) because it's no longer necessary in the intercepts -- it was a by-product of being a portable C++ bindings layer. Now we can just query the C layer directly to figure out what type a communicator is. This solves some logistics / callback issues, too. * Rename several types, variables, and fix many comments in the back-end C attribute implementation to make the names really reflect what they are (keyvals vs. attributes). The previous names heavily overloaded the name "key" and were ''extremely'' confusing. This commit was SVN r13565. The following Trac tickets were found above: Ticket 817 --> https://svn.open-mpi.org/trac/ompi/ticket/817
2007-02-09 02:50:04 +03:00
// Copyright (c) 2006-2007 Cisco Systems, Inc. All rights reserved.
// $COPYRIGHT$
//
// Additional copyrights may follow
//
// $HEADER$
//
class Comm_Null {
#if 0 /* OMPI_ENABLE_MPI_PROFILING */
// friend class PMPI::Comm_Null;
#endif
public:
#if 0 /* OMPI_ENABLE_MPI_PROFILING */
// construction
inline Comm_Null() { }
// copy
inline Comm_Null(const Comm_Null& data) : pmpi_comm(data.pmpi_comm) { }
// inter-language operability
This is a workaround to bug in the Intel C++ compiler, version 9.1 (all versions up to and including 20060925). The issue has been reported to Intel, along with a small [non-MPI] test program that reproduces the problem (the test program and the OMPI C++ bindings work fine with Intel C++ 9.0 and many other C++ compilers). In short, a static initializer for a global variable (i.e., its constructor is fired before main()) that takes as an argument a reference to a typedef'd type will simply get the wrong value in the argument. Specifically: {{{ namespace MPI { Intracomm COMM_WORLD(MPI_COMM_WORLD); } }}} The constructor for MPI::Intracomm should get the value of &ompi_mpi_comm_world. It does not; it seems to get a random value. As mandated by MPI-2, annex B.13.4, for C/C++ interoperability, the prototype for this constructor is: {{{ class Intracomm { public: Intracomm(const MPI_Comm& data); }; }}} Experiments with icpc 9.1/20060925 have shown that removing the reference from the prototype makes it work (!). After lots of discussions about this issue with a C++ expert (Doug Gregor from IU), we decided the following (cut-n-paste from an e-mail): ----- > So here's my question: given that OMPI's MPI_<CLASS> types are all > pointers, is there any legal MPI program that adheres to the above > bindings that would fail to compile or work properly if we simply > removed the "&" from the second binding, above? I don't know of any way that a program could detect this change. FWIW, the C++ committee has agreed that implementation of the C++ standard library are allowed to decide arbitrarily between const& and by-value. If they don't care, MPI users won't care. When you remove the '&', I suggest also removing the "const". It is redundant, but can trigger some strange name mangling in Sun's C++ compiler. ----- So with this change: * we now work again with the Intel 9.1 compiler * our C++ bindings do not exactly conform to the MPI-2 spec, but valid/legal MPI C++ apps cannot tell the difference (i.e., the functionality is the same) This commit was SVN r12514.
2006-11-09 20:34:12 +03:00
inline Comm_Null(MPI_Comm data) : pmpi_comm(data) { }
inline Comm_Null(const PMPI::Comm_Null& data) : pmpi_comm(data) { }
// destruction
virtual inline ~Comm_Null() { }
inline Comm_Null& operator=(const Comm_Null& data) {
pmpi_comm = data.pmpi_comm;
return *this;
}
// comparison
inline bool operator==(const Comm_Null& data) const {
return (bool) (pmpi_comm == data.pmpi_comm); }
inline bool operator!=(const Comm_Null& data) const {
return (bool) (pmpi_comm != data.pmpi_comm);}
// inter-language operability (conversion operators)
inline operator MPI_Comm() const { return pmpi_comm; }
// inline operator MPI_Comm*() /*const JGS*/ { return pmpi_comm; }
inline operator const PMPI::Comm_Null&() const { return pmpi_comm; }
#else
// construction
inline Comm_Null() : mpi_comm(MPI_COMM_NULL) { }
// copy
inline Comm_Null(const Comm_Null& data) : mpi_comm(data.mpi_comm) { }
// inter-language operability
This is a workaround to bug in the Intel C++ compiler, version 9.1 (all versions up to and including 20060925). The issue has been reported to Intel, along with a small [non-MPI] test program that reproduces the problem (the test program and the OMPI C++ bindings work fine with Intel C++ 9.0 and many other C++ compilers). In short, a static initializer for a global variable (i.e., its constructor is fired before main()) that takes as an argument a reference to a typedef'd type will simply get the wrong value in the argument. Specifically: {{{ namespace MPI { Intracomm COMM_WORLD(MPI_COMM_WORLD); } }}} The constructor for MPI::Intracomm should get the value of &ompi_mpi_comm_world. It does not; it seems to get a random value. As mandated by MPI-2, annex B.13.4, for C/C++ interoperability, the prototype for this constructor is: {{{ class Intracomm { public: Intracomm(const MPI_Comm& data); }; }}} Experiments with icpc 9.1/20060925 have shown that removing the reference from the prototype makes it work (!). After lots of discussions about this issue with a C++ expert (Doug Gregor from IU), we decided the following (cut-n-paste from an e-mail): ----- > So here's my question: given that OMPI's MPI_<CLASS> types are all > pointers, is there any legal MPI program that adheres to the above > bindings that would fail to compile or work properly if we simply > removed the "&" from the second binding, above? I don't know of any way that a program could detect this change. FWIW, the C++ committee has agreed that implementation of the C++ standard library are allowed to decide arbitrarily between const& and by-value. If they don't care, MPI users won't care. When you remove the '&', I suggest also removing the "const". It is redundant, but can trigger some strange name mangling in Sun's C++ compiler. ----- So with this change: * we now work again with the Intel 9.1 compiler * our C++ bindings do not exactly conform to the MPI-2 spec, but valid/legal MPI C++ apps cannot tell the difference (i.e., the functionality is the same) This commit was SVN r12514.
2006-11-09 20:34:12 +03:00
inline Comm_Null(MPI_Comm data) : mpi_comm(data) { }
// destruction
virtual inline ~Comm_Null() { }
// comparison
// JGS make sure this is right (in other classes too)
inline bool operator==(const Comm_Null& data) const {
return (bool) (mpi_comm == data.mpi_comm); }
inline bool operator!=(const Comm_Null& data) const {
return (bool) !(*this == data);}
// inter-language operability (conversion operators)
inline operator MPI_Comm() const { return mpi_comm; }
#endif
protected:
#if 0 /* OMPI_ENABLE_MPI_PROFILING */
PMPI::Comm_Null pmpi_comm;
#else
MPI_Comm mpi_comm;
#endif
};
class Comm : public Comm_Null {
public:
typedef void Errhandler_fn(Comm&, int*, ...);
typedef int Copy_attr_function(const Comm& oldcomm, int comm_keyval,
void* extra_state, void* attribute_val_in,
void* attribute_val_out,
bool& flag);
typedef int Delete_attr_function(Comm& comm, int comm_keyval,
void* attribute_val,
void* extra_state);
#if !0 /* OMPI_ENABLE_MPI_PROFILING */
#define _MPI2CPP_ERRHANDLERFN_ Errhandler_fn
#define _MPI2CPP_COPYATTRFN_ Copy_attr_function
#define _MPI2CPP_DELETEATTRFN_ Delete_attr_function
#endif
// construction
Comm();
// copy
Comm(const Comm_Null& data);
#if 0 /* OMPI_ENABLE_MPI_PROFILING */
Comm(const Comm& data) :
Comm_Null(data),
pmpi_comm((const PMPI::Comm&) data) { }
// inter-language operability
This is a workaround to bug in the Intel C++ compiler, version 9.1 (all versions up to and including 20060925). The issue has been reported to Intel, along with a small [non-MPI] test program that reproduces the problem (the test program and the OMPI C++ bindings work fine with Intel C++ 9.0 and many other C++ compilers). In short, a static initializer for a global variable (i.e., its constructor is fired before main()) that takes as an argument a reference to a typedef'd type will simply get the wrong value in the argument. Specifically: {{{ namespace MPI { Intracomm COMM_WORLD(MPI_COMM_WORLD); } }}} The constructor for MPI::Intracomm should get the value of &ompi_mpi_comm_world. It does not; it seems to get a random value. As mandated by MPI-2, annex B.13.4, for C/C++ interoperability, the prototype for this constructor is: {{{ class Intracomm { public: Intracomm(const MPI_Comm& data); }; }}} Experiments with icpc 9.1/20060925 have shown that removing the reference from the prototype makes it work (!). After lots of discussions about this issue with a C++ expert (Doug Gregor from IU), we decided the following (cut-n-paste from an e-mail): ----- > So here's my question: given that OMPI's MPI_<CLASS> types are all > pointers, is there any legal MPI program that adheres to the above > bindings that would fail to compile or work properly if we simply > removed the "&" from the second binding, above? I don't know of any way that a program could detect this change. FWIW, the C++ committee has agreed that implementation of the C++ standard library are allowed to decide arbitrarily between const& and by-value. If they don't care, MPI users won't care. When you remove the '&', I suggest also removing the "const". It is redundant, but can trigger some strange name mangling in Sun's C++ compiler. ----- So with this change: * we now work again with the Intel 9.1 compiler * our C++ bindings do not exactly conform to the MPI-2 spec, but valid/legal MPI C++ apps cannot tell the difference (i.e., the functionality is the same) This commit was SVN r12514.
2006-11-09 20:34:12 +03:00
Comm(MPI_Comm data) : Comm_Null(data), pmpi_comm(data) { }
Comm(const PMPI::Comm& data) :
Comm_Null((const PMPI::Comm_Null&)data),
pmpi_comm(data) { }
operator const PMPI::Comm&() const { return pmpi_comm; }
// assignment
Comm& operator=(const Comm& data) {
this->Comm_Null::operator=(data);
pmpi_comm = data.pmpi_comm;
return *this;
}
Comm& operator=(const Comm_Null& data) {
this->Comm_Null::operator=(data);
MPI_Comm tmp = data;
pmpi_comm = tmp;
return *this;
}
// inter-language operability
Comm& operator=(const MPI_Comm& data) {
this->Comm_Null::operator=(data);
pmpi_comm = data;
return *this;
}
#else
Comm(const Comm& data) : Comm_Null(data.mpi_comm) { }
// inter-language operability
This is a workaround to bug in the Intel C++ compiler, version 9.1 (all versions up to and including 20060925). The issue has been reported to Intel, along with a small [non-MPI] test program that reproduces the problem (the test program and the OMPI C++ bindings work fine with Intel C++ 9.0 and many other C++ compilers). In short, a static initializer for a global variable (i.e., its constructor is fired before main()) that takes as an argument a reference to a typedef'd type will simply get the wrong value in the argument. Specifically: {{{ namespace MPI { Intracomm COMM_WORLD(MPI_COMM_WORLD); } }}} The constructor for MPI::Intracomm should get the value of &ompi_mpi_comm_world. It does not; it seems to get a random value. As mandated by MPI-2, annex B.13.4, for C/C++ interoperability, the prototype for this constructor is: {{{ class Intracomm { public: Intracomm(const MPI_Comm& data); }; }}} Experiments with icpc 9.1/20060925 have shown that removing the reference from the prototype makes it work (!). After lots of discussions about this issue with a C++ expert (Doug Gregor from IU), we decided the following (cut-n-paste from an e-mail): ----- > So here's my question: given that OMPI's MPI_<CLASS> types are all > pointers, is there any legal MPI program that adheres to the above > bindings that would fail to compile or work properly if we simply > removed the "&" from the second binding, above? I don't know of any way that a program could detect this change. FWIW, the C++ committee has agreed that implementation of the C++ standard library are allowed to decide arbitrarily between const& and by-value. If they don't care, MPI users won't care. When you remove the '&', I suggest also removing the "const". It is redundant, but can trigger some strange name mangling in Sun's C++ compiler. ----- So with this change: * we now work again with the Intel 9.1 compiler * our C++ bindings do not exactly conform to the MPI-2 spec, but valid/legal MPI C++ apps cannot tell the difference (i.e., the functionality is the same) This commit was SVN r12514.
2006-11-09 20:34:12 +03:00
Comm(MPI_Comm data) : Comm_Null(data) { }
#endif
//
// Point-to-Point
//
virtual void Send(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const;
virtual void Recv(void *buf, int count, const Datatype & datatype,
int source, int tag, Status & status) const;
virtual void Recv(void *buf, int count, const Datatype & datatype,
int source, int tag) const;
virtual void Bsend(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const;
virtual void Ssend(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const ;
virtual void Rsend(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const;
virtual Request Isend(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const;
virtual Request Ibsend(const void *buf, int count, const
Datatype & datatype, int dest, int tag) const;
virtual Request Issend(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const;
virtual Request Irsend(const void *buf, int count,
const Datatype & datatype, int dest, int tag) const;
virtual Request Irecv(void *buf, int count,
const Datatype & datatype, int source, int tag) const;
virtual bool Iprobe(int source, int tag, Status & status) const;
virtual bool Iprobe(int source, int tag) const;
virtual void Probe(int source, int tag, Status & status) const;
virtual void Probe(int source, int tag) const;
virtual Prequest Send_init(const void *buf, int count,
const Datatype & datatype, int dest,
int tag) const;
virtual Prequest Bsend_init(const void *buf, int count,
const Datatype & datatype, int dest,
int tag) const;
virtual Prequest Ssend_init(const void *buf, int count,
const Datatype & datatype, int dest,
int tag) const;
virtual Prequest Rsend_init(const void *buf, int count,
const Datatype & datatype, int dest,
int tag) const;
virtual Prequest Recv_init(void *buf, int count,
const Datatype & datatype, int source,
int tag) const;
virtual void Sendrecv(const void *sendbuf, int sendcount,
const Datatype & sendtype, int dest, int sendtag,
void *recvbuf, int recvcount,
const Datatype & recvtype, int source,
int recvtag, Status & status) const;
virtual void Sendrecv(const void *sendbuf, int sendcount,
const Datatype & sendtype, int dest, int sendtag,
void *recvbuf, int recvcount,
const Datatype & recvtype, int source,
int recvtag) const;
virtual void Sendrecv_replace(void *buf, int count,
const Datatype & datatype, int dest,
int sendtag, int source,
int recvtag, Status & status) const;
virtual void Sendrecv_replace(void *buf, int count,
const Datatype & datatype, int dest,
int sendtag, int source,
int recvtag) const;
//
// Groups, Contexts, and Communicators
//
virtual Group Get_group() const;
virtual int Get_size() const;
virtual int Get_rank() const;
static int Compare(const Comm & comm1, const Comm & comm2);
virtual Comm& Clone() const = 0;
virtual void Free(void);
virtual bool Is_inter() const;
//
// Collective Communication
//
// Up in Comm because as of MPI-2, they are common to intracomm and
// intercomm -- with the exception of Scan and Exscan, which are not
// defined on intercomms.
//
virtual void
Barrier() const;
virtual void
Bcast(void *buffer, int count,
const Datatype& datatype, int root) const;
virtual void
Gather(const void *sendbuf, int sendcount,
const Datatype & sendtype,
void *recvbuf, int recvcount,
const Datatype & recvtype, int root) const;
virtual void
Gatherv(const void *sendbuf, int sendcount,
const Datatype & sendtype, void *recvbuf,
const int recvcounts[], const int displs[],
const Datatype & recvtype, int root) const;
virtual void
Scatter(const void *sendbuf, int sendcount,
const Datatype & sendtype,
void *recvbuf, int recvcount,
const Datatype & recvtype, int root) const;
virtual void
Scatterv(const void *sendbuf, const int sendcounts[],
const int displs[], const Datatype & sendtype,
void *recvbuf, int recvcount,
const Datatype & recvtype, int root) const;
virtual void
Allgather(const void *sendbuf, int sendcount,
const Datatype & sendtype, void *recvbuf,
int recvcount, const Datatype & recvtype) const;
virtual void
Allgatherv(const void *sendbuf, int sendcount,
const Datatype & sendtype, void *recvbuf,
const int recvcounts[], const int displs[],
const Datatype & recvtype) const;
virtual void
Alltoall(const void *sendbuf, int sendcount,
const Datatype & sendtype, void *recvbuf,
int recvcount, const Datatype & recvtype) const;
virtual void
Alltoallv(const void *sendbuf, const int sendcounts[],
const int sdispls[], const Datatype & sendtype,
void *recvbuf, const int recvcounts[],
const int rdispls[], const Datatype & recvtype) const;
virtual void
Alltoallw(const void *sendbuf, const int sendcounts[],
const int sdispls[], const Datatype sendtypes[],
void *recvbuf, const int recvcounts[],
const int rdispls[], const Datatype recvtypes[]) const;
virtual void
Reduce(const void *sendbuf, void *recvbuf, int count,
const Datatype & datatype, const Op & op,
int root) const;
virtual void
Allreduce(const void *sendbuf, void *recvbuf, int count,
const Datatype & datatype, const Op & op) const;
virtual void
Reduce_scatter(const void *sendbuf, void *recvbuf,
int recvcounts[],
const Datatype & datatype,
const Op & op) const;
//
// Process Creation
//
virtual void Disconnect();
static Intercomm Get_parent();
static Intercomm Join(const int fd);
//
// External Interfaces
//
virtual void Get_name(char * comm_name, int& resultlen) const;
virtual void Set_name(const char* comm_name);
//
// Process Topologies
//
virtual int Get_topology() const;
//
// Environmental Inquiry
//
virtual void Abort(int errorcode);
//
// Errhandler
//
virtual void Set_errhandler(const Errhandler& errhandler);
virtual Errhandler Get_errhandler() const;
//JGS took out const below from fn arg
static Errhandler Create_errhandler(Comm::Errhandler_fn* function);
//
// Keys and Attributes
//
Fixes trac:817 The C++ bindings were not tracking keyvals properly -- they were freeing some internal meta data when Free_keyval() was called, not when the keyval was actually destroyed (keyvals are refcounted in the C layer, just like all other MPI objects, because they can live for long after their corresponding Free call is invoked). This commit fixes this problem and several other things: * Add infrastructure on the ompi_attribute_keyval_t for an "extra" destructor pointer that will be invoked during the "real" constructor (i.e., when OBJ_RELEASE puts the refcount to 0). This allows calling back into the C++ layer to release meta data associated with the keyval. * Adjust all cases where keyvals are created to pass in relevant destructors (NULL or the C++ destructor). * Do essentially the same for MPI::Comm, MPI::Win, and MPI:Datatype: * Move several functions out of the .cc file into the _inln.h file since they no longer require locks * Make the 4 Create_keyval() functions call a common back-end keyval creation function that does the Right Thing depending on whether C or C++ function pointers were used for the keyval functions. The back-end function does not call the corresponding C MPI_*_create_keyval function, but rather does the work itself so that it can associate a "destructor" callback for the C++ bindings for when the keyval is actually destroyed. * Change a few type names to be more indicative of what they are (mostly dealing with keyvals [not "keys"]). * Add the 3 missing bindings for MPI::Comm::Create_keyval(). * Remove MPI::Comm::comm_map (and associated types) because it's no longer necessary in the intercepts -- it was a by-product of being a portable C++ bindings layer. Now we can just query the C layer directly to figure out what type a communicator is. This solves some logistics / callback issues, too. * Rename several types, variables, and fix many comments in the back-end C attribute implementation to make the names really reflect what they are (keyvals vs. attributes). The previous names heavily overloaded the name "key" and were ''extremely'' confusing. This commit was SVN r13565. The following Trac tickets were found above: Ticket 817 --> https://svn.open-mpi.org/trac/ompi/ticket/817
2007-02-09 02:50:04 +03:00
// Need 4 overloaded versions of this function because per the
// MPI-2 spec, you can mix-n-match the C predefined functions with
// C++ functions.
static int Create_keyval(Copy_attr_function* comm_copy_attr_fn,
Fixes trac:817 The C++ bindings were not tracking keyvals properly -- they were freeing some internal meta data when Free_keyval() was called, not when the keyval was actually destroyed (keyvals are refcounted in the C layer, just like all other MPI objects, because they can live for long after their corresponding Free call is invoked). This commit fixes this problem and several other things: * Add infrastructure on the ompi_attribute_keyval_t for an "extra" destructor pointer that will be invoked during the "real" constructor (i.e., when OBJ_RELEASE puts the refcount to 0). This allows calling back into the C++ layer to release meta data associated with the keyval. * Adjust all cases where keyvals are created to pass in relevant destructors (NULL or the C++ destructor). * Do essentially the same for MPI::Comm, MPI::Win, and MPI:Datatype: * Move several functions out of the .cc file into the _inln.h file since they no longer require locks * Make the 4 Create_keyval() functions call a common back-end keyval creation function that does the Right Thing depending on whether C or C++ function pointers were used for the keyval functions. The back-end function does not call the corresponding C MPI_*_create_keyval function, but rather does the work itself so that it can associate a "destructor" callback for the C++ bindings for when the keyval is actually destroyed. * Change a few type names to be more indicative of what they are (mostly dealing with keyvals [not "keys"]). * Add the 3 missing bindings for MPI::Comm::Create_keyval(). * Remove MPI::Comm::comm_map (and associated types) because it's no longer necessary in the intercepts -- it was a by-product of being a portable C++ bindings layer. Now we can just query the C layer directly to figure out what type a communicator is. This solves some logistics / callback issues, too. * Rename several types, variables, and fix many comments in the back-end C attribute implementation to make the names really reflect what they are (keyvals vs. attributes). The previous names heavily overloaded the name "key" and were ''extremely'' confusing. This commit was SVN r13565. The following Trac tickets were found above: Ticket 817 --> https://svn.open-mpi.org/trac/ompi/ticket/817
2007-02-09 02:50:04 +03:00
Delete_attr_function* comm_delete_attr_fn,
void* extra_state);
static int Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
MPI_Comm_delete_attr_function* comm_delete_attr_fn,
void* extra_state);
static int Create_keyval(Copy_attr_function* comm_copy_attr_fn,
MPI_Comm_delete_attr_function* comm_delete_attr_fn,
void* extra_state);
static int Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
Delete_attr_function* comm_delete_attr_fn,
void* extra_state);
protected:
static int do_create_keyval(MPI_Comm_copy_attr_function* c_copy_fn,
MPI_Comm_delete_attr_function* c_delete_fn,
Copy_attr_function* cxx_copy_fn,
Delete_attr_function* cxx_delete_fn,
void* extra_state);
public:
static void Free_keyval(int& comm_keyval);
virtual void Set_attr(int comm_keyval, const void* attribute_val) const;
virtual bool Get_attr(int comm_keyval, void* attribute_val) const;
virtual void Delete_attr(int comm_keyval);
static int NULL_COPY_FN(const Comm& oldcomm, int comm_keyval,
void* extra_state, void* attribute_val_in,
void* attribute_val_out, bool& flag);
static int DUP_FN(const Comm& oldcomm, int comm_keyval,
void* extra_state, void* attribute_val_in,
void* attribute_val_out, bool& flag);
static int NULL_DELETE_FN(Comm& comm, int comm_keyval, void* attribute_val,
void* extra_state);
private:
#if 0 /* OMPI_ENABLE_MPI_PROFILING */
PMPI::Comm pmpi_comm;
#endif
#if ! 0 /* OMPI_ENABLE_MPI_PROFILING */
public: // JGS hmmm, these used by errhandler_intercept
// should make it a friend
Errhandler* my_errhandler;
typedef ::std::map<MPI_Comm, Comm*> mpi_comm_err_map_t;
static mpi_comm_err_map_t mpi_comm_err_map;
Fixes trac:817 The C++ bindings were not tracking keyvals properly -- they were freeing some internal meta data when Free_keyval() was called, not when the keyval was actually destroyed (keyvals are refcounted in the C layer, just like all other MPI objects, because they can live for long after their corresponding Free call is invoked). This commit fixes this problem and several other things: * Add infrastructure on the ompi_attribute_keyval_t for an "extra" destructor pointer that will be invoked during the "real" constructor (i.e., when OBJ_RELEASE puts the refcount to 0). This allows calling back into the C++ layer to release meta data associated with the keyval. * Adjust all cases where keyvals are created to pass in relevant destructors (NULL or the C++ destructor). * Do essentially the same for MPI::Comm, MPI::Win, and MPI:Datatype: * Move several functions out of the .cc file into the _inln.h file since they no longer require locks * Make the 4 Create_keyval() functions call a common back-end keyval creation function that does the Right Thing depending on whether C or C++ function pointers were used for the keyval functions. The back-end function does not call the corresponding C MPI_*_create_keyval function, but rather does the work itself so that it can associate a "destructor" callback for the C++ bindings for when the keyval is actually destroyed. * Change a few type names to be more indicative of what they are (mostly dealing with keyvals [not "keys"]). * Add the 3 missing bindings for MPI::Comm::Create_keyval(). * Remove MPI::Comm::comm_map (and associated types) because it's no longer necessary in the intercepts -- it was a by-product of being a portable C++ bindings layer. Now we can just query the C layer directly to figure out what type a communicator is. This solves some logistics / callback issues, too. * Rename several types, variables, and fix many comments in the back-end C attribute implementation to make the names really reflect what they are (keyvals vs. attributes). The previous names heavily overloaded the name "key" and were ''extremely'' confusing. This commit was SVN r13565. The following Trac tickets were found above: Ticket 817 --> https://svn.open-mpi.org/trac/ompi/ticket/817
2007-02-09 02:50:04 +03:00
typedef ::std::pair<Comm::_MPI2CPP_COPYATTRFN_*, Comm::_MPI2CPP_DELETEATTRFN_*> keyval_pair_t;
typedef ::std::map<int, keyval_pair_t*> mpi_comm_keyval_fn_map_t;
static mpi_comm_keyval_fn_map_t mpi_comm_keyval_fn_map;
void init() {
my_errhandler = (Errhandler*)0;
}
#endif
};