py_nonblocking.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 256 行
CPP
256 行
// (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);}} } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?