liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (C) 2006 Douglas Gregor <doug.gregor -at- gmail.com>.
 
// 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)
 
/** @file status.hpp
 *
 *  This header defines the class @c status, which reports on the
 *  results of point-to-point communication.
 */
#ifndef BOOST_MPI_STATUS_HPP
#define BOOST_MPI_STATUS_HPP
 
#include <boost/mpi/config.hpp>
#include <boost/mpi/datatype.hpp>
#include <boost/optional.hpp>
#include <boost/mpl/bool.hpp>
 
namespace boost { namespace mpi {
 
class request;
class communicator;
 
/** @brief Contains information about a message that has been or can
 *  be received.
 *
 *  This structure contains status information about messages that
 *  have been received (with @c communicator::recv) or can be received
 *  (returned from @c communicator::probe or @c
 *  communicator::iprobe). It permits access to the source of the
 *  message, message tag, error code (rarely used), or the number of
 *  elements that have been transmitted.
 */
class BOOST_MPI_DECL status
{
 public:
  status() : m_count(-1) { }
  
  status(MPI_Status const& s) : m_status(s), m_count(-1) {}
 
  /**
   * Retrieve the source of the message.
   */
  int source() const { return m_status.MPI_SOURCE; }
 
  /**
   * Retrieve the message tag.
   */
  int tag() const { return m_status.MPI_TAG; }
 
  /**
   * Retrieve the error code.
   */
  int error() const { return m_status.MPI_ERROR; }
 
  /**
   * Determine whether the communication associated with this object
   * has been successfully cancelled.
  */
  bool cancelled() const;
 
  /**
   * Determines the number of elements of type @c T contained in the
   * message. The type @c T must have an associated data type, i.e.,
   * @c is_mpi_datatype<T> must derive @c mpl::true_. In cases where
   * the type @c T does not match the transmitted type, this routine
   * will return an empty @c optional<int>.
   *
   * @returns the number of @c T elements in the message, if it can be
   * determined.
   */
  template<typename T> optional<int> count() const { return count_impl<T>(is_mpi_datatype<T>()); }
 
  /**
   * References the underlying @c MPI_Status
   */
  operator       MPI_Status&()       { return m_status; }
 
  /**
   * References the underlying @c MPI_Status
   */
  operator const MPI_Status&() const { return m_status; }
 
 private:
  /**
   * INTERNAL ONLY
   */
  template<typename T> optional<int> count_impl(mpl::true_) const;
 
  /**
   * INTERNAL ONLY
   */
  template<typename T> optional<int> count_impl(mpl::false_) const;
 
 public: // friend templates are not portable
 
  /// INTERNAL ONLY
  mutable MPI_Status m_status;
  mutable int m_count;
 
  friend class communicator;
  friend class request;
};
 
template<typename T> 
inline optional<int> status::count_impl(mpl::true_) const
{
  if (m_count != -1)
    return m_count;
 
  int return_value;
  BOOST_MPI_CHECK_RESULT(MPI_Get_count,
                         (&m_status, get_mpi_datatype<T>(T()), &return_value));
  if (return_value == MPI_UNDEFINED)
    return optional<int>();
  else
    /* Cache the result. */
    return m_count = return_value;
}
 
template<typename T> 
inline optional<int> status::count_impl(mpl::false_) const
{
  if (m_count == -1)
    return optional<int>();
  else
    return m_count;
}
 
 
} } // end namespace boost::mpi
 
#endif // BOOST_MPI_STATUS_HPP