request.hpp 5.3 KB

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