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
24template <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 */
45template<typename T, typename Mem, int pack_type >
46class Packer
47{
48public:
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 */
78template<typename T, typename Mem>
79class Packer<T,Mem,PACKER_PRIMITIVE>
80{
81public:
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
128template<typename T, typename Mem>
129class Packer<T,Mem,PACKER_ARRAY_PRIMITIVE>
130{
131public:
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
165template<typename T, typename Mem>
166class Packer<T,Mem,PACKER_ARRAY_CP_PRIMITIVE>
167{
168public:
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 */
242template<typename T, typename Mem>
243class Packer<T,Mem,PACKER_OBJECTS_WITH_WARNING_POINTERS>
244{
245public:
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 */
297template<typename T, typename Mem>
298class Packer<T,Mem,PACKER_OBJECTS_WITH_POINTER_CHECK>
299{
300public:
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 */
352template<typename T, typename Mem>
353class Packer<T,Mem,PACKER_GENERAL>
354{
355public:
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 */
374template<typename T, typename Mem>
375class Packer<T,Mem,PACKER_GRID>
376{
377public:
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
400template<typename T, typename Mem>
401class Packer<T,Mem,PACKER_ENCAP_OBJECTS>
402{
403public:
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
462template<typename e_src, typename e_dst>
463struct 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
498template <typename> struct Debug;
499
500template<bool is_not_zero, typename T, typename T_nc, int ... prp>
501struct 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
514template<typename T, typename T_nc, int ... prp>
515struct 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
527template<typename T, typename Mem>
528class Packer<T,Mem,PACKER_ENCAP_OBJECTS_CHUNKING>
529{
530public:
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