]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/mpi/src/python/py_nonblocking.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / mpi / src / python / py_nonblocking.cpp
CommitLineData
7c673cae
FG
1// (C) Copyright 2007
2// Douglas Gregor <doug.gregor -at- gmail.com>
3// Andreas Kloeckner <inform -at- tiker.net>
4
5// Use, modification and distribution is subject to the Boost Software
6// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// Authors: Douglas Gregor, Andreas Kloeckner
10
11/** @file py_nonblocking.cpp
12 *
13 * This file reflects the Boost.MPI nonblocking operations into Python
14 * functions.
15 */
16
17#include <vector>
18#include <iterator>
19#include <algorithm>
20#include <boost/operators.hpp>
21#include <boost/python.hpp>
22#include <boost/python/stl_iterator.hpp>
23#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
24#include <boost/mpi.hpp>
25#include "request_with_value.hpp"
26
27using namespace std;
28using namespace boost::python;
29using namespace boost::mpi;
30
31
32
33
34namespace
35{
36 template <class ValueType, class RequestIterator>
37 class py_call_output_iterator :
38 public boost::output_iterator_helper<
39 py_call_output_iterator<ValueType, RequestIterator> >
40 {
41 private:
42 object m_callable;
43 RequestIterator m_request_iterator;
44
45 public:
46 explicit py_call_output_iterator(object callable,
47 const RequestIterator &req_it)
48 : m_callable(callable), m_request_iterator(req_it)
49 { }
50
51 py_call_output_iterator &operator=(ValueType const &v)
52 {
53 m_callable((m_request_iterator++)->get_value_or_none(), v);
54 return *this;
55 }
56 };
57
58
59
60
61 typedef std::vector<python::request_with_value> request_list;
62 typedef py_call_output_iterator<status, request_list::iterator>
63 status_value_iterator;
64
65
66
67
92f5a8d4 68 std::shared_ptr<request_list> make_request_list_from_py_list(object iterable)
7c673cae 69 {
92f5a8d4 70 std::shared_ptr<request_list> result(new request_list);
7c673cae
FG
71 std::copy(
72 stl_input_iterator<python::request_with_value>(iterable),
73 stl_input_iterator<python::request_with_value>(),
74 back_inserter(*result));
75 return result;
76 }
77
78
79
80
81 class request_list_indexing_suite :
82 public vector_indexing_suite<request_list, false, request_list_indexing_suite>
83 {
84 public:
85 // FIXME: requests are not comparable, thus __contains__ makes no sense.
86 // Unfortunately, indexing_suites insist on having __contains__ available.
87 // Just make it error out for now.
88
89 static bool
90 contains(request_list& container, request const& key)
91 {
92 PyErr_SetString(PyExc_NotImplementedError, "mpi requests are not comparable");
93 throw error_already_set();
94 }
95 };
96
97
98
99
100 void check_request_list_not_empty(const request_list &requests)
101 {
102 if (requests.size() == 0)
103 {
104 PyErr_SetString(PyExc_ValueError, "cannot wait on an empty request vector");
105 throw error_already_set();
106 }
107
108 }
109
110
111
112
113
114 object wrap_wait_any(request_list &requests)
115 {
116 check_request_list_not_empty(requests);
117
118 pair<status, request_list::iterator> result =
119 wait_any(requests.begin(), requests.end());
120
121 return boost::python::make_tuple(
122 result.second->get_value_or_none(),
123 result.first,
124 distance(requests.begin(), result.second));
125 }
126
127
128
129
130 object wrap_test_any(request_list &requests)
131 {
132 check_request_list_not_empty(requests);
133 ::boost::optional<pair<status, request_list::iterator> > result =
134 test_any(requests.begin(), requests.end());
135
136 if (result)
137 return boost::python::make_tuple(
138 result->second->get_value_or_none(),
139 result->first,
140 distance(requests.begin(), result->second));
141 else
142 return object();
143 }
144
145
146
147
148
149 void wrap_wait_all(request_list &requests, object py_callable)
150 {
151 check_request_list_not_empty(requests);
152 if (py_callable != object())
153 wait_all(requests.begin(), requests.end(),
154 status_value_iterator(py_callable, requests.begin()));
155 else
156 wait_all(requests.begin(), requests.end());
157 }
158
159
160
161
162 bool wrap_test_all(request_list &requests, object py_callable)
163 {
164 check_request_list_not_empty(requests);
165 if (py_callable != object())
166 return bool(test_all(requests.begin(), requests.end(),
167 status_value_iterator(py_callable, requests.begin())));
168 else
169 return bool(test_all(requests.begin(), requests.end()));
170 }
171
172
173
174
175 int wrap_wait_some(request_list &requests, object py_callable)
176 {
177 check_request_list_not_empty(requests);
178 request_list::iterator first_completed;
179 if (py_callable != object())
180 first_completed = wait_some(requests.begin(), requests.end(),
181 status_value_iterator(py_callable, requests.begin())).second;
182 else
183 first_completed = wait_some(requests.begin(), requests.end());
184
185 return distance(requests.begin(), first_completed);
186 }
187
188
189
190
191 int wrap_test_some(request_list &requests, object py_callable)
192 {
193 check_request_list_not_empty(requests);
194 request_list::iterator first_completed;
195 if (py_callable != object())
196 first_completed = test_some(requests.begin(), requests.end(),
197 status_value_iterator(py_callable, requests.begin())).second;
198 else
199 first_completed = test_some(requests.begin(), requests.end());
200
201 return distance(requests.begin(), first_completed);
202 }
203}
204
205
206
207
208namespace boost { namespace mpi { namespace python {
209
210extern const char* request_list_init_docstring;
211extern const char* request_list_append_docstring;
212
213extern const char* nonblocking_wait_any_docstring;
214extern const char* nonblocking_test_any_docstring;
215extern const char* nonblocking_wait_all_docstring;
216extern const char* nonblocking_test_all_docstring;
217extern const char* nonblocking_wait_some_docstring;
218extern const char* nonblocking_test_some_docstring;
219
220void export_nonblocking()
221{
222 using boost::python::arg;
223
224 {
225 typedef request_list cl;
226 class_<cl>("RequestList", "A list of Request objects.")
227 .def("__init__", make_constructor(make_request_list_from_py_list),
228 /*arg("iterable"),*/ request_list_init_docstring)
229 .def(request_list_indexing_suite())
230 ;
231 }
232
233 def("wait_any", wrap_wait_any,
234 (arg("requests")),
235 nonblocking_wait_any_docstring);
236 def("test_any", wrap_test_any,
237 (arg("requests")),
238 nonblocking_test_any_docstring);
239
240 def("wait_all", wrap_wait_all,
241 (arg("requests"), arg("callable") = object()),
242 nonblocking_wait_all_docstring);
243 def("test_all", wrap_test_all,
244 (arg("requests"), arg("callable") = object()),
245 nonblocking_test_all_docstring);
246
247 def("wait_some", wrap_wait_some,
248 (arg("requests"), arg("callable") = object()),
249 nonblocking_wait_some_docstring);
250 def("test_some", wrap_test_some,
251 (arg("requests"), arg("callable") = object()),
252 nonblocking_test_some_docstring);
253}
254
255} } }