1 // -*- c++ -*-
2 //
3 // Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
4 //                         University Research and Technology
5 //                         Corporation.  All rights reserved.
6 // Copyright (c) 2004-2005 The University of Tennessee and The University
7 //                         of Tennessee Research Foundation.  All rights
8 //                         reserved.
9 // Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10 //                         University of Stuttgart.  All rights reserved.
11 // Copyright (c) 2004-2005 The Regents of the University of California.
12 //                         All rights reserved.
13 // Copyright (c) 2007-2016 Cisco Systems, Inc.  All rights reserved.
14 // Copyright (c) 2011      FUJITSU LIMITED.  All rights reserved.
15 // $COPYRIGHT$
16 //
17 // Additional copyrights may follow
18 //
19 // $HEADER$
20 //
21 
22 //
23 // Point-to-Point
24 //
25 
26 inline void
Send(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)27 MPI::Comm::Send(const void *buf, int count,
28 		const MPI::Datatype & datatype, int dest, int tag) const
29 {
30   (void)MPI_Send(const_cast<void *>(buf), count, datatype, dest, tag, mpi_comm);
31 }
32 
33 inline void
Recv(void * buf,int count,const MPI::Datatype & datatype,int source,int tag,MPI::Status & status)34 MPI::Comm::Recv(void *buf, int count, const MPI::Datatype & datatype,
35 		int source, int tag, MPI::Status & status) const
36 {
37   (void)MPI_Recv(buf, count, datatype, source, tag, mpi_comm, &status.mpi_status);
38 }
39 
40 inline void
Recv(void * buf,int count,const MPI::Datatype & datatype,int source,int tag)41 MPI::Comm::Recv(void *buf, int count, const MPI::Datatype & datatype,
42 				    int source, int tag) const
43 {
44   (void)MPI_Recv(buf, count, datatype, source,
45 		 tag, mpi_comm, MPI_STATUS_IGNORE);
46 }
47 
48 inline void
Bsend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)49 MPI::Comm::Bsend(const void *buf, int count,
50 		 const MPI::Datatype & datatype, int dest, int tag) const
51 {
52   (void)MPI_Bsend(const_cast<void *>(buf), count, datatype,
53 		  dest, tag, mpi_comm);
54 }
55 
56 inline void
Ssend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)57 MPI::Comm::Ssend(const void *buf, int count,
58 		 const MPI::Datatype & datatype, int dest, int tag) const
59 {
60   (void)MPI_Ssend(const_cast<void *>(buf), count,  datatype, dest,
61 		  tag, mpi_comm);
62 }
63 
64 inline void
Rsend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)65 MPI::Comm::Rsend(const void *buf, int count,
66 		 const MPI::Datatype & datatype, int dest, int tag) const
67 {
68   (void)MPI_Rsend(const_cast<void *>(buf), count, datatype,
69 		  dest, tag, mpi_comm);
70 }
71 
72 inline MPI::Request
Isend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)73 MPI::Comm::Isend(const void *buf, int count,
74 		 const MPI::Datatype & datatype, int dest, int tag) const
75 {
76   MPI_Request request;
77   (void)MPI_Isend(const_cast<void *>(buf), count, datatype,
78 		  dest, tag, mpi_comm, &request);
79   return request;
80 }
81 
82 inline MPI::Request
Ibsend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)83 MPI::Comm::Ibsend(const void *buf, int count,
84 		  const MPI::Datatype & datatype, int dest, int tag) const
85 {
86   MPI_Request request;
87   (void)MPI_Ibsend(const_cast<void *>(buf), count, datatype,
88 		   dest, tag, mpi_comm, &request);
89   return request;
90 }
91 
92 inline MPI::Request
Issend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)93 MPI::Comm::Issend(const void *buf, int count,
94 		  const MPI::Datatype & datatype, int dest, int tag) const
95 {
96   MPI_Request request;
97   (void)MPI_Issend(const_cast<void *>(buf), count, datatype,
98 		   dest, tag, mpi_comm, &request);
99   return request;
100 }
101 
102 inline MPI::Request
Irsend(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)103 MPI::Comm::Irsend(const void *buf, int count,
104 		  const MPI::Datatype & datatype, int dest, int tag) const
105 {
106   MPI_Request request;
107   (void)MPI_Irsend(const_cast<void *>(buf), count, datatype,
108 		   dest, tag, mpi_comm, &request);
109   return request;
110 }
111 
112 inline MPI::Request
Irecv(void * buf,int count,const MPI::Datatype & datatype,int source,int tag)113 MPI::Comm::Irecv(void *buf, int count,
114 		 const MPI::Datatype & datatype, int source, int tag) const
115 {
116   MPI_Request request;
117   (void)MPI_Irecv(buf, count, datatype, source,
118 		  tag, mpi_comm, &request);
119   return request;
120 }
121 
122 
123 inline bool
Iprobe(int source,int tag,MPI::Status & status)124 MPI::Comm::Iprobe(int source, int tag, MPI::Status & status) const
125 {
126   int t;
127   (void)MPI_Iprobe(source, tag, mpi_comm, &t, &status.mpi_status);
128   return OPAL_INT_TO_BOOL(t);
129 }
130 
131 inline bool
Iprobe(int source,int tag)132 MPI::Comm::Iprobe(int source, int tag) const
133 {
134   int t;
135   (void)MPI_Iprobe(source, tag, mpi_comm, &t, MPI_STATUS_IGNORE);
136   return OPAL_INT_TO_BOOL(t);
137 }
138 
139 inline void
Probe(int source,int tag,MPI::Status & status)140 MPI::Comm::Probe(int source, int tag, MPI::Status & status) const
141 {
142   (void)MPI_Probe(source, tag, mpi_comm, &status.mpi_status);
143 }
144 
145 inline void
Probe(int source,int tag)146 MPI::Comm::Probe(int source, int tag) const
147 {
148   (void)MPI_Probe(source, tag, mpi_comm, MPI_STATUS_IGNORE);
149 }
150 
151 inline MPI::Prequest
Send_init(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)152 MPI::Comm::Send_init(const void *buf, int count,
153 		     const MPI::Datatype & datatype, int dest, int tag) const
154 {
155   MPI_Request request;
156   (void)MPI_Send_init(const_cast<void *>(buf), count, datatype,
157 		      dest, tag, mpi_comm, &request);
158   return request;
159 }
160 
161 inline MPI::Prequest
Bsend_init(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)162 MPI::Comm::Bsend_init(const void *buf, int count,
163 		      const MPI::Datatype & datatype, int dest, int tag) const
164 {
165   MPI_Request request;
166   (void)MPI_Bsend_init(const_cast<void *>(buf), count, datatype,
167 		       dest, tag, mpi_comm, &request);
168   return request;
169 }
170 
171 inline MPI::Prequest
Ssend_init(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)172 MPI::Comm::Ssend_init(const void *buf, int count,
173 		      const MPI::Datatype & datatype, int dest, int tag) const
174 {
175   MPI_Request request;
176   (void)MPI_Ssend_init(const_cast<void *>(buf), count, datatype,
177 		       dest, tag, mpi_comm, &request);
178   return request;
179 }
180 
181 inline MPI::Prequest
Rsend_init(const void * buf,int count,const MPI::Datatype & datatype,int dest,int tag)182 MPI::Comm::Rsend_init(const void *buf, int count,
183 		      const MPI::Datatype & datatype, int dest, int tag) const
184 {
185   MPI_Request request;
186   (void)MPI_Rsend_init(const_cast<void *>(buf), count,  datatype,
187 		       dest, tag, mpi_comm, &request);
188   return request;
189 }
190 
191 inline MPI::Prequest
Recv_init(void * buf,int count,const MPI::Datatype & datatype,int source,int tag)192 MPI::Comm::Recv_init(void *buf, int count,
193 		     const MPI::Datatype & datatype, int source, int tag) const
194 {
195   MPI_Request request;
196   (void)MPI_Recv_init(buf, count, datatype, source,
197 		      tag, mpi_comm, &request);
198   return request;
199 }
200 
201 inline void
Sendrecv(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,int dest,int sendtag,void * recvbuf,int recvcount,const MPI::Datatype & recvtype,int source,int recvtag,MPI::Status & status)202 MPI::Comm::Sendrecv(const void *sendbuf, int sendcount,
203 		    const MPI::Datatype & sendtype, int dest, int sendtag,
204 		    void *recvbuf, int recvcount,
205 		    const MPI::Datatype & recvtype, int source,
206 		    int recvtag, MPI::Status & status) const
207 {
208   (void)MPI_Sendrecv(const_cast<void *>(sendbuf), sendcount,
209 		     sendtype,
210 		     dest, sendtag, recvbuf, recvcount,
211 		     recvtype,
212 		     source, recvtag, mpi_comm, &status.mpi_status);
213 }
214 
215 inline void
Sendrecv(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,int dest,int sendtag,void * recvbuf,int recvcount,const MPI::Datatype & recvtype,int source,int recvtag)216 MPI::Comm::Sendrecv(const void *sendbuf, int sendcount,
217 		    const MPI::Datatype & sendtype, int dest, int sendtag,
218 		    void *recvbuf, int recvcount,
219 		    const MPI::Datatype & recvtype, int source,
220 		    int recvtag) const
221 {
222   (void)MPI_Sendrecv(const_cast<void *>(sendbuf), sendcount,
223 		     sendtype,
224 		     dest, sendtag, recvbuf, recvcount,
225 		     recvtype,
226 		     source, recvtag, mpi_comm, MPI_STATUS_IGNORE);
227 }
228 
229 inline void
Sendrecv_replace(void * buf,int count,const MPI::Datatype & datatype,int dest,int sendtag,int source,int recvtag,MPI::Status & status)230 MPI::Comm::Sendrecv_replace(void *buf, int count,
231 			    const MPI::Datatype & datatype, int dest,
232 			    int sendtag, int source,
233 			    int recvtag, MPI::Status & status) const
234 {
235   (void)MPI_Sendrecv_replace(buf, count, datatype, dest,
236 			     sendtag, source, recvtag, mpi_comm,
237 			     &status.mpi_status);
238 }
239 
240 inline void
Sendrecv_replace(void * buf,int count,const MPI::Datatype & datatype,int dest,int sendtag,int source,int recvtag)241 MPI::Comm::Sendrecv_replace(void *buf, int count,
242 			    const MPI::Datatype & datatype, int dest,
243 			    int sendtag, int source,
244 			    int recvtag) const
245 {
246   (void)MPI_Sendrecv_replace(buf, count, datatype, dest,
247 			     sendtag, source, recvtag, mpi_comm,
248 			     MPI_STATUS_IGNORE);
249 }
250 
251 //
252 // Groups, Contexts, and Communicators
253 //
254 
255 inline MPI::Group
Get_group()256 MPI::Comm::Get_group() const
257 {
258   MPI_Group group;
259   (void)MPI_Comm_group(mpi_comm, &group);
260   return group;
261 }
262 
263 inline int
Get_size()264 MPI::Comm::Get_size() const
265 {
266   int size;
267   (void)MPI_Comm_size (mpi_comm, &size);
268   return size;
269 }
270 
271 inline int
Get_rank()272 MPI::Comm::Get_rank() const
273 {
274   int myrank;
275   (void)MPI_Comm_rank (mpi_comm, &myrank);
276   return myrank;
277 }
278 
279 inline int
Compare(const MPI::Comm & comm1,const MPI::Comm & comm2)280 MPI::Comm::Compare(const MPI::Comm & comm1,
281 		   const MPI::Comm & comm2)
282 {
283   int result;
284   (void)MPI_Comm_compare(comm1, comm2, &result);
285   return result;
286 }
287 
288 inline void
Free(void)289 MPI::Comm::Free(void)
290 {
291     (void)MPI_Comm_free(&mpi_comm);
292 }
293 
294 inline bool
Is_inter()295 MPI::Comm::Is_inter() const
296 {
297   int t;
298   (void)MPI_Comm_test_inter(mpi_comm, &t);
299   return OPAL_INT_TO_BOOL(t);
300 }
301 
302 
303 //
304 // Collective Communication
305 //
306 
307 inline void
Barrier()308 MPI::Comm::Barrier() const
309 {
310     (void)MPI_Barrier(mpi_comm);
311 }
312 
313 inline void
Bcast(void * buffer,int count,const MPI::Datatype & datatype,int root)314 MPI::Comm::Bcast(void *buffer, int count,
315                  const MPI::Datatype& datatype, int root) const
316 {
317     (void)MPI_Bcast(buffer, count, datatype, root, mpi_comm);
318 }
319 
320 inline void
Gather(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,void * recvbuf,int recvcount,const MPI::Datatype & recvtype,int root)321 MPI::Comm::Gather(const void *sendbuf, int sendcount,
322                   const MPI::Datatype & sendtype,
323                   void *recvbuf, int recvcount,
324                   const MPI::Datatype & recvtype, int root) const
325 {
326     (void)MPI_Gather(const_cast<void *>(sendbuf), sendcount, sendtype,
327                      recvbuf, recvcount, recvtype, root, mpi_comm);
328 }
329 
330 inline void
Gatherv(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,void * recvbuf,const int recvcounts[],const int displs[],const MPI::Datatype & recvtype,int root)331 MPI::Comm::Gatherv(const void *sendbuf, int sendcount,
332                    const MPI::Datatype & sendtype, void *recvbuf,
333                    const int recvcounts[], const int displs[],
334                    const MPI::Datatype & recvtype, int root) const
335 {
336     (void)MPI_Gatherv(const_cast<void *>(sendbuf), sendcount,  sendtype,
337                       recvbuf, const_cast<int *>(recvcounts),
338                       const_cast<int *>(displs),
339                       recvtype, root, mpi_comm);
340 }
341 
342 inline void
Scatter(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,void * recvbuf,int recvcount,const MPI::Datatype & recvtype,int root)343 MPI::Comm::Scatter(const void *sendbuf, int sendcount,
344                    const MPI::Datatype & sendtype,
345                    void *recvbuf, int recvcount,
346                    const MPI::Datatype & recvtype, int root) const
347 {
348     (void)MPI_Scatter(const_cast<void *>(sendbuf), sendcount, sendtype,
349                       recvbuf, recvcount, recvtype, root, mpi_comm);
350 }
351 
352 inline void
Scatterv(const void * sendbuf,const int sendcounts[],const int displs[],const MPI::Datatype & sendtype,void * recvbuf,int recvcount,const MPI::Datatype & recvtype,int root)353 MPI::Comm::Scatterv(const void *sendbuf, const int sendcounts[],
354                     const int displs[], const MPI::Datatype & sendtype,
355                     void *recvbuf, int recvcount,
356                     const MPI::Datatype & recvtype, int root) const
357 {
358     (void)MPI_Scatterv(const_cast<void *>(sendbuf),
359                        const_cast<int *>(sendcounts),
360                        const_cast<int *>(displs), sendtype,
361                        recvbuf, recvcount, recvtype,
362                        root, mpi_comm);
363 }
364 
365 inline void
Allgather(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,void * recvbuf,int recvcount,const MPI::Datatype & recvtype)366 MPI::Comm::Allgather(const void *sendbuf, int sendcount,
367                      const MPI::Datatype & sendtype, void *recvbuf,
368                      int recvcount, const MPI::Datatype & recvtype) const
369 {
370     (void)MPI_Allgather(const_cast<void *>(sendbuf), sendcount,
371                         sendtype, recvbuf, recvcount,
372                         recvtype, mpi_comm);
373 }
374 
375 inline void
Allgatherv(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,void * recvbuf,const int recvcounts[],const int displs[],const MPI::Datatype & recvtype)376 MPI::Comm::Allgatherv(const void *sendbuf, int sendcount,
377                       const MPI::Datatype & sendtype, void *recvbuf,
378                       const int recvcounts[], const int displs[],
379                       const MPI::Datatype & recvtype) const
380 {
381     (void)MPI_Allgatherv(const_cast<void *>(sendbuf), sendcount,
382                          sendtype, recvbuf,
383                          const_cast<int *>(recvcounts),
384                          const_cast<int *>(displs),
385                          recvtype, mpi_comm);
386 }
387 
388 inline void
Alltoall(const void * sendbuf,int sendcount,const MPI::Datatype & sendtype,void * recvbuf,int recvcount,const MPI::Datatype & recvtype)389 MPI::Comm::Alltoall(const void *sendbuf, int sendcount,
390                     const MPI::Datatype & sendtype, void *recvbuf,
391                     int recvcount, const MPI::Datatype & recvtype) const
392 {
393     (void)MPI_Alltoall(const_cast<void *>(sendbuf), sendcount,
394                        sendtype, recvbuf, recvcount,
395                        recvtype, mpi_comm);
396 }
397 
398 inline void
Alltoallv(const void * sendbuf,const int sendcounts[],const int sdispls[],const MPI::Datatype & sendtype,void * recvbuf,const int recvcounts[],const int rdispls[],const MPI::Datatype & recvtype)399 MPI::Comm::Alltoallv(const void *sendbuf, const int sendcounts[],
400                      const int sdispls[], const MPI::Datatype & sendtype,
401                      void *recvbuf, const int recvcounts[],
402                      const int rdispls[],
403                      const MPI::Datatype & recvtype) const
404 {
405     (void)MPI_Alltoallv(const_cast<void *>(sendbuf),
406                         const_cast<int *>(sendcounts),
407 			const_cast<int *>(sdispls), sendtype, recvbuf,
408 			const_cast<int *>(recvcounts),
409                         const_cast<int *>(rdispls),
410 			recvtype,mpi_comm);
411 }
412 
413 inline void
Alltoallw(const void * sendbuf,const int sendcounts[],const int sdispls[],const MPI::Datatype sendtypes[],void * recvbuf,const int recvcounts[],const int rdispls[],const MPI::Datatype recvtypes[])414 MPI::Comm::Alltoallw(const void *sendbuf, const int sendcounts[],
415                      const int sdispls[], const MPI::Datatype sendtypes[],
416                      void *recvbuf, const int recvcounts[],
417                      const int rdispls[],
418                      const MPI::Datatype recvtypes[]) const
419 {
420     const int comm_size = Get_size();
421     MPI_Datatype *const data_type_tbl = new MPI_Datatype [2*comm_size];
422 
423     // This must be done because MPI::Datatype arrays cannot be
424     // converted directly into MPI_Datatype arrays.
425     for (int i_rank=0; i_rank < comm_size; i_rank++) {
426         data_type_tbl[i_rank] = sendtypes[i_rank];
427         data_type_tbl[i_rank + comm_size] = recvtypes[i_rank];
428     }
429 
430     (void)MPI_Alltoallw(const_cast<void *>(sendbuf),
431                         const_cast<int *>(sendcounts),
432                         const_cast<int *>(sdispls),
433                         data_type_tbl, recvbuf,
434                         const_cast<int *>(recvcounts),
435                         const_cast<int *>(rdispls),
436                         &data_type_tbl[comm_size], mpi_comm);
437 
438     delete[] data_type_tbl;
439 }
440 
441 inline void
Reduce(const void * sendbuf,void * recvbuf,int count,const MPI::Datatype & datatype,const MPI::Op & op,int root)442 MPI::Comm::Reduce(const void *sendbuf, void *recvbuf, int count,
443                   const MPI::Datatype & datatype, const MPI::Op& op,
444                   int root) const
445 {
446     (void)MPI_Reduce(const_cast<void *>(sendbuf), recvbuf, count, datatype, op, root, mpi_comm);
447 }
448 
449 inline void
Allreduce(const void * sendbuf,void * recvbuf,int count,const MPI::Datatype & datatype,const MPI::Op & op)450 MPI::Comm::Allreduce(const void *sendbuf, void *recvbuf, int count,
451                      const MPI::Datatype & datatype, const MPI::Op& op) const
452 {
453     (void)MPI_Allreduce (const_cast<void *>(sendbuf), recvbuf, count, datatype,  op, mpi_comm);
454 }
455 
456 inline void
Reduce_scatter(const void * sendbuf,void * recvbuf,int recvcounts[],const MPI::Datatype & datatype,const MPI::Op & op)457 MPI::Comm::Reduce_scatter(const void *sendbuf, void *recvbuf,
458                           int recvcounts[],
459                           const MPI::Datatype & datatype,
460                           const MPI::Op& op) const
461 {
462     (void)MPI_Reduce_scatter(const_cast<void *>(sendbuf), recvbuf, recvcounts,
463                              datatype, op, mpi_comm);
464 }
465 
466 //
467 // Process Creation and Managemnt
468 //
469 
470 inline void
Disconnect()471 MPI::Comm::Disconnect()
472 {
473   (void) MPI_Comm_disconnect(&mpi_comm);
474 }
475 
476 
477 inline MPI::Intercomm
Get_parent()478 MPI::Comm::Get_parent()
479 {
480   MPI_Comm parent;
481   MPI_Comm_get_parent(&parent);
482   return parent;
483 }
484 
485 
486 inline MPI::Intercomm
Join(const int fd)487 MPI::Comm::Join(const int fd)
488 {
489   MPI_Comm newcomm;
490   (void) MPI_Comm_join((int) fd, &newcomm);
491   return newcomm;
492 }
493 
494 //
495 // External Interfaces
496 //
497 
498 inline void
Get_name(char * comm_name,int & resultlen)499 MPI::Comm::Get_name(char* comm_name, int& resultlen) const
500 {
501   (void) MPI_Comm_get_name(mpi_comm, comm_name, &resultlen);
502 }
503 
504 inline void
Set_name(const char * comm_name)505 MPI::Comm::Set_name(const char* comm_name)
506 {
507   (void) MPI_Comm_set_name(mpi_comm, const_cast<char *>(comm_name));
508 }
509 
510 //
511 //Process Topologies
512 //
513 
514 inline int
Get_topology()515 MPI::Comm::Get_topology() const
516 {
517   int status;
518   (void)MPI_Topo_test(mpi_comm, &status);
519   return status;
520 }
521 
522 //
523 // Environmental Inquiry
524 //
525 
526 inline void
Abort(int errorcode)527 MPI::Comm::Abort(int errorcode)
528 {
529   (void)MPI_Abort(mpi_comm, errorcode);
530 }
531 
532 //
533 //  These C++ bindings are for MPI-2.
534 //  The MPI-1.2 functions called below are all
535 //  going to be deprecated and replaced in MPI-2.
536 //
537 
538 inline MPI::Errhandler
Get_errhandler()539 MPI::Comm::Get_errhandler() const
540 {
541     MPI_Errhandler errhandler;
542     MPI_Comm_get_errhandler(mpi_comm, &errhandler);
543     return errhandler;
544 }
545 
546 inline void
Set_errhandler(const MPI::Errhandler & errhandler)547 MPI::Comm::Set_errhandler(const MPI::Errhandler& errhandler)
548 {
549     (void)MPI_Comm_set_errhandler(mpi_comm, errhandler);
550 }
551 
552 inline void
Call_errhandler(int errorcode)553 MPI::Comm::Call_errhandler(int errorcode) const
554 {
555   (void) MPI_Comm_call_errhandler(mpi_comm, errorcode);
556 }
557 
558 // 1) original Create_keyval that takes the first 2 arguments as C++
559 //    functions
560 inline int
Create_keyval(MPI::Comm::Copy_attr_function * comm_copy_attr_fn,MPI::Comm::Delete_attr_function * comm_delete_attr_fn,void * extra_state)561 MPI::Comm::Create_keyval(MPI::Comm::Copy_attr_function* comm_copy_attr_fn,
562                          MPI::Comm::Delete_attr_function* comm_delete_attr_fn,
563                          void* extra_state)
564 {
565     // Back-end function does the heavy lifting
566     int ret, keyval;
567     ret = do_create_keyval(NULL, NULL,
568                            comm_copy_attr_fn, comm_delete_attr_fn,
569                            extra_state, keyval);
570     return (MPI_SUCCESS == ret) ? keyval : ret;
571 }
572 
573 // 2) overload Create_keyval to take the first 2 arguments as C
574 //    functions
575 inline int
Create_keyval(MPI_Comm_copy_attr_function * comm_copy_attr_fn,MPI_Comm_delete_attr_function * comm_delete_attr_fn,void * extra_state)576 MPI::Comm::Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
577                          MPI_Comm_delete_attr_function* comm_delete_attr_fn,
578                          void* extra_state)
579 {
580     // Back-end function does the heavy lifting
581     int ret, keyval;
582     ret = do_create_keyval(comm_copy_attr_fn, comm_delete_attr_fn,
583                            NULL, NULL,
584                            extra_state, keyval);
585     return (MPI_SUCCESS == ret) ? keyval : ret;
586 }
587 
588 // 3) overload Create_keyval to take the first 2 arguments as C++ & C
589 //    functions
590 inline int
Create_keyval(MPI::Comm::Copy_attr_function * comm_copy_attr_fn,MPI_Comm_delete_attr_function * comm_delete_attr_fn,void * extra_state)591 MPI::Comm::Create_keyval(MPI::Comm::Copy_attr_function* comm_copy_attr_fn,
592                          MPI_Comm_delete_attr_function* comm_delete_attr_fn,
593                          void* extra_state)
594 {
595     // Back-end function does the heavy lifting
596     int ret, keyval;
597     ret = do_create_keyval(NULL, comm_delete_attr_fn,
598                            comm_copy_attr_fn, NULL,
599                            extra_state, keyval);
600     return (MPI_SUCCESS == ret) ? keyval : ret;
601 }
602 
603 // 4) overload Create_keyval to take the first 2 arguments as C & C++
604 //    functions
605 inline int
Create_keyval(MPI_Comm_copy_attr_function * comm_copy_attr_fn,MPI::Comm::Delete_attr_function * comm_delete_attr_fn,void * extra_state)606 MPI::Comm::Create_keyval(MPI_Comm_copy_attr_function* comm_copy_attr_fn,
607                          MPI::Comm::Delete_attr_function* comm_delete_attr_fn,
608                          void* extra_state)
609 {
610     // Back-end function does the heavy lifting
611     int ret, keyval;
612     ret = do_create_keyval(comm_copy_attr_fn, NULL,
613                            NULL, comm_delete_attr_fn,
614                            extra_state, keyval);
615     return (MPI_SUCCESS == ret) ? keyval : ret;
616 }
617 
618 inline void
Free_keyval(int & comm_keyval)619 MPI::Comm::Free_keyval(int& comm_keyval)
620 {
621     (void) MPI_Comm_free_keyval(&comm_keyval);
622 }
623 
624 inline void
Set_attr(int comm_keyval,const void * attribute_val)625 MPI::Comm::Set_attr(int comm_keyval, const void* attribute_val) const
626 {
627     (void)MPI_Comm_set_attr(mpi_comm, comm_keyval, const_cast<void*>(attribute_val));
628 }
629 
630 inline bool
Get_attr(int comm_keyval,void * attribute_val)631 MPI::Comm::Get_attr(int comm_keyval, void* attribute_val) const
632 {
633   int flag;
634   (void)MPI_Comm_get_attr(mpi_comm, comm_keyval, attribute_val, &flag);
635   return OPAL_INT_TO_BOOL(flag);
636 }
637 
638 inline void
Delete_attr(int comm_keyval)639 MPI::Comm::Delete_attr(int comm_keyval)
640 {
641   (void)MPI_Comm_delete_attr(mpi_comm, comm_keyval);
642 }
643 
644 // Comment out the unused parameters so that compilers don't warn
645 // about them.  Use comments instead of just deleting the param names
646 // outright so that we know/remember what they are.
647 inline int
NULL_COPY_FN(const MPI::Comm &,int,void *,void *,void *,bool & flag)648 MPI::Comm::NULL_COPY_FN(const MPI::Comm& /* oldcomm */,
649                         int /* comm_keyval */,
650                         void* /* extra_state */,
651                         void* /* attribute_val_in */,
652                         void* /* attribute_val_out */,
653                         bool& flag)
654 {
655     flag = false;
656     return MPI_SUCCESS;
657 }
658 
659 inline int
DUP_FN(const MPI::Comm & oldcomm,int comm_keyval,void * extra_state,void * attribute_val_in,void * attribute_val_out,bool & flag)660 MPI::Comm::DUP_FN(const MPI::Comm& oldcomm, int comm_keyval,
661 			 void* extra_state, void* attribute_val_in,
662 			 void* attribute_val_out, bool& flag)
663 {
664     if (sizeof(bool) != sizeof(int)) {
665         int f = (int)flag;
666         int ret;
667         ret = MPI_COMM_DUP_FN(oldcomm, comm_keyval, extra_state,
668                               attribute_val_in, attribute_val_out, &f);
669         flag = OPAL_INT_TO_BOOL(f);
670         return ret;
671     } else {
672         return MPI_COMM_DUP_FN(oldcomm, comm_keyval, extra_state,
673                                attribute_val_in, attribute_val_out,
674                                (int*)&flag);
675     }
676 }
677 
678 // Comment out the unused parameters so that compilers don't warn
679 // about them.  Use comments instead of just deleting the param names
680 // outright so that we know/remember what they are.
681 inline int
NULL_DELETE_FN(MPI::Comm &,int,void *,void *)682 MPI::Comm::NULL_DELETE_FN(MPI::Comm& /* comm */,
683                           int /* comm_keyval */,
684                           void* /* attribute_val */,
685                           void* /* extra_state */)
686 {
687     return MPI_SUCCESS;
688 }
689 
690