Fenix @develop
 
Loading...
Searching...
No Matches
comm.hpp
1#ifndef FENIX_MPIXX_COMM_HPP
2#define FENIX_MPIXX_COMM_HPP
3
4#include <mpi.h>
5#include <utility>
6
7#include "fenix/mpixx/group.hpp"
8#include "fenix/mpixx/util.hpp"
9
10namespace fenix::mpixx {
11
12// RAII wrapper for MPI_Comm with move-only semantics
13// Owns an MPI_Comm handle and automatically frees it on destruction.
14// Accessors check MPI initialization state and return MPI_COMM_NULL
15// if MPI is not initialized or has been finalized.
16class Comm {
17 public:
18 explicit Comm(MPI_Comm comm) noexcept : comm_(comm) {}
19 Comm() noexcept : Comm(MPI_COMM_NULL) {}
20 virtual ~Comm() { free(); }
21
22 // frees old comm before taking ownership
23 Comm& operator=(Comm&& o);
24 Comm& operator=(MPI_Comm c) { return *this = Comm(c); }
25 Comm(Comm&& o) noexcept { *this = std::move(o); }
26
27 // Disable copy
28 Comm(const Comm&) = delete;
29 Comm& operator=(const Comm&) = delete;
30
31 MPI_Comm get() const noexcept { return mpi_active() ? comm_ : MPI_COMM_NULL; }
32
33 // Implicit conversion to MPI_Comm
34 operator MPI_Comm() const noexcept { return get(); }
35
36 explicit operator bool() const noexcept { return get() != MPI_COMM_NULL; }
37
38 // Release ownership of the communicator without freeing it
39 MPI_Comm release() noexcept;
40
41 // Basic MPI_Comm function overloads
42 int size() const;
43 int rank() const;
44 bool is_revoked() const;
45 int revoke();
46 virtual void free(); // safe even if comm_ is MPI_COMM_NULL
47
48 // Get group associated with this communicator
49 Group group() const;
50
51 // Static versions taking raw MPI_Comm
52 static int size(MPI_Comm comm);
53 static int rank(MPI_Comm comm);
54 static bool is_revoked(MPI_Comm comm);
55 static int revoke(MPI_Comm comm);
56 static Group group(MPI_Comm comm);
57
58 // MPI_Comm creation overloads
59 Comm dup() const;
60 Comm dup_with_info(MPI_Info info) const;
61
62 Comm create(MPI_Group group) const;
63 Comm create_group(MPI_Group group, int tag) const;
64
65 Comm split(int color, int key) const;
66 Comm split_type(int split_type, int key, MPI_Info info) const;
67
68 Comm intercomm_create(
69 int local_leader, MPI_Comm peer_comm, int remote_leader, int tag
70 ) const;
71
72 Comm shrink() const;
73
74 // Static MPI_Comm creation overloads (taking an input comm)
75 static Comm dup(MPI_Comm comm);
76 static Comm dup_with_info(MPI_Comm comm, MPI_Info info);
77
78 static Comm create(MPI_Comm comm, MPI_Group group);
79 static Comm create_group(MPI_Comm comm, MPI_Group group, int tag);
80
81 static Comm split(MPI_Comm comm, int color, int key);
82 static Comm split_type(MPI_Comm comm, int split_type, int key, MPI_Info info);
83
84 static Comm intercomm_create(
85 MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm,
86 int remote_leader, int tag
87 );
88
89 static Comm shrink(MPI_Comm comm);
90
91 private:
92 MPI_Comm comm_ = MPI_COMM_NULL;
93};
94
95// Non-owning reference to an MPI_Comm
96// Does not free the communicator on destruction, only releases ownership.
97// Useful for storing communicators that are owned elsewhere.
98// Unlike Comm, CommRef is copyable since it doesn't own the resource.
99class CommRef : public Comm {
100 public:
101 // Implicit constructor from MPI_Comm
102 CommRef(MPI_Comm comm = MPI_COMM_NULL) : Comm(comm) {}
103
104 // Construct from Comm (non-owning reference)
105 CommRef(const Comm& c) : Comm(c.get()) {}
106
107 // Copy operations (allowed for non-owning reference)
108 CommRef(const CommRef& o) : Comm(o.get()) {}
109 CommRef& operator=(const CommRef& o) {
110 *this = o.get();
111 return *this;
112 }
113
114 // Assign from Comm (non-owning reference)
115 CommRef& operator=(const Comm& c) {
116 *this = c.get();
117 return *this;
118 }
119
120 // Move assignment - release old comm without freeing it
121 CommRef& operator=(CommRef&& o) {
122 if (this != &o) {
123 (void)release(); // Just release the old one, don't free
124 *this = o.release(); // Assign the new comm via operator=(MPI_Comm)
125 }
126 return *this;
127 }
128 CommRef& operator=(MPI_Comm c) {
129 (void)release(); // Just release the old one, don't free
130 // Directly assign to base class via Comm's assignment operator
131 Comm::operator=(Comm(c));
132 return *this;
133 }
134
135 ~CommRef() override { (void)release(); }
136};
137
138} // namespace fenix::mpixx
139
140#endif // FENIX_MPIXX_COMM_HPP
Definition comm.hpp:99
Definition comm.hpp:16
Definition group.hpp:21