TIMPI
Loading...
Searching...
No Matches
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
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
41namespace libMesh
42{
43
44namespace Parallel
45{
46
47template <typename T, typename Enable>
48class 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
54template <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
71public:
72 static constexpr bool value = sizeof(test<Derived>(nullptr)) == sizeof(Yes);
73};
74
75
76// specialization for std::pair
77template <typename T1, typename T2>
79{
80 typedef typename std::remove_const<T1>::type cT1;
81
82 static const bool value =
88};
89
90
91template <typename T1, typename T2>
92class Packing<std::pair<T1, T2>,
93 typename std::enable_if<PairHasPacking<T1,T2>::value>::type>;
94
95
96// specializations for std::tuple
97
98template <typename... Types>
100
101template <>
103{
104 static const bool value = true;
105};
106
107template <typename T, typename... Types>
108struct TupleHasPacking<T, Types...>
109{
110 static const bool value =
111 !TIMPI::StandardType<std::tuple<T, Types...>>::is_fixed_type &&
115 TIMPI::StandardType<std::tuple<Types...>>::is_fixed_type);
116};
117
118
119template <typename Enable>
120class Packing<std::tuple<>, Enable>;
121
122template <typename T, typename... Types>
123class Packing<std::tuple<T, Types...>,
124 typename std::enable_if<TupleHasPacking<T, Types...>::value>::type>;
125
126
127// specialization for std::array
128template <typename T, std::size_t N>
129class 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.
135template <typename Container>
136class PackingRange;
137
138
139#define TIMPI_DECL_PACKING_RANGE_SUBCLASS(Container) \
140class 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
146template <typename T, typename A>
147TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::vector<T TIMPI_P_COMMA A>);
148
149template <typename T, typename A>
150TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::list<T TIMPI_P_COMMA A>);
151
152template <typename K, typename T, typename C, typename A>
153TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::map<K TIMPI_P_COMMA T TIMPI_P_COMMA C TIMPI_P_COMMA A>);
154
155template <typename K, typename T, typename C, typename A>
156TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::multimap<K TIMPI_P_COMMA T TIMPI_P_COMMA C TIMPI_P_COMMA A>);
157
158template <typename K, typename C, typename A>
159TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::multiset<K TIMPI_P_COMMA C TIMPI_P_COMMA A>);
160
161template <typename K, typename C, typename A>
162TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::set<K TIMPI_P_COMMA C TIMPI_P_COMMA A>);
163
164template <typename K, typename T, typename H, typename KE, typename A>
165TIMPI_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
167template <typename K, typename T, typename H, typename KE, typename A>
168TIMPI_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
170template <typename K, typename H, typename KE, typename A>
171TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::unordered_multiset<K TIMPI_P_COMMA H TIMPI_P_COMMA KE TIMPI_P_COMMA A>);
172
173template <typename K, typename H, typename KE, typename A>
174TIMPI_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
180template <typename T>
181class 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
189namespace TIMPI {
190
192
201template <typename Context, typename buffertype,
202 typename OutputIter, typename T>
203inline 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
216template <typename Context, typename buffertype, typename Iter>
217inline 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
227template <typename Context, typename Iter>
228inline 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...
static No & test(typename U::buffer_type *)
Define data types and (un)serialization functions for use when encoding a potentially-variable-size o...
Definition packing.h:60
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::size_t packed_range_size(const Context *context, Iter range_begin, const Iter range_end)
Helper function for range packing.
Definition packing.h:1023
OutputIter unpack_range(const std::vector< buffertype > &buffer, Context *context, OutputIter out_iter, const T *)
Helper function for range unpacking.
Definition packing.h:1103
TIMPI_DECL_PACKING_RANGE_SUBCLASS(std::vector< T TIMPI_P_COMMA A >)
std::remove_const< T1 >::type cT1