diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-06-25 22:59:01 +0000 |
---|---|---|
committer | <> | 2013-09-27 11:49:28 +0000 |
commit | 8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch) | |
tree | c09e2ce80f47b90c85cc720f5139089ad9c8cfff /libs/mpi/src/python/py_nonblocking.cpp | |
download | boost-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.cpp | 255 |
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); +} + +} } } |