summaryrefslogtreecommitdiff
path: root/libs/mpi/src/python/py_nonblocking.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-06-25 22:59:01 +0000
committer <>2013-09-27 11:49:28 +0000
commit8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch)
treec09e2ce80f47b90c85cc720f5139089ad9c8cfff /libs/mpi/src/python/py_nonblocking.cpp
downloadboost-tarball-baserock/morph.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'libs/mpi/src/python/py_nonblocking.cpp')
-rw-r--r--libs/mpi/src/python/py_nonblocking.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/libs/mpi/src/python/py_nonblocking.cpp b/libs/mpi/src/python/py_nonblocking.cpp
new file mode 100644
index 000000000..22f289f9e
--- /dev/null
+++ b/libs/mpi/src/python/py_nonblocking.cpp
@@ -0,0 +1,255 @@
+// (C) Copyright 2007
+// Douglas Gregor <doug.gregor -at- gmail.com>
+// Andreas Kloeckner <inform -at- tiker.net>
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Douglas Gregor, Andreas Kloeckner
+
+/** @file py_nonblocking.cpp
+ *
+ * This file reflects the Boost.MPI nonblocking operations into Python
+ * functions.
+ */
+
+#include <vector>
+#include <iterator>
+#include <algorithm>
+#include <boost/operators.hpp>
+#include <boost/python.hpp>
+#include <boost/python/stl_iterator.hpp>
+#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
+#include <boost/mpi.hpp>
+#include "request_with_value.hpp"
+
+using namespace std;
+using namespace boost::python;
+using namespace boost::mpi;
+
+
+
+
+namespace
+{
+ template <class ValueType, class RequestIterator>
+ class py_call_output_iterator :
+ public boost::output_iterator_helper<
+ py_call_output_iterator<ValueType, RequestIterator> >
+ {
+ private:
+ object m_callable;
+ RequestIterator m_request_iterator;
+
+ public:
+ explicit py_call_output_iterator(object callable,
+ const RequestIterator &req_it)
+ : m_callable(callable), m_request_iterator(req_it)
+ { }
+
+ py_call_output_iterator &operator=(ValueType const &v)
+ {
+ m_callable((m_request_iterator++)->get_value_or_none(), v);
+ return *this;
+ }
+ };
+
+
+
+
+ typedef std::vector<python::request_with_value> request_list;
+ typedef py_call_output_iterator<status, request_list::iterator>
+ status_value_iterator;
+
+
+
+
+ std::auto_ptr<request_list> make_request_list_from_py_list(object iterable)
+ {
+ std::auto_ptr<request_list> result(new request_list);
+ std::copy(
+ stl_input_iterator<python::request_with_value>(iterable),
+ stl_input_iterator<python::request_with_value>(),
+ back_inserter(*result));
+ return result;
+ }
+
+
+
+
+ class request_list_indexing_suite :
+ public vector_indexing_suite<request_list, false, request_list_indexing_suite>
+ {
+ public:
+ // FIXME: requests are not comparable, thus __contains__ makes no sense.
+ // Unfortunately, indexing_suites insist on having __contains__ available.
+ // Just make it error out for now.
+
+ static bool
+ contains(request_list& container, request const& key)
+ {
+ PyErr_SetString(PyExc_NotImplementedError, "mpi requests are not comparable");
+ throw error_already_set();
+ }
+ };
+
+
+
+
+ void check_request_list_not_empty(const request_list &requests)
+ {
+ if (requests.size() == 0)
+ {
+ PyErr_SetString(PyExc_ValueError, "cannot wait on an empty request vector");
+ throw error_already_set();
+ }
+
+ }
+
+
+
+
+
+ object wrap_wait_any(request_list &requests)
+ {
+ check_request_list_not_empty(requests);
+
+ pair<status, request_list::iterator> result =
+ wait_any(requests.begin(), requests.end());
+
+ return make_tuple(
+ result.second->get_value_or_none(),
+ result.first,
+ distance(requests.begin(), result.second));
+ }
+
+
+
+
+ object wrap_test_any(request_list &requests)
+ {
+ check_request_list_not_empty(requests);
+ ::boost::optional<pair<status, request_list::iterator> > result =
+ test_any(requests.begin(), requests.end());
+
+ if (result)
+ return make_tuple(
+ result->second->get_value_or_none(),
+ result->first,
+ distance(requests.begin(), result->second));
+ else
+ return object();
+ }
+
+
+
+
+
+ void wrap_wait_all(request_list &requests, object py_callable)
+ {
+ check_request_list_not_empty(requests);
+ if (py_callable != object())
+ wait_all(requests.begin(), requests.end(),
+ status_value_iterator(py_callable, requests.begin()));
+ else
+ wait_all(requests.begin(), requests.end());
+ }
+
+
+
+
+ bool wrap_test_all(request_list &requests, object py_callable)
+ {
+ check_request_list_not_empty(requests);
+ if (py_callable != object())
+ return test_all(requests.begin(), requests.end(),
+ status_value_iterator(py_callable, requests.begin()));
+ else
+ return test_all(requests.begin(), requests.end());
+ }
+
+
+
+
+ int wrap_wait_some(request_list &requests, object py_callable)
+ {
+ check_request_list_not_empty(requests);
+ request_list::iterator first_completed;
+ if (py_callable != object())
+ first_completed = wait_some(requests.begin(), requests.end(),
+ status_value_iterator(py_callable, requests.begin())).second;
+ else
+ first_completed = wait_some(requests.begin(), requests.end());
+
+ return distance(requests.begin(), first_completed);
+ }
+
+
+
+
+ int wrap_test_some(request_list &requests, object py_callable)
+ {
+ check_request_list_not_empty(requests);
+ request_list::iterator first_completed;
+ if (py_callable != object())
+ first_completed = test_some(requests.begin(), requests.end(),
+ status_value_iterator(py_callable, requests.begin())).second;
+ else
+ first_completed = test_some(requests.begin(), requests.end());
+
+ return distance(requests.begin(), first_completed);
+ }
+}
+
+
+
+
+namespace boost { namespace mpi { namespace python {
+
+extern const char* request_list_init_docstring;
+extern const char* request_list_append_docstring;
+
+extern const char* nonblocking_wait_any_docstring;
+extern const char* nonblocking_test_any_docstring;
+extern const char* nonblocking_wait_all_docstring;
+extern const char* nonblocking_test_all_docstring;
+extern const char* nonblocking_wait_some_docstring;
+extern const char* nonblocking_test_some_docstring;
+
+void export_nonblocking()
+{
+ using boost::python::arg;
+
+ {
+ typedef request_list cl;
+ class_<cl>("RequestList", "A list of Request objects.")
+ .def("__init__", make_constructor(make_request_list_from_py_list),
+ /*arg("iterable"),*/ request_list_init_docstring)
+ .def(request_list_indexing_suite())
+ ;
+ }
+
+ def("wait_any", wrap_wait_any,
+ (arg("requests")),
+ nonblocking_wait_any_docstring);
+ def("test_any", wrap_test_any,
+ (arg("requests")),
+ nonblocking_test_any_docstring);
+
+ def("wait_all", wrap_wait_all,
+ (arg("requests"), arg("callable") = object()),
+ nonblocking_wait_all_docstring);
+ def("test_all", wrap_test_all,
+ (arg("requests"), arg("callable") = object()),
+ nonblocking_test_all_docstring);
+
+ def("wait_some", wrap_wait_some,
+ (arg("requests"), arg("callable") = object()),
+ nonblocking_wait_some_docstring);
+ def("test_some", wrap_test_some,
+ (arg("requests"), arg("callable") = object()),
+ nonblocking_test_some_docstring);
+}
+
+} } }