Cleanup #1489: Delete GPU dummy mempool
[charm.git] / src / util / pup_stl.h
blobb51913dd1cd1841ec9132dd7648ddc7ac9a67211
1 /*
2 Pup routines for STL classes.
4 After including this header, you can parameter-marshall
5 a variable consisting of STL containers such as vectors,
6 lists, maps, strings, or pairs.
8 This includes variables of type "std::list<int>", or even
9 "std::map<double, std::vector<std::string> >".
11 NOT included are the rarer types like valarray or slice.
13 Orion Sky Lawlor, olawlor@acm.org, 7/22/2002
15 #ifndef _UIUC_CHARM_PUP_STL_H
16 #define _UIUC_CHARM_PUP_STL_H
18 #include <conv-config.h>
20 /*It's kind of annoying that we have to drag all these headers in
21 just so the std:: parameter declarations will compile.
23 #include <algorithm>
24 #include <array>
25 #include <set>
26 #include <vector>
27 #include <deque>
28 #include <forward_list>
29 #include <list>
30 #include <map>
31 #include <memory>
32 #include <tuple>
33 #include <unordered_map>
34 #include <unordered_set>
35 #include <string>
36 #include <complex>
37 #include <utility> /*for std::pair*/
38 #include "pup.h"
40 #include <cstddef>
42 namespace PUP {
43 /*************** Simple classes ***************/
44 // Non-const version is required for puping std::pair
45 template <class A,class B>
46 inline void operator|(er &p,typename std::pair<A,B> &v);
47 template <class A,class B>
48 inline void operator|(er &p,typename std::pair<const A,B> &v);
49 template <class T>
50 inline void operator|(er &p,std::complex<T> &v);
51 template <class T>
52 inline void operator|(er &p, std::unique_ptr<T, std::default_delete<T>> &ptr);
53 template <class charType>
54 inline void operator|(er &p,typename std::basic_string<charType> &v);
55 inline void operator|(er &p,std::string &v);
56 template <class container>
57 inline size_t PUP_stl_container_size(er &p,container &c);
58 template <class container, class dtype>
59 inline void PUP_stl_container_items(er &p, container &c, size_t nElem);
60 template <> inline void PUP_stl_container_items<std::vector<bool>,bool>(er &p, std::vector<bool> &c, size_t nElem);
61 template <class container,class dtype>
62 inline void PUP_stl_container(er &p,container &c);
63 template <class container,class dtype>
64 inline void PUP_stl_map(er &p,container &c);
65 template <class T>
66 inline void operator|(er &p,typename std::vector<T> &v);
67 template <class T>
68 inline void operator|(er &p,typename std::deque<T> &d);
69 template <class T>
70 inline void operator|(er &p,typename std::list<T> &v);
71 template <class T>
72 inline void operator|(er &p,typename std::forward_list<T> &fl);
73 template <class V,class T,class Cmp>
74 inline void operator|(er &p,typename std::map<V,T,Cmp> &m);
75 template <class V,class T,class Cmp>
76 inline void operator|(er &p,typename std::multimap<V,T,Cmp> &m);
77 template <class T>
78 inline void operator|(er &p,typename std::set<T> &m);
79 template <class T,class Cmp>
80 inline void operator|(er &p,typename std::multiset<T,Cmp> &m);
81 template <> inline void operator|(er &p,std::vector<bool> &v);
83 template <class A,class B>
84 inline void operator|(er &p,typename std::pair<A,B> &v)
86 p.syncComment(sync_index);
87 p|v.first;
88 p.syncComment(sync_item);
89 p|v.second;
91 // Const version is required for puping std::map
92 template <class A,class B>
93 inline void operator|(er &p,typename std::pair<const A,B> &v)
95 p.syncComment(sync_index);
96 p|*(A *)&v.first; /* cast away constness on A */
97 p.syncComment(sync_item);
98 p|v.second;
100 template <class T>
101 inline void operator|(er &p,std::complex<T> &v)
103 T re=v.real(), im=v.imag();
104 p|re; p|im;
105 v=std::complex<T>(re,im);
107 template <class charType>
108 inline void operator|(er &p,typename std::basic_string<charType> &v)
110 size_t nChar=v.length();
111 p|nChar;
112 if (p.isUnpacking()) { //Unpack to temporary buffer
113 charType *buf=new charType[nChar];
114 p(buf,nChar);
115 v=std::basic_string<charType>(buf,nChar);
116 delete[] buf;
118 else /*packing*/ { //Do packing in-place from data
119 //Have to cast away constness here
120 p((charType *)v.data(),nChar);
123 inline void operator|(er &p,std::string &v)
125 p.syncComment(sync_begin_object,"std::string");
126 size_t nChar=v.length();
127 p|nChar;
128 if (p.isUnpacking()) { //Unpack to temporary buffer
129 char *buf=new char[nChar];
130 p(buf,nChar);
131 v=std::basic_string<char>(buf,nChar);
132 delete[] buf;
134 else /*packing*/ { //Do packing in-place from data
135 //Have to cast away constness here
136 p((char *)v.data(),nChar);
138 p.syncComment(sync_end_object);
141 /**************** Containers *****************/
143 template <class container>
144 void reserve_if_applicable(container &c, size_t nElem)
146 c.clear();
147 c.reserve(nElem);
149 template <class dtype>
150 void reserve_if_applicable(std::deque<dtype> &c, size_t nElem)
152 c.clear();
154 template <class dtype>
155 void reserve_if_applicable(std::list<dtype> &c, size_t nElem)
157 c.clear();
159 template <class dtype>
160 void reserve_if_applicable(std::forward_list<dtype> &c, size_t nElem)
162 c.clear();
164 template <class K, class V>
165 void reserve_if_applicable(std::map<K, V> &c, size_t nElem)
167 c.clear();
169 template <class K, class V>
170 void reserve_if_applicable(std::multimap<K, V> &c, size_t nElem)
172 c.clear();
175 //Impl. util: pup the length of a container
176 template <class container>
177 inline size_t PUP_stl_container_size(er &p,container &c) {
178 size_t nElem=c.size();
179 p|nElem;
180 return nElem;
183 //Impl. util: pup each current item of a container (no allocation)
184 template <class container, class dtype>
185 inline void PUP_stl_container_items(er &p, container &c, size_t nElem)
187 if (p.isUnpacking())
189 reserve_if_applicable(c, nElem);
190 for (size_t i = 0; i < nElem; ++i)
192 p.syncComment(sync_item);
193 detail::TemporaryObjectHolder<dtype> n;
194 p|n;
195 c.emplace_back(std::move(n.t));
198 else
200 for (typename container::iterator it=c.begin(); it!=c.end(); ++it)
202 p.syncComment(sync_item);
203 // Cast away the constness (needed for std::set)
204 p|*(dtype *)&(*it);
209 // Specialized to work with vector<bool>
210 template<>
211 inline void PUP_stl_container_items<std::vector<bool>, bool>(er &p, std::vector<bool> &c, size_t nElem)
213 if (p.isUnpacking())
214 c.resize(nElem);
216 std::deque<bool> q(c.begin(), c.end());
218 for (std::deque<bool>::iterator it = q.begin(); it != q.end(); it++)
220 p.syncComment(sync_item);
221 p|*it;
225 template <class container,class dtype>
226 inline void PUP_stl_container(er &p,container &c) {
227 p.syncComment(sync_begin_array);
228 size_t nElem=PUP_stl_container_size(p,c);
229 PUP_stl_container_items<container, dtype>(p, c, nElem);
230 p.syncComment(sync_end_array);
233 template <class container, class K, class V>
234 inline void PUP_stl_map(er &p,container &c) {
235 p.syncComment(sync_begin_list);
236 size_t nElem=PUP_stl_container_size(p,c);
237 if (p.isUnpacking())
238 { //Unpacking: Extract each element and insert:
239 reserve_if_applicable(c, nElem);
240 for (size_t i=0;i<nElem;i++)
242 detail::TemporaryObjectHolder<K> k;
243 detail::TemporaryObjectHolder<V> v;
245 // keep in sync with std::pair
246 p.syncComment(sync_index);
247 p | k;
248 p.syncComment(sync_item);
249 p | v;
251 c.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(k.t)), std::forward_as_tuple(std::move(v.t)));
254 else
256 for (auto& kv : c)
258 p | kv;
261 p.syncComment(sync_end_list);
264 template <class T>
265 inline void operator|(er &p, typename std::vector<T> &v) {
266 if (PUP::as_bytes<T>::value) {
267 size_t nElem = PUP_stl_container_size(p, v);
268 if (p.isUnpacking()) {
269 v.resize(nElem);
270 v.shrink_to_fit();
272 PUParray(p, v.data(), nElem);
273 } else {
274 PUP_stl_container<std::vector<T>, T>(p, v);
278 template <class T>
279 inline void operator|(er &p,typename std::deque<T> &d)
280 { PUP_stl_container<std::deque<T>,T>(p,d); }
281 template <class T>
282 inline void operator|(er &p,typename std::list<T> &v)
283 { PUP_stl_container<std::list<T>,T>(p,v); }
284 template <class T>
285 inline void operator|(er &p,typename std::forward_list<T> &fl)
286 { PUP_stl_container<std::forward_list<T>,T>(p,fl); }
288 template <class V,class T,class Cmp>
289 inline void operator|(er &p,typename std::map<V,T,Cmp> &m)
290 { PUP_stl_map<std::map<V,T,Cmp>,V,T >(p,m); }
291 template <class V,class T,class Cmp>
292 inline void operator|(er &p,typename std::multimap<V,T,Cmp> &m)
293 { PUP_stl_map<std::multimap<V,T,Cmp>,V,T >(p,m); }
294 /// \warning This does not work with custom hash functions that have state
295 template <class V,class T,class Cmp>
296 inline void operator|(er &p,typename std::unordered_map<V,T,Cmp> &m)
297 { PUP_stl_map<std::unordered_map<V,T,Cmp>,V,T >(p,m); }
298 template <class V,class T,class Cmp>
299 inline void operator|(er &p,typename std::unordered_multimap<V,T,Cmp> &m)
300 { PUP_stl_map<std::unordered_multimap<V,T,Cmp>,V,T >(p,m); }
302 template <class T>
303 inline void operator|(er &p,typename std::set<T> &m)
304 { PUP_stl_container<std::set<T>,T >(p,m); }
305 template <class T,class Cmp>
306 inline void operator|(er &p,typename std::multiset<T,Cmp> &m)
307 { PUP_stl_container<std::multiset<T,Cmp>,T >(p,m); }
308 template <class T>
309 inline void operator|(er &p,typename std::unordered_set<T> &m)
310 { PUP_stl_container<std::unordered_set<T>,T >(p,m); }
311 template <class T,class Cmp>
312 inline void operator|(er &p,typename std::unordered_multiset<T,Cmp> &m)
313 { PUP_stl_container<std::unordered_multiset<T,Cmp>,T >(p,m); }
315 // Specialized to work with vector<bool>, which doesn't
316 // have data() or shrink_to_fit() members
317 template <>
318 inline void operator|(er &p,std::vector<bool> &v) {
319 PUP_stl_container<std::vector<bool>, bool>(p, v);
322 // Distributed under the MIT License.
323 // The following allows for pupping STL structures with pointers to abstract
324 // base classes. Requires is used in place of enable_if_t to enforce
325 // requirements on template parameters for the following PUP methods.
326 template <bool B>
327 struct requires_impl {
328 using template_error_type_failed_to_meet_requirements_on_template_parameters
329 = std::nullptr_t;
332 template <>
333 struct requires_impl<false> {};
335 template <bool B>
336 using Requires = typename requires_impl<
337 B>::template_error_type_failed_to_meet_requirements_on_template_parameters;
339 template <typename T, std::size_t N,
340 Requires<!PUP::as_bytes<T>::value> = nullptr>
341 inline void pup(PUP::er& p, std::array<T, N>& a) {
342 std::for_each(a.begin(), a.end(), [&p](T& t) { p | t; });
345 template <typename T, std::size_t N,
346 Requires<PUP::as_bytes<T>::value> = nullptr>
347 inline void pup(PUP::er& p, std::array<T, N>& a) {
348 PUParray(p, a.data(), N);
351 template <typename T, std::size_t N>
352 inline void operator|(er& p, std::array<T, N>& a) {
353 pup(p, a);
356 template <typename T, Requires<std::is_enum<T>::value> = nullptr>
357 inline void operator|(PUP::er& p, T& s) {
358 pup_bytes(&p, static_cast<void*>(&s), sizeof(T));
361 template <size_t N = 0, typename... Args,
362 Requires<0 == sizeof...(Args)> = nullptr>
363 void pup_tuple_impl(PUP::er& /* p */, std::tuple<Args...>& /* t */) {
366 template <size_t N = 0, typename... Args,
367 Requires<(0 < sizeof...(Args) && 0 == N)> = nullptr>
368 void pup_tuple_impl(PUP::er& p, std::tuple<Args...>& t) {
369 p | std::get<N>(t);
372 template <size_t N, typename... Args,
373 Requires<(sizeof...(Args) > 0 && N > 0)> = nullptr>
374 void pup_tuple_impl(PUP::er& p, std::tuple<Args...>& t) {
375 p | std::get<N>(t);
376 pup_tuple_impl<N - 1>(p, t);
379 template <typename... Args>
380 inline void pup(PUP::er& p, std::tuple<Args...>& t) {
381 pup_tuple_impl<sizeof...(Args) - 1>(p, t);
384 template <typename... Args>
385 inline void operator|(PUP::er& p, std::tuple<Args...>& t) {
386 pup(p, t);
389 template <typename T,
390 Requires<!std::is_base_of<PUP::able, T>::value> = nullptr>
391 inline void pup(PUP::er& p, std::unique_ptr<T>& t) {
392 bool is_nullptr = nullptr == t;
393 p | is_nullptr;
394 if (!is_nullptr) {
395 T* t1;
396 if (p.isUnpacking()) {
397 t1 = new T;
398 } else {
399 t1 = t.get();
401 p | *t1;
402 if (p.isUnpacking()) {
403 t.reset(t1);
408 template <typename T, Requires<std::is_base_of<PUP::able, T>::value> = nullptr>
409 inline void pup(PUP::er& p, std::unique_ptr<T>& t) {
410 T* t1 = nullptr;
411 if (p.isUnpacking()) {
412 p | t1;
413 t = std::unique_ptr<T>(t1);
414 } else {
415 t1 = t.get();
416 p | t1;
420 template <typename T>
421 inline void operator|(PUP::er& p, std::unique_ptr<T>& t) {
422 pup(p, t);
425 } // end of namespace PUP
427 #endif