]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/mpi/src/request.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / mpi / src / request.cpp
1 // Copyright (C) 2006 Douglas Gregor.
2
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 #include <boost/mpi/request.hpp>
7 #include <boost/mpi/status.hpp>
8 #include <boost/mpi/communicator.hpp>
9 #include <boost/mpi/detail/request_handlers.hpp>
10
11 namespace boost { namespace mpi {
12
13 request::request()
14 : m_handler() {}
15
16 void
17 request::preserve(boost::shared_ptr<void> d) {
18 if (!m_preserved) {
19 m_preserved = d;
20 } else {
21 boost::shared_ptr<void> cdr = m_preserved;
22 typedef std::pair<boost::shared_ptr<void>, boost::shared_ptr<void> > cons;
23 boost::shared_ptr<cons> p(new cons(d, cdr));
24 m_preserved = p;
25 }
26 }
27 request request::make_dynamic() { return request(new dynamic_handler()); }
28
29 request
30 request::make_bottom_send(communicator const& comm, int dest, int tag, MPI_Datatype tp) {
31 trivial_handler* handler = new trivial_handler;
32 BOOST_MPI_CHECK_RESULT(MPI_Isend,
33 (MPI_BOTTOM, 1, tp,
34 dest, tag, comm, &handler->m_request));
35 return request(handler);
36 }
37
38 request
39 request::make_empty_send(communicator const& comm, int dest, int tag) {
40 trivial_handler* handler = new trivial_handler;
41 BOOST_MPI_CHECK_RESULT(MPI_Isend,
42 (MPI_BOTTOM, 0, MPI_PACKED,
43 dest, tag, comm, &handler->m_request));
44 return request(handler);
45 }
46
47 request
48 request::make_bottom_recv(communicator const& comm, int dest, int tag, MPI_Datatype tp) {
49 trivial_handler* handler = new trivial_handler;
50 BOOST_MPI_CHECK_RESULT(MPI_Irecv,
51 (MPI_BOTTOM, 1, tp,
52 dest, tag, comm, &handler->m_request));
53 return request(handler);
54 }
55
56 request
57 request::make_empty_recv(communicator const& comm, int dest, int tag) {
58 trivial_handler* handler = new trivial_handler;
59 BOOST_MPI_CHECK_RESULT(MPI_Irecv,
60 (MPI_BOTTOM, 0, MPI_PACKED,
61 dest, tag, comm, &handler->m_request));
62 return request(handler);
63 }
64
65 request
66 request::make_packed_send(communicator const& comm, int dest, int tag, void const* buffer, std::size_t n) {
67 #if defined(BOOST_MPI_USE_IMPROBE)
68 {
69 trivial_handler* handler = new trivial_handler;
70 BOOST_MPI_CHECK_RESULT(MPI_Isend,
71 (const_cast<void*>(buffer), n, MPI_PACKED,
72 dest, tag, comm, &handler->m_request));
73 return request(handler);
74 }
75 #else
76 {
77 dynamic_handler *handler = new dynamic_handler;
78 request req(handler);
79 shared_ptr<std::size_t> size(new std::size_t(n));
80 req.preserve(size);
81 BOOST_MPI_CHECK_RESULT(MPI_Isend,
82 (size.get(), 1,
83 get_mpi_datatype(*size),
84 dest, tag, comm, handler->m_requests));
85 BOOST_MPI_CHECK_RESULT(MPI_Isend,
86 (const_cast<void*>(buffer), *size,
87 MPI_PACKED,
88 dest, tag, comm, handler->m_requests+1));
89 return req;
90 }
91 #endif
92 }
93
94 /***************************************************************************
95 * handlers *
96 ***************************************************************************/
97
98 request::handler::~handler() {}
99
100 optional<MPI_Request&>
101 request::legacy_handler::trivial() {
102 return boost::none;
103 }
104
105 bool
106 request::legacy_handler::active() const {
107 return m_requests[0] != MPI_REQUEST_NULL || m_requests[1] != MPI_REQUEST_NULL;
108 }
109
110 // trivial handler
111
112 request::trivial_handler::trivial_handler()
113 : m_request(MPI_REQUEST_NULL) {}
114
115 status
116 request::trivial_handler::wait()
117 {
118 status result;
119 BOOST_MPI_CHECK_RESULT(MPI_Wait, (&m_request, &result.m_status));
120 return result;
121 }
122
123
124 optional<status>
125 request::trivial_handler::test()
126 {
127 status result;
128 int flag = 0;
129 BOOST_MPI_CHECK_RESULT(MPI_Test,
130 (&m_request, &flag, &result.m_status));
131 return flag != 0? optional<status>(result) : optional<status>();
132 }
133
134 void
135 request::trivial_handler::cancel()
136 {
137 BOOST_MPI_CHECK_RESULT(MPI_Cancel, (&m_request));
138 }
139
140 bool
141 request::trivial_handler::active() const
142 {
143 return m_request != MPI_REQUEST_NULL;
144 }
145
146 optional<MPI_Request&>
147 request::trivial_handler::trivial()
148 {
149 return m_request;
150 }
151
152 // dynamic handler
153
154 request::dynamic_handler::dynamic_handler()
155 {
156 m_requests[0] = MPI_REQUEST_NULL;
157 m_requests[1] = MPI_REQUEST_NULL;
158 }
159
160 status
161 request::dynamic_handler::wait()
162 {
163 // This request is a send of a serialized type, broken into two
164 // separate messages. Complete both sends at once.
165 MPI_Status stats[2];
166 int error_code = MPI_Waitall(2, m_requests, stats);
167 if (error_code == MPI_ERR_IN_STATUS) {
168 // Dig out which status structure has the error, and use that
169 // one when throwing the exception.
170 if (stats[0].MPI_ERROR == MPI_SUCCESS
171 || stats[0].MPI_ERROR == MPI_ERR_PENDING)
172 boost::throw_exception(exception("MPI_Waitall", stats[1].MPI_ERROR));
173 else
174 boost::throw_exception(exception("MPI_Waitall", stats[0].MPI_ERROR));
175 } else if (error_code != MPI_SUCCESS) {
176 // There was an error somewhere in the MPI_Waitall call; throw
177 // an exception for it.
178 boost::throw_exception(exception("MPI_Waitall", error_code));
179 }
180
181 // No errors. Returns the first status structure.
182 status result;
183 result.m_status = stats[0];
184 return result;
185 }
186
187 optional<status>
188 request::dynamic_handler::test()
189 {
190 // This request is a send of a serialized type, broken into two
191 // separate messages. We only get a result if both complete.
192 MPI_Status stats[2];
193 int flag = 0;
194 int error_code = MPI_Testall(2, m_requests, &flag, stats);
195 if (error_code == MPI_ERR_IN_STATUS) {
196 // Dig out which status structure has the error, and use that
197 // one when throwing the exception.
198 if (stats[0].MPI_ERROR == MPI_SUCCESS
199 || stats[0].MPI_ERROR == MPI_ERR_PENDING)
200 boost::throw_exception(exception("MPI_Testall", stats[1].MPI_ERROR));
201 else
202 boost::throw_exception(exception("MPI_Testall", stats[0].MPI_ERROR));
203 } else if (error_code != MPI_SUCCESS) {
204 // There was an error somewhere in the MPI_Testall call; throw
205 // an exception for it.
206 boost::throw_exception(exception("MPI_Testall", error_code));
207 }
208
209 // No errors. Returns the second status structure if the send has
210 // completed.
211 if (flag != 0) {
212 status result;
213 result.m_status = stats[1];
214 return result;
215 } else {
216 return optional<status>();
217 }
218 }
219
220 void
221 request::dynamic_handler::cancel()
222 {
223 BOOST_MPI_CHECK_RESULT(MPI_Cancel, (&m_requests[0]));
224 BOOST_MPI_CHECK_RESULT(MPI_Cancel, (&m_requests[1]));
225 }
226
227 bool
228 request::dynamic_handler::active() const
229 {
230 return (m_requests[0] != MPI_REQUEST_NULL
231 || m_requests[1] != MPI_REQUEST_NULL);
232 }
233
234 optional<MPI_Request&>
235 request::dynamic_handler::trivial() {
236 return boost::none;
237 }
238
239 } } // end namespace boost::mpi