1 | /* |
2 | * Packer_cls.hpp |
3 | * |
4 | * Created on: Jul 15, 2015 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef SRC_PACKER_HPP_ |
9 | #define SRC_PACKER_HPP_ |
10 | |
11 | #include "util/object_util.hpp" |
12 | //#include "Grid/util.hpp" |
13 | #include "Vector/util.hpp" |
14 | #include "memory/ExtPreAlloc.hpp" |
15 | #include "util/util_debug.hpp" |
16 | |
17 | |
18 | #include "Grid/grid_sm.hpp" |
19 | #include "util/Pack_stat.hpp" |
20 | #include "Pack_selector.hpp" |
21 | #include "has_pack_encap.hpp" |
22 | #include "Packer_util.hpp" |
23 | |
24 | template <typename> struct Debug; |
25 | |
26 | /*! \brief Packing class |
27 | * |
28 | * This class pack objects primitives vectors and grids, the general usage is to create a vector of |
29 | * packing request (std::vector<size_t>) that contain the size of the required space needed to pack |
30 | * the information. Calculate the total size, allocating it on HeapMemory (for example), Create an |
31 | * ExtPreAlloc memory object giving the preallocated memory to it and finally Pack all the objects |
32 | * subsequently |
33 | * |
34 | * In order to unpack the information the Unpacker class can be used |
35 | * |
36 | * \see Unpacker |
37 | * |
38 | * \snippet Packer_unit_tests.hpp Pack into a message primitives objects vectors and grids |
39 | * |
40 | * \tparam T object type to pack |
41 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
42 | * \tparam Implementation of the packer (the Pack_selector choose the correct one) |
43 | * |
44 | */ |
45 | template<typename T, typename Mem, int pack_type > |
46 | class Packer |
47 | { |
48 | public: |
49 | |
50 | /*! \brief Error, no implementation |
51 | * |
52 | */ |
53 | static void pack(ExtPreAlloc<Mem> , const T & obj) |
54 | { |
55 | #ifndef DISABLE_ALL_RTTI |
56 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " packing for the type " << demangle(typeid(T).name()) << " is not implemented\n" ; |
57 | #endif |
58 | } |
59 | |
60 | /*! \brief Error, no implementation |
61 | * |
62 | */ |
63 | static size_t packRequest(const T & obj, size_t & req) |
64 | { |
65 | #ifndef DISABLE_ALL_RTTI |
66 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " packing for the type " << demangle(typeid(T).name()) << " is not implemented\n" ; |
67 | #endif |
68 | return 0; |
69 | } |
70 | }; |
71 | |
72 | /*! \brief Packer for primitives |
73 | * |
74 | * \tparam T object type to pack |
75 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
76 | * |
77 | */ |
78 | template<typename T, typename Mem> |
79 | class Packer<T,Mem,PACKER_PRIMITIVE> |
80 | { |
81 | public: |
82 | |
83 | /*! \brief It pack any C++ primitives |
84 | * |
85 | * \param ext preallocated memory where to pack the object |
86 | * \param obj object to pack |
87 | * \param sts pack-stat info |
88 | * |
89 | */ |
90 | inline static void pack(ExtPreAlloc<Mem> & ext, const T & obj, Pack_stat & sts) |
91 | { |
92 | ext.allocate(sizeof(T)); |
93 | *(typename std::remove_const<T>::type *)ext.getPointer() = obj; |
94 | |
95 | // update statistic |
96 | sts.incReq(); |
97 | } |
98 | |
99 | /*! \brief It add a request to pack a C++ primitive |
100 | * |
101 | * \param req requests vector |
102 | * |
103 | */ |
104 | static void packRequest(const T & obj, size_t & req) |
105 | { |
106 | req += sizeof(T); |
107 | } |
108 | |
109 | /*! \brief It add a request to pack a C++ primitive |
110 | * |
111 | * \param req requests vector |
112 | * |
113 | */ |
114 | static void packRequest(size_t & req) |
115 | { |
116 | req += sizeof(T); |
117 | } |
118 | }; |
119 | |
120 | /*! \brief Packer for primitives |
121 | * |
122 | * \tparam T object type to pack |
123 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
124 | * |
125 | */ |
126 | |
127 | |
128 | template<typename T, typename Mem> |
129 | class Packer<T,Mem,PACKER_ARRAY_PRIMITIVE> |
130 | { |
131 | public: |
132 | |
133 | /*! \brief It packs arrays of C++ primitives |
134 | * |
135 | * \param ext preallocated memory where to pack the object |
136 | * \param obj object to pack |
137 | * \param sts pack-stat info |
138 | * |
139 | */ |
140 | inline static void pack(ExtPreAlloc<Mem> & ext, const T & obj, Pack_stat & sts, size_t n) |
141 | { |
142 | //Pack the size of a vector |
143 | Packer<size_t, Mem>::pack(ext,obj.size(),sts); |
144 | |
145 | //Pack a vector |
146 | ext.allocate(sizeof(typename T::value_type)*n); |
147 | memcpy(ext.getPointer(),obj.getPointer(),sizeof(typename T::value_type)*n); |
148 | |
149 | // update statistic |
150 | sts.incReq(); |
151 | } |
152 | |
153 | /*! \brief It add a request to pack a C++ primitive |
154 | * |
155 | * \param req requests vector |
156 | * |
157 | */ |
158 | static void packRequest(T & obj,size_t & req) |
159 | { |
160 | req += sizeof(typename T::value_type)*obj.size(); |
161 | } |
162 | }; |
163 | |
164 | |
165 | template<typename T, typename Mem> |
166 | class Packer<T,Mem,PACKER_ARRAY_CP_PRIMITIVE> |
167 | { |
168 | public: |
169 | |
170 | /*! \brief It packs arrays of C++ primitives |
171 | * |
172 | * \param ext preallocated memory where to pack the object |
173 | * \param obj object to pack |
174 | * \param sts pack-stat info |
175 | * |
176 | */ |
177 | inline static void pack(ExtPreAlloc<Mem> & ext, const T & obj, Pack_stat & sts) |
178 | { |
179 | typedef typename std::remove_extent<T>::type prim_type; |
180 | |
181 | //Pack a vector |
182 | ext.allocate(sizeof(T)); |
183 | |
184 | meta_copy<T>::meta_copy_(obj,(prim_type *)ext.getPointer()); |
185 | |
186 | // update statistic |
187 | sts.incReq(); |
188 | } |
189 | |
190 | /*! \brief It packs arrays of C++ primitives |
191 | * |
192 | * \param ext preallocated memory where to pack the object |
193 | * \param obj object to pack |
194 | * \param sts pack-stat info |
195 | * |
196 | */ |
197 | template<typename tp, long unsigned int dim, typename vmpl> |
198 | inline static void pack(ExtPreAlloc<Mem> & ext, |
199 | const openfpm::detail::multi_array::sub_array_openfpm<tp,dim,vmpl> & obj, |
200 | Pack_stat & sts) |
201 | { |
202 | typedef typename std::remove_extent<T>::type prim_type; |
203 | |
204 | //Pack a vector |
205 | ext.allocate(sizeof(T)); |
206 | |
207 | meta_copy<T>::meta_copy_(obj,(prim_type *)ext.getPointer()); |
208 | |
209 | // update statistic |
210 | sts.incReq(); |
211 | } |
212 | |
213 | /*! \brief It add a request to pack a C++ primitive |
214 | * |
215 | * \param req requests vector |
216 | * |
217 | */ |
218 | static void packRequest(T & obj,size_t & req) |
219 | { |
220 | req += sizeof(T); |
221 | } |
222 | |
223 | /*! \brief It add a request to pack a C++ primitive |
224 | * |
225 | * \param req requests vector |
226 | * |
227 | */ |
228 | template<typename tp, long unsigned int dim, typename vmpl> |
229 | static void packRequest(const openfpm::detail::multi_array::sub_array_openfpm<tp,dim,vmpl> & obj, |
230 | size_t & req) |
231 | { |
232 | req += sizeof(T); |
233 | } |
234 | }; |
235 | |
236 | /*! \brief Packer for objects, with impossibility to check for internal pointers |
237 | * |
238 | * \tparam T object type to pack |
239 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
240 | * |
241 | */ |
242 | template<typename T, typename Mem> |
243 | class Packer<T,Mem,PACKER_OBJECTS_WITH_WARNING_POINTERS> |
244 | { |
245 | public: |
246 | |
247 | /*! \brief It pack an object |
248 | * |
249 | * \param ext preallocated memory where to pack the objects |
250 | * \param obj object to pack |
251 | * \param sts pack-stat info |
252 | * |
253 | */ |
254 | static void pack(ExtPreAlloc<Mem> & ext, const T & obj, Pack_stat & sts) |
255 | { |
256 | #ifdef SE_CLASS1 |
257 | if (ext.ref() == 0) |
258 | std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n" ; |
259 | |
260 | if (!(std::is_array<T>::value == true && std::is_fundamental<typename std::remove_all_extents<T>::type>::value == true)) |
261 | std::cerr << "Warning: " << __FILE__ << ":" << __LINE__ << " impossible to check the type " << demangle(typeid(T).name()) << " please consider to add a static method like \"static bool noPointers() {return true;}\" \n" ; |
262 | #endif |
263 | ext.allocate(sizeof(T)); |
264 | memcpy((typename std::remove_reference<T>::type *)ext.getPointer(),&obj,sizeof(T)); |
265 | |
266 | // update statistic |
267 | sts.incReq(); |
268 | } |
269 | |
270 | /*! \brief it add a request to pack an object |
271 | * |
272 | * \param req requests vector |
273 | * |
274 | */ |
275 | static void packRequest(const T & obj,size_t & req) |
276 | { |
277 | req += sizeof(T); |
278 | } |
279 | |
280 | /*! \brief it add a request to pack an object |
281 | * |
282 | * \param req requests vector |
283 | * |
284 | */ |
285 | static void packRequest(size_t & req) |
286 | { |
287 | req += sizeof(T); |
288 | } |
289 | }; |
290 | |
291 | /*! \brief Packer class for objects |
292 | * |
293 | * \tparam T object type to pack |
294 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
295 | * |
296 | */ |
297 | template<typename T, typename Mem> |
298 | class Packer<T,Mem,PACKER_OBJECTS_WITH_POINTER_CHECK> |
299 | { |
300 | public: |
301 | |
302 | /*! \brief It pack any object checking that the object does not have pointers inside |
303 | * |
304 | * \param ext preallocated memory where to pack the objects |
305 | * \param obj object to pack |
306 | * \param sts pack-stat info |
307 | * |
308 | */ |
309 | static void pack(ExtPreAlloc<Mem> & ext, const T & obj, Pack_stat & sts) |
310 | { |
311 | #ifdef SE_CLASS1 |
312 | if (ext.ref() == 0) |
313 | std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n" ; |
314 | |
315 | if (obj.noPointers() == false) |
316 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " the type " << demangle(typeid(T).name()) << " has pointers inside, sending pointers values has no sense\n" ; |
317 | #endif |
318 | ext.allocate(sizeof(T)); |
319 | memcpy((typename std::remove_const<T>::type *)ext.getPointer(),&obj,sizeof(T)); |
320 | |
321 | // Update statistic |
322 | sts.incReq(); |
323 | } |
324 | |
325 | /*! \brief it add a request to pack an object |
326 | * |
327 | * \param req requests vector |
328 | * |
329 | */ |
330 | static void packRequest(const T & obj,size_t & req) |
331 | { |
332 | req += sizeof(T); |
333 | } |
334 | |
335 | /*! \brief it add a request to pack an object |
336 | * |
337 | * \param req requests vector |
338 | * |
339 | */ |
340 | static void packRequest(size_t & req) |
341 | { |
342 | req += sizeof(T); |
343 | } |
344 | }; |
345 | |
346 | /*! \brief Packer class for vectors |
347 | * |
348 | * \tparam T vector type to pack |
349 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
350 | * |
351 | */ |
352 | template<typename T, typename Mem> |
353 | class Packer<T,Mem,PACKER_GENERAL> |
354 | { |
355 | public: |
356 | |
357 | template<int ... prp> static void packRequest(const T & obj, size_t & req) |
358 | { |
359 | obj.template packRequest<prp...>(req); |
360 | } |
361 | |
362 | template<int ... prp> static void pack(ExtPreAlloc<Mem> & mem, const T & obj, Pack_stat & sts) |
363 | { |
364 | obj.template pack<prp...>(mem, sts); |
365 | } |
366 | }; |
367 | |
368 | /*! \brief Packer for grids and sub-grids |
369 | * |
370 | * \tparam T grid type to pack |
371 | * \tparam Mem Memory origin HeapMemory CudaMemory ... |
372 | * |
373 | */ |
374 | template<typename T, typename Mem> |
375 | class Packer<T,Mem,PACKER_GRID> |
376 | { |
377 | public: |
378 | |
379 | template<int ... prp> static void packRequest(const T & obj, size_t & req) |
380 | { |
381 | obj.template packRequest<prp...>(req); |
382 | } |
383 | |
384 | template<typename grid_sub_it_type, int ... prp> static void packRequest(T & obj, grid_sub_it_type & sub, size_t & req) |
385 | { |
386 | obj.template packRequest<prp...>(sub, req); |
387 | } |
388 | |
389 | template<int ... prp> static void pack(ExtPreAlloc<Mem> & mem, const T & obj, Pack_stat & sts) |
390 | { |
391 | obj.template pack<prp...>(mem, sts); |
392 | } |
393 | |
394 | template<typename grid_sub_it_type, int ... prp> static void pack(ExtPreAlloc<Mem> & mem, T & obj, grid_sub_it_type & sub_it, Pack_stat & sts) |
395 | { |
396 | obj.template pack<prp...>(mem, sub_it, sts); |
397 | } |
398 | }; |
399 | |
400 | template<typename T, typename Mem> |
401 | class Packer<T,Mem,PACKER_ENCAP_OBJECTS> |
402 | { |
403 | public: |
404 | |
405 | /*! \brief |
406 | * |
407 | * |
408 | */ |
409 | template<int ... prp> static void pack(ExtPreAlloc<Mem> & mem, const T & eobj, Pack_stat & sts) |
410 | { |
411 | #ifdef SE_CLASS1 |
412 | if (mem.ref() == 0) |
413 | std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n" ; |
414 | #endif |
415 | |
416 | if (has_pack_encap<T,prp ...>::result::value == true) |
417 | {call_encapPack<T,Mem,prp ...>::call_pack(eobj,mem,sts);} |
418 | else |
419 | { |
420 | if (sizeof...(prp) == 0) |
421 | { |
422 | mem.allocate(sizeof(typename T::T_type)); |
423 | encapc<1,typename T::T_type,typename memory_traits_lin< typename T::T_type >::type> enc(*static_cast<typename T::T_type::type *>(mem.getPointer())); |
424 | enc = eobj; |
425 | } |
426 | else |
427 | { |
428 | typedef object<typename object_creator<typename T::type,prp...>::type> prp_object; |
429 | mem.allocate(sizeof(prp_object)); |
430 | encapc<1,prp_object,typename memory_traits_lin< prp_object >::type> enc(*static_cast<typename prp_object::type *>(mem.getPointer())); |
431 | object_si_d<T,decltype(enc),OBJ_ENCAP,prp ... >(eobj,enc); |
432 | } |
433 | } |
434 | |
435 | // update statistic |
436 | sts.incReq(); |
437 | } |
438 | |
439 | /*! \brief |
440 | * |
441 | * |
442 | */ |
443 | template<int ... prp> void packRequest(T & eobj,size_t & req) |
444 | { |
445 | if (has_pack_encap<T>::value == true) |
446 | {call_encapPackRequest<T,Mem,prp ...>::call_packRequest(eobj,req);} |
447 | else |
448 | { |
449 | if (sizeof...(prp) == 0) |
450 | return; |
451 | |
452 | typedef object<typename object_creator<typename T::type,prp...>::type> prp_object; |
453 | |
454 | req += sizeof(prp_object); |
455 | } |
456 | } |
457 | }; |
458 | |
459 | /////////////////////////////////// |
460 | |
461 | //! It copy one element of the chunk for each property |
462 | template<typename e_src, typename e_dst> |
463 | struct copy_packer_chunk |
464 | { |
465 | //! encapsulated object source |
466 | const e_src & src; |
467 | //! encapsulated object destination |
468 | e_dst & dst; |
469 | |
470 | //! element to copy |
471 | size_t sub_id; |
472 | |
473 | /*! \brief constructor |
474 | * |
475 | * |
476 | * \param src source encapsulated object |
477 | * \param dst destination encapsulated object |
478 | * |
479 | */ |
480 | inline copy_packer_chunk(const e_src & src, size_t sub_id, e_dst & dst) |
481 | :src(src),dst(dst),sub_id(sub_id) |
482 | { |
483 | }; |
484 | |
485 | |
486 | |
487 | //! It call the copy function for each property |
488 | template<typename T> |
489 | inline void operator()(T& t) const |
490 | { |
491 | // Remove the reference from the type to copy |
492 | typedef typename boost::remove_reference<decltype(dst.template get< T::value >())>::type copy_rtype; |
493 | |
494 | meta_copy<copy_rtype>::meta_copy_(src.template get< T::value >()[sub_id],dst.template get< T::value >()); |
495 | } |
496 | }; |
497 | |
498 | template <typename> struct Debug; |
499 | |
500 | template<bool is_not_zero, typename T, typename T_nc, int ... prp> |
501 | struct selector_chunking_prp_has_zero_size |
502 | { |
503 | template<typename Mem> static inline void select(ExtPreAlloc<Mem> & mem, const T & eobj, size_t sub_id) |
504 | { |
505 | mem.allocate(sizeof(T_nc)); |
506 | encapc<1,T_nc,typename memory_traits_lin< T_nc >::type> enc(*static_cast<typename T_nc::type *>(mem.getPointer())); |
507 | copy_packer_chunk<decltype(eobj), |
508 | encapc<1,T_nc,typename memory_traits_lin< T_nc >::type>> cp(eobj,sub_id,enc); |
509 | boost::mpl::for_each_ref<boost::mpl::range_c<int,0,T::T_type::max_prop>>(cp); |
510 | //enc = eobj[sub_id]; |
511 | } |
512 | }; |
513 | |
514 | template<typename T, typename T_nc, int ... prp> |
515 | struct selector_chunking_prp_has_zero_size<true,T,T_nc,prp...> |
516 | { |
517 | template<typename Mem> static inline void select(ExtPreAlloc<Mem> & mem, const T & eobj, size_t sub_id) |
518 | { |
519 | // Here we create an encap without array extent |
520 | typedef object<typename object_creator_chunking<typename T::type,prp...>::type> prp_object; |
521 | mem.allocate(sizeof(prp_object)); |
522 | encapc<1,prp_object,typename memory_traits_lin< prp_object>::type> enc(*static_cast<typename prp_object::type *>(mem.getPointer())); |
523 | object_si_d<T,decltype(enc),OBJ_ENCAP_CHUNKING,prp ... >(eobj,sub_id,enc); |
524 | } |
525 | }; |
526 | |
527 | template<typename T, typename Mem> |
528 | class Packer<T,Mem,PACKER_ENCAP_OBJECTS_CHUNKING> |
529 | { |
530 | public: |
531 | |
532 | /*! \brief Pack the encapsulkated object |
533 | * |
534 | * \tparam Base object without chunking |
535 | * |
536 | */ |
537 | template<typename T_nc, int ... prp> static void pack(ExtPreAlloc<Mem> & mem, const T & eobj, size_t sub_id, Pack_stat & sts) |
538 | { |
539 | #ifdef SE_CLASS1 |
540 | if (mem.ref() == 0) |
541 | std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n" ; |
542 | #endif |
543 | |
544 | if (has_pack_encap<T,prp ...>::result::value == true) |
545 | {call_encapPackChunking<T,Mem,prp ...>::call_pack(eobj,sub_id,mem,sts);} |
546 | else |
547 | { |
548 | selector_chunking_prp_has_zero_size<sizeof...(prp) != 0,T, T_nc, prp ...>::select(mem,eobj,sub_id); |
549 | } |
550 | |
551 | // update statistic |
552 | sts.incReq(); |
553 | } |
554 | |
555 | /*! \brief |
556 | * |
557 | * |
558 | */ |
559 | template<int ... prp> void packRequest(T & eobj,size_t & req) |
560 | { |
561 | if (has_pack_encap<T>::value == true) |
562 | call_encapPackRequest<T,Mem,prp ...>::call_packRequest(eobj,req); |
563 | else |
564 | { |
565 | if (sizeof...(prp) == 0) |
566 | return; |
567 | |
568 | typedef object<typename object_creator<typename T::type,prp...>::type> prp_object; |
569 | |
570 | req += sizeof(prp_object); |
571 | } |
572 | } |
573 | }; |
574 | |
575 | #endif /* SRC_PACKER_HPP_ */ |
576 | |