@@ -69,6 +69,21 @@ namespace dftfe
6969 std::shared_ptr<const MPIPatternP2P<memorySpace>> mpiPatternP2P,
7070 const dftfe::uInt blockSize);
7171
72+ /*
73+ * @Brief Completes any non-blocking communication that was started
74+ * (through one of the *Begin() calls) but never finished (through the
75+ * matching *End() call), and reports it on std::cerr. Such an operation
76+ * would otherwise leak its MPI_Request objects, which are drawn from a
77+ * finite pool inside the MPI implementation.
78+ *
79+ * @note This reports rather than throws. A destructor is implicitly
80+ * noexcept, and more importantly it is routinely run while another
81+ * exception is unwinding the stack, where a second exception would
82+ * call std::terminate and discard the original error. The unmatched
83+ * Begin()/End() itself is caught by the checks in those functions.
84+ */
85+ ~MPICommunicatorP2P ();
86+
7287 void
7388 updateGhostValues (MemoryStorage<ValueType, memorySpace> &dataArray,
7489 const dftfe::uInt communicationChannel = 0 );
@@ -124,6 +139,20 @@ namespace dftfe
124139 void
125140 setCompressBitsPerValue (dftfe::uInt bpv);
126141
142+ private:
143+ /*
144+ * @Brief Helper used by the destructor. If \p inFlight is true, waits
145+ * on \p requests so that the MPI_Request objects are returned to the
146+ * MPI implementation, and reports the unmatched Begin() on \p opName
147+ * to std::cerr.
148+ */
149+ void
150+ reclaimPendingRequests (bool &inFlight,
151+ std::vector<MPI_Request> &requests,
152+ const std::string &opName);
153+
154+
155+
127156 private:
128157 std::shared_ptr<const MPIPatternP2P<memorySpace>> d_mpiPatternP2P;
129158
@@ -207,6 +236,17 @@ namespace dftfe
207236 std::vector<MPI_Request> d_requestsAccumulateInsertLocallyOwned;
208237 MPI_Comm d_mpiCommunicator;
209238
239+ /*
240+ * Each of the three operations owns a single set of MPI_Request
241+ * handles, which is reused across communication channels. Starting an
242+ * operation while a previous one is still in flight would silently
243+ * overwrite (and thereby leak) the outstanding handles, so the flags
244+ * below track the Begin()/End() pairing and are asserted on.
245+ */
246+ bool d_updateGhostValuesInFlight;
247+ bool d_accumulateAddLocallyOwnedInFlight;
248+ bool d_accumulateInsertLocallyOwnedInFlight;
249+
210250 communicationProtocol d_commProtocol;
211251 communicationPrecision d_commPrecision;
212252 };
0 commit comments