1 // Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>. 2 3 // Use, modification and distribution is subject to the Boost Software 4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 /** @file request.hpp 8 * 9 * This header defines the class @c request, which contains a request 10 * for non-blocking communication. 11 */ 12 #ifndef BOOST_MPI_REQUEST_HPP 13 #define BOOST_MPI_REQUEST_HPP 14 15 #include <boost/mpi/config.hpp> 16 #include <boost/mpi/status.hpp> 17 #include <boost/optional.hpp> 18 #include <boost/shared_ptr.hpp> 19 #include <boost/mpi/packed_iarchive.hpp> 20 21 namespace boost { namespace mpi { 22 23 class status; 24 class communicator; 25 26 /** 27 * @brief A request for a non-blocking send or receive. 28 * 29 * This structure contains information about a non-blocking send or 30 * receive and will be returned from @c isend or @c irecv, 31 * respectively. 32 */ 33 class BOOST_MPI_DECL request 34 { 35 public: 36 /** 37 * Constructs a NULL request. 38 */ 39 request(); 40 41 /** 42 * Send a known number of primitive objects in one MPI request. 43 */ 44 template<typename T> 45 static request make_trivial_send(communicator const& comm, int dest, int tag, T const& value); 46 template<typename T> 47 static request make_trivial_send(communicator const& comm, int dest, int tag, T const* values, int n); 48 static request make_packed_send(communicator const& comm, int dest, int tag, void const* values, std::size_t n); 49 50 static request make_bottom_send(communicator const& comm, int dest, int tag, MPI_Datatype tp); 51 static request make_empty_send(communicator const& comm, int dest, int tag); 52 /** 53 * Receive a known number of primitive objects in one MPI request. 54 */ 55 template<typename T> 56 static request make_trivial_recv(communicator const& comm, int dest, int tag, T& value); 57 template<typename T> 58 static request make_trivial_recv(communicator const& comm, int dest, int tag, T* values, int n); 59 60 static request make_bottom_recv(communicator const& comm, int dest, int tag, MPI_Datatype tp); 61 static request make_empty_recv(communicator const& comm, int dest, int tag); 62 /** 63 * Construct request for simple data of unknown size. 64 */ 65 static request make_dynamic(); 66 /** 67 * Constructs request for serialized data. 68 */ 69 template<typename T> 70 static request make_serialized(communicator const& comm, int source, int tag, T& value); 71 /** 72 * Constructs request for array of complex data. 73 */ 74 template<typename T> 75 static request make_serialized_array(communicator const& comm, int source, int tag, T* values, int n); 76 /** 77 * Request to recv array of primitive data. 78 */ 79 template<typename T, class A> 80 static request 81 make_dynamic_primitive_array_recv(communicator const& comm, int source, int tag, 82 std::vector<T,A>& values); 83 /** 84 * Request to send array of primitive data. 85 */ 86 template<typename T, class A> 87 static request 88 make_dynamic_primitive_array_send(communicator const& comm, int source, int tag, 89 std::vector<T,A> const& values); 90 /** 91 * Wait until the communication associated with this request has 92 * completed, then return a @c status object describing the 93 * communication. 94 */ wait()95 status wait() { return m_handler ? m_handler->wait() : status(); } 96 97 /** 98 * Determine whether the communication associated with this request 99 * has completed successfully. If so, returns the @c status object 100 * describing the communication. Otherwise, returns an empty @c 101 * optional<> to indicate that the communication has not completed 102 * yet. Note that once @c test() returns a @c status object, the 103 * request has completed and @c wait() should not be called. 104 */ test()105 optional<status> test() { return active() ? m_handler->test() : optional<status>(); } 106 107 /** 108 * Cancel a pending communication, assuming it has not already been 109 * completed. 110 */ cancel()111 void cancel() { if (m_handler) { m_handler->cancel(); } m_preserved.reset(); } 112 113 /** 114 * The trivial MPI requet implenting this request, provided it's trivial. 115 * Probably irrelevant to most users. 116 */ trivial()117 optional<MPI_Request&> trivial() { return (m_handler 118 ? m_handler->trivial() 119 : optional<MPI_Request&>()); } 120 121 /** 122 * Is this request potentialy pending ? 123 */ active() const124 bool active() const { return bool(m_handler) && m_handler->active(); } 125 126 // Some data might need protection while the reqest is processed. 127 void preserve(boost::shared_ptr<void> d); 128 129 class handler { 130 public: 131 virtual BOOST_MPI_DECL ~handler() = 0; 132 virtual status wait() = 0; 133 virtual optional<status> test() = 0; 134 virtual void cancel() = 0; 135 136 virtual bool active() const = 0; 137 virtual optional<MPI_Request&> trivial() = 0; 138 }; 139 140 private: 141 request(handler * h)142 request(handler *h) : m_handler(h) {}; 143 144 // specific implementations 145 class legacy_handler; 146 class trivial_handler; 147 class dynamic_handler; 148 template<typename T> class legacy_serialized_handler; 149 template<typename T> class legacy_serialized_array_handler; 150 template<typename T, class A> class legacy_dynamic_primitive_array_handler; 151 #if BOOST_MPI_VERSION >= 3 152 template<class Data> class probe_handler; 153 #endif 154 private: 155 shared_ptr<handler> m_handler; 156 shared_ptr<void> m_preserved; 157 }; 158 159 } } // end namespace boost::mpi 160 161 #endif // BOOST_MPI_REQUEST_HPP 162