]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/mpi/src/request.cpp
1 // Copyright (C) 2006 Douglas Gregor.
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>
11 namespace boost
{ namespace mpi
{
17 request::preserve(boost::shared_ptr
<void> d
) {
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
));
27 request
request::make_dynamic() { return request(new dynamic_handler()); }
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
,
34 dest
, tag
, comm
, &handler
->m_request
));
35 return request(handler
);
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
);
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
,
52 dest
, tag
, comm
, &handler
->m_request
));
53 return request(handler
);
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
);
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)
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
);
77 dynamic_handler
*handler
= new dynamic_handler
;
79 shared_ptr
<std::size_t> size(new std::size_t(n
));
81 BOOST_MPI_CHECK_RESULT(MPI_Isend
,
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
,
88 dest
, tag
, comm
, handler
->m_requests
+1));
94 /***************************************************************************
96 ***************************************************************************/
98 request::handler::~handler() {}
100 optional
<MPI_Request
&>
101 request::legacy_handler::trivial() {
106 request::legacy_handler::active() const {
107 return m_requests
[0] != MPI_REQUEST_NULL
|| m_requests
[1] != MPI_REQUEST_NULL
;
112 request::trivial_handler::trivial_handler()
113 : m_request(MPI_REQUEST_NULL
) {}
116 request::trivial_handler::wait()
119 BOOST_MPI_CHECK_RESULT(MPI_Wait
, (&m_request
, &result
.m_status
));
125 request::trivial_handler::test()
129 BOOST_MPI_CHECK_RESULT(MPI_Test
,
130 (&m_request
, &flag
, &result
.m_status
));
131 return flag
!= 0? optional
<status
>(result
) : optional
<status
>();
135 request::trivial_handler::cancel()
137 BOOST_MPI_CHECK_RESULT(MPI_Cancel
, (&m_request
));
141 request::trivial_handler::active() const
143 return m_request
!= MPI_REQUEST_NULL
;
146 optional
<MPI_Request
&>
147 request::trivial_handler::trivial()
154 request::dynamic_handler::dynamic_handler()
156 m_requests
[0] = MPI_REQUEST_NULL
;
157 m_requests
[1] = MPI_REQUEST_NULL
;
161 request::dynamic_handler::wait()
163 // This request is a send of a serialized type, broken into two
164 // separate messages. Complete both sends at once.
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
));
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
));
181 // No errors. Returns the first status structure.
183 result
.m_status
= stats
[0];
188 request::dynamic_handler::test()
190 // This request is a send of a serialized type, broken into two
191 // separate messages. We only get a result if both complete.
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
));
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
));
209 // No errors. Returns the second status structure if the send has
213 result
.m_status
= stats
[1];
216 return optional
<status
>();
221 request::dynamic_handler::cancel()
223 BOOST_MPI_CHECK_RESULT(MPI_Cancel
, (&m_requests
[0]));
224 BOOST_MPI_CHECK_RESULT(MPI_Cancel
, (&m_requests
[1]));
228 request::dynamic_handler::active() const
230 return (m_requests
[0] != MPI_REQUEST_NULL
231 || m_requests
[1] != MPI_REQUEST_NULL
);
234 optional
<MPI_Request
&>
235 request::dynamic_handler::trivial() {
239 } } // end namespace boost::mpi