]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/mpi/detail/mpi_datatype_primitive.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / mpi / detail / mpi_datatype_primitive.hpp
1 // (C) Copyright 2005 Matthias Troyer
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 // Authors: Matthias Troyer
8
9 #ifndef BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
10 #define BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP
11
12 #include <boost/mpi/config.hpp>
13 #include <cstddef> // size_t
14
15 #include <boost/config.hpp>
16 #if defined(BOOST_NO_STDC_NAMESPACE)
17 namespace std{
18 using ::size_t;
19 } // namespace std
20 #endif
21
22 #include <boost/mpi/datatype_fwd.hpp>
23 #include <boost/mpi/exception.hpp>
24 #include <boost/mpi/detail/antiques.hpp>
25 #include <boost/throw_exception.hpp>
26 #include <boost/assert.hpp>
27 #include <boost/mpl/placeholders.hpp>
28 #include <boost/serialization/array.hpp>
29 #include <stdexcept>
30 #include <iostream>
31 #include <vector>
32 #include <boost/mpi/detail/antiques.hpp>
33
34 namespace boost { namespace mpi { namespace detail {
35
36 /////////////////////////////////////////////////////////////////////////
37 // class mpi_data_type_oprimitive - creation of custom MPI data types
38
39 class mpi_datatype_primitive
40 {
41 public:
42
43 // trivial default constructor
44 mpi_datatype_primitive()
45 : is_committed(false),
46 origin(0)
47 {}
48
49 mpi_datatype_primitive(void const* orig)
50 : is_committed(false),
51 origin()
52 {
53 #if BOOST_MPI_VERSION >= 2
54 BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(orig), &origin));
55 #else
56 BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(orig), &origin));
57 #endif
58 }
59
60 void save_binary(void const *address, std::size_t count)
61 {
62 save_impl(address,MPI_BYTE,count);
63 }
64
65 // fast saving of arrays of MPI types
66 template<class T>
67 void save_array(serialization::array_wrapper<T> const& x, unsigned int /* version */)
68 {
69 if (x.count())
70 save_impl(x.address(), boost::mpi::get_mpi_datatype(*x.address()), x.count());
71 }
72
73 typedef is_mpi_datatype<mpl::_1> use_array_optimization;
74
75 // create and return the custom MPI data type
76 MPI_Datatype get_mpi_datatype()
77 {
78 if (!is_committed)
79 {
80 #if BOOST_MPI_VERSION >= 2
81 BOOST_MPI_CHECK_RESULT(MPI_Type_create_struct,
82 (
83 addresses.size(),
84 c_data(lengths),
85 c_data(addresses),
86 c_data(types),
87 &datatype_
88 ));
89 #else
90 BOOST_MPI_CHECK_RESULT(MPI_Type_struct,
91 (
92 addresses.size(),
93 c_data(lengths),
94 c_data(addresses),
95 c_data(types),
96 &datatype_
97 ));
98 #endif
99 BOOST_MPI_CHECK_RESULT(MPI_Type_commit,(&datatype_));
100
101 is_committed = true;
102 }
103
104 return datatype_;
105 }
106
107 // default saving of primitives.
108 template<class T>
109 void save(const T & t)
110 {
111 save_impl(&t, boost::mpi::get_mpi_datatype(t), 1);
112 }
113
114 private:
115
116 void save_impl(void const * p, MPI_Datatype t, int l)
117 {
118 BOOST_ASSERT ( !is_committed );
119
120 // store address, type and length
121
122 MPI_Aint a;
123 #if BOOST_MPI_VERSION >= 2
124 BOOST_MPI_CHECK_RESULT(MPI_Get_address,(const_cast<void*>(p), &a));
125 #else
126 BOOST_MPI_CHECK_RESULT(MPI_Address,(const_cast<void*>(p), &a));
127 #endif
128 addresses.push_back(a-origin);
129 types.push_back(t);
130 lengths.push_back(l);
131 }
132
133 template <class T>
134 static T* get_data(std::vector<T>& v)
135 {
136 return v.empty() ? 0 : &(v[0]);
137 }
138
139 std::vector<MPI_Aint> addresses;
140 std::vector<MPI_Datatype> types;
141 std::vector<int> lengths;
142
143 bool is_committed;
144 MPI_Datatype datatype_;
145 MPI_Aint origin;
146 };
147
148
149 } } } // end namespace boost::mpi::detail
150
151
152 #endif // BOOST_MPI_DETAIL_MPI_DATATYPE_OPRIMITIVE_HPP