TIMPI
packing_decl.h
Go to the documentation of this file.
1 // The TIMPI Message-Passing Parallelism Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 #ifndef TIMPI_PACKING_DECL_H
20 #define TIMPI_PACKING_DECL_H
21 
22 // TIMPI Includes
23 #include "timpi/packing_forward.h"
24 #include "timpi/standard_type.h"
25 
26 // C++ includes
27 #include <array>
28 #include <list>
29 #include <map>
30 #include <set>
31 #include <tuple>
32 #include <type_traits> // enable_if
33 #include <unordered_map>
34 #include <unordered_set>
35 #include <utility> // pair
36 #include <vector>
37 
38 
39 // FIXME: This *should* be in TIMPI namespace but we have libMesh
40 // users which already partially specialized it
41 namespace libMesh
42 {
43 
44 namespace Parallel
45 {
46 
47 template <typename T, typename Enable>
48 class Packing;
49 
50 // Idiom taken from https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector
51 //
52 // We need this in _decl because we're using it for SFINAE in
53 // template declarations
54 template <typename T>
56 {
57  using Yes = char[2];
58  using No = char[1];
59 
60  struct Fallback {
61  struct buffer_type {};
62  };
63  struct Derived : T, Fallback {};
64 
65  template <typename U> static Yes &test(U *);
66 
67  // this template must be more specialized in general than the Yes version because it involves a
68  // type-dependent expression...?
69  template <typename U> static No &test(typename U::buffer_type *);
70 
71 public:
72  static constexpr bool value = sizeof(test<Derived>(nullptr)) == sizeof(Yes);
73 };
74 
75 
76 // specialization for std::pair
77 template <typename T1, typename T2>
79 {
80  typedef typename std::remove_const<T1>::type cT1;
81 
82  static const bool value =
83  !TIMPI::StandardType<std::pair<cT1, T2>>::is_fixed_type &&
88 };
89 
90 
91 template <typename T1, typename T2>
92 class Packing<std::pair<T1, T2>,
93  typename std::enable_if<PairHasPacking<T1,T2>::value>::type>;
94 
95 
96 // specializations for std::tuple
97 
98 template <typename... Types>
100 
101 template <>
103 {
104  static const bool value = true;
105 };
106 
107 template <typename T, typename... Types>
108 struct TupleHasPacking<T, Types...>
109 {
110  static const bool value =
111  !TIMPI::StandardType<std::tuple<T, Types...>>::is_fixed_type &&
112  (Has_buffer_type<Packing<T>>::value ||
115  TIMPI::StandardType<std::tuple<Types...>>::is_fixed_type);
116 };
117 
118 
119 template <typename Enable>
120 class Packing<std::tuple<>, Enable>;
121 
122 template <typename T, typename... Types>
123 class Packing<std::tuple<T, Types...>,
124  typename std::enable_if<TupleHasPacking<T, Types...>::value>::type>;
125 
126 
127 // specialization for std::array
128 template <typename T, std::size_t N>
129 class Packing<std::array<T, N>,
130  typename std::enable_if<Has_buffer_type<Packing<T>>::value>::type>;
131 
132 
133 // helper class for any homogeneous-type variable-size containers
134 // which define the usual iterator ranges, value_type, etc.
135 template <typename Container>
136 class PackingRange;
137 
138 
139 #define TIMPI_DECL_PACKING_RANGE_SUBCLASS(Container) \
140 class Packing<Container, \
141  typename std::enable_if<Has_buffer_type<Packing<typename Container::value_type>>::value || \
142  TIMPI::StandardType<typename Container::value_type>::is_fixed_type>::type>
143 
144 #define TIMPI_P_COMMA ,
145 
146 template <typename T, typename A>
147 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::vector<T TIMPI_P_COMMA A>);
148 
149 template <typename T, typename A>
150 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::list<T TIMPI_P_COMMA A>);
151 
152 template <typename K, typename T, typename C, typename A>
153 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::map<K TIMPI_P_COMMA T TIMPI_P_COMMA C TIMPI_P_COMMA A>);
154 
155 template <typename K, typename T, typename C, typename A>
156 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::multimap<K TIMPI_P_COMMA T TIMPI_P_COMMA C TIMPI_P_COMMA A>);
157 
158 template <typename K, typename C, typename A>
159 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::multiset<K TIMPI_P_COMMA C TIMPI_P_COMMA A>);
160 
161 template <typename K, typename C, typename A>
162 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::set<K TIMPI_P_COMMA C TIMPI_P_COMMA A>);
163 
164 template <typename K, typename T, typename H, typename KE, typename A>
165 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_map<K TIMPI_P_COMMA T TIMPI_P_COMMA H TIMPI_P_COMMA KE TIMPI_P_COMMA A>);
166 
167 template <typename K, typename T, typename H, typename KE, typename A>
168 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_multimap<K TIMPI_P_COMMA T TIMPI_P_COMMA H TIMPI_P_COMMA KE TIMPI_P_COMMA A>);
169 
170 template <typename K, typename H, typename KE, typename A>
171 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_multiset<K TIMPI_P_COMMA H TIMPI_P_COMMA KE TIMPI_P_COMMA A>);
172 
173 template <typename K, typename H, typename KE, typename A>
174 TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_set<K TIMPI_P_COMMA H TIMPI_P_COMMA KE TIMPI_P_COMMA A>);
175 
176 
177 
178 #define TIMPI_HAVE_STRING_PACKING
179 
180 template <typename T>
181 class Packing<std::basic_string<T>,
182  typename std::enable_if<TIMPI::StandardType<T>::is_fixed_type>::type>;
183 
184 } // namespace Parallel
185 
186 } // namespace libMesh
187 
188 
189 namespace TIMPI {
190 
192 
201 template <typename Context, typename buffertype,
202  typename OutputIter, typename T>
203 inline OutputIter unpack_range (const typename std::vector<buffertype> & buffer,
204  Context * context,
205  OutputIter out_iter,
206  const T * output_type /* used only to infer T */);
207 
216 template <typename Context, typename buffertype, typename Iter>
217 inline Iter pack_range (const Context * context,
218  Iter range_begin,
219  const Iter range_end,
220  typename std::vector<buffertype> & buffer,
221  std::size_t approx_buffer_size = 1000000);
222 
227 template <typename Context, typename Iter>
228 inline std::size_t packed_range_size (const Context * context,
229  Iter range_begin,
230  const Iter range_end);
231 
232 } // namespace TIMPI
233 
234 #endif // TIMPI_PACKING_H
Templated class to provide the appropriate MPI datatype for use with built-in C types or simple C++ c...
Definition: standard_type.h:83
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition: packing.h:60
OutputIter unpack_range(const typename std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *output_type)
Decode a range of potentially-variable-size objects from a data array.
static constexpr bool value
Definition: packing_decl.h:72
Iter pack_range(const Context *context, Iter range_begin, const Iter range_end, std::vector< buffertype > &buffer, std::size_t approx_buffer_size)
Helper function for range packing.
Definition: packing.h:1044
std::remove_const< T1 >::type cT1
Definition: packing_decl.h:80
TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::vector< T TIMPI_P_COMMA A >)
std::size_t packed_range_size(const Context *context, Iter range_begin, const Iter range_end)
Helper function for range packing.
Definition: packing.h:1023