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