1/*
2 * Unpacker.hpp
3 *
4 * Created on: Jul 17, 2015
5 * Author: i-bird
6 */
7
8#ifndef SRC_UNPACKER_HPP_
9#define SRC_UNPACKER_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#include "Pack_selector.hpp"
17#include "util/Pack_stat.hpp"
18#include "memory/PtrMemory.hpp"
19#include "Packer_util.hpp"
20#include "util/multi_array_openfpm/multi_array_ref_openfpm.hpp"
21#include "has_pack_encap.hpp"
22#include "util/object_creator.hpp"
23#include "Grid/grid_common.hpp"
24
25/*! \brief Unpacker class
26 *
27 * \tparam T object type to unpack
28 * \tparam Mem Memory origin HeapMemory CudaMemory ...
29 * \tparam Implementation of the unpacker (the Pack_selector choose the correct one)
30 *
31 */
32template<typename T, typename Mem, int pack_type >
33class Unpacker
34{
35public:
36
37 /*! \brief Error, no implementation
38 *
39 */
40 static void unpack(ExtPreAlloc<Mem> , T & obj)
41 {
42#ifndef DISABLE_ALL_RTTI
43 std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " packing for the type " << demangle(typeid(T).name()) << " is not implemented\n";
44#endif
45 }
46};
47
48/*! \brief Unpacker for primitives
49 *
50 * \tparam T object type to unpack
51 * \tparam Mem Memory origin HeapMemory CudaMemory ...
52 *
53 */
54template<typename T, typename Mem>
55class Unpacker<T,Mem,PACKER_PRIMITIVE>
56{
57public:
58
59
60 /*! \brief It unpack C++ primitives
61 *
62 * \param ext preallocated memory from where to unpack the object
63 * \param obj object where to unpack
64 *
65 */
66 static void unpack(ExtPreAlloc<Mem> & ext, T & obj,Unpack_stat & ps)
67 {
68 T * ptr = static_cast<T *>(ext.getPointerOffset(ps.getOffset()));
69 obj = *ptr;
70
71 ps.addOffset(sizeof(T));
72 }
73};
74
75template<typename T, typename Mem>
76class Unpacker<T,Mem,PACKER_ARRAY_PRIMITIVE>
77{
78
79
80public:
81
82
83 /*! \brief It unpack C++ primitives
84 *
85 * \param ext preallocated memory from where to unpack the object
86 * \param obj object where to unpack
87 *
88 */
89 static void unpack(ExtPreAlloc<Mem> & ext, T & obj, Unpack_stat & ps)
90 {
91
92 //Unpacking a size of a source vector
93 size_t u2 = 0;
94 Unpacker<size_t, Mem>::unpack(ext,u2,ps);
95
96 //Resize a destination vector
97 obj.resize(u2);
98
99 memcpy(obj.getPointer(),ext.getPointerOffset(ps.getOffset()),sizeof(typename T::value_type)*obj.size());
100
101 ps.addOffset(sizeof(typename T::value_type)*obj.size());
102 }
103};
104
105template <typename T, bool is_array>
106struct get_pointer_unpack
107{
108 static void * getpointer(T & obj)
109 {
110 return &obj;
111 }
112};
113
114template <typename T>
115struct get_pointer_unpack<T,true>
116{
117 static void * getpointer(T & obj)
118 {
119 return obj;
120 }
121};
122
123template<typename T, typename Mem>
124class Unpacker<T,Mem,PACKER_ARRAY_CP_PRIMITIVE>
125{
126 //! base type of the primitive arrat
127 typedef typename std::remove_all_extents<T>::type base_type;
128
129 //! numver of extents in the primitive array
130 typedef typename boost::mpl::int_<std::rank<T>::value> n_ext;
131
132 typedef typename to_memory_multi_array_ref_view<T>::vmpl vmpl;
133
134public:
135
136 /*! \brief It packs arrays of C++ primitives
137 *
138 * \param ext preallocated memory where to pack the object
139 * \param obj object to pack
140 * \param sts pack-stat info
141 *
142 */
143 inline static void unpack(ExtPreAlloc<Mem> & ext, T & obj, Unpack_stat & ps)
144 {
145 typedef typename std::remove_extent<T>::type prim_type;
146
147 meta_copy<T>::meta_copy_((prim_type *)ext.getPointerOffset(ps.getOffset()),obj);
148
149 ps.addOffset(sizeof(T));
150 }
151
152 /*! \brief It unpack C++ primitives
153 *
154 * \param ext preallocated memory from where to unpack the object
155 * \param obj object where to unpack
156 *
157 */
158 static void unpack(ExtPreAlloc<Mem> & ext,
159 typename openfpm::multi_array_ref_openfpm<base_type,n_ext::value+1,vmpl>::reference obj,
160 Unpack_stat & ps)
161 {
162 meta_copy_d<T,typename openfpm::multi_array_ref_openfpm<base_type,n_ext::value+1,vmpl>::reference>
163 ::meta_copy_d_(*static_cast<T *>(ext.getPointerOffset(ps.getOffset())),obj);
164
165 ps.addOffset(sizeof(T));
166 }
167};
168
169/*! \brief Unpacker for objects with no possibility to check for internal pointers
170 *
171 * \tparam T object type to unpack
172 * \tparam Mem Memory origin HeapMemory CudaMemory ...
173 *
174 */
175template<typename T, typename Mem>
176class Unpacker<T,Mem,PACKER_OBJECTS_WITH_WARNING_POINTERS>
177{
178public:
179
180 /*! \brief unpack object
181 *
182 * \param ext preallocated memory from where to unpack the object
183 * \param obj object where to unpack
184 * \param ps unpack statistic
185 *
186 */
187 static void unpack(ExtPreAlloc<Mem> & ext, T & obj, Unpack_stat & ps)
188 {
189 memcpy(get_pointer_unpack<T,std::is_array<T>::value>::getpointer(obj),
190 (void *)ext.getPointerOffset(ps.getOffset()),
191 sizeof(T));
192
193 ps.addOffset(sizeof(T));
194 }
195};
196
197/*! \brief Unpacker class for objects
198 *
199 * \tparam T object type to unpack
200 * \tparam Mem Memory origin HeapMemory CudaMemory ...
201 *
202 */
203template<typename T, typename Mem>
204class Unpacker<T,Mem,PACKER_OBJECTS_WITH_POINTER_CHECK>
205{
206public:
207
208 /*! \brief It unpack any object checking that the object does not have pointers inside
209 *
210 * \param ext preallocated memory from where to unpack the object
211 * \param obj object where to unpack
212 *
213 */
214 static void unpack(ExtPreAlloc<Mem> & ext, T & obj, Unpack_stat & ps)
215 {
216 memcpy(&obj,(T *)ext.getPointerOffset(ps.getOffset()),sizeof(T));
217
218 ps.addOffset(sizeof(T));
219 }
220};
221
222/*! \brief Unpacker for vectors
223 *
224 * \tparam T object type to unpack
225 * \tparam Mem Memory origin HeapMemory CudaMemory ...
226 *
227 */
228template<typename T, typename Mem>
229class Unpacker<T,Mem,PACKER_GENERAL>
230{
231public:
232
233 template<unsigned int ... prp> void static unpack(ExtPreAlloc<Mem> & mem, T & obj, Unpack_stat & ps)
234 {
235 obj.template unpack<prp...>(mem, ps);
236 }
237
238 template<unsigned int ... prp> void static unpack(ExtPreAlloc<Mem> & mem, T & obj, Unpack_stat & ps, size_t n)
239 {
240 if (mem.size() == 0)
241 return;
242
243 obj.template unpack<prp...>(mem, ps);
244 }
245};
246
247/*! \brief Unpacker for grids
248 *
249 * \tparam T object type to unpack
250 * \tparam Mem Memory origin HeapMemory CudaMemory ...
251 *
252 */
253template<typename T, typename Mem>
254class Unpacker<T,Mem,PACKER_GRID>
255{
256public:
257
258 template<unsigned int ... prp> static void unpack(ExtPreAlloc<Mem> & mem, T & obj, Unpack_stat & ps)
259 {
260 obj.template unpack<prp...>(mem, ps);
261 }
262
263 template<typename grid_sub_it_type,
264 typename context_type,
265 unsigned int ... prp> static void unpack(ExtPreAlloc<Mem> & mem, grid_sub_it_type & sub_it, T & obj, Unpack_stat & ps, context_type & context, rem_copy_opt opt)
266 {
267 obj.template unpack<prp...>(mem, sub_it, ps, context, opt);
268 }
269
270 template<typename grid_sub_it_type,
271 typename header_type,
272 typename context_type,
273 unsigned int ... prp> static void unpack_with_header(ExtPreAlloc<Mem> & mem,
274 grid_sub_it_type & sub_it,
275 T & obj,
276 header_type & header,
277 int ih,
278 Unpack_stat & ps,
279 context_type & context,
280 rem_copy_opt opt)
281 {
282 obj.template unpack_with_headers<prp...>(mem, sub_it, header, ih, ps, context, opt);
283 }
284};
285
286
287template<unsigned int prop, typename T>
288struct std_array_copy_chunks
289{
290 template<typename Tsrc, typename Tdst>
291 static void copy(Tsrc & src, Tdst & dst, size_t pos)
292 {
293 typedef typename std::remove_reference<decltype(dst.template get<prop>()[0])>::type copy_rtype;
294
295 meta_copy<copy_rtype>::meta_copy_(src.template get<prop>()[0],dst.template get<prop>()[pos]);
296 }
297
298 template<typename Tsrc, typename Tdst>
299 static void copy_unpack(Tsrc & src, Tdst & dst, size_t pos)
300 {
301 // Remove the reference from the type to copy
302 typedef typename boost::remove_reference<decltype(src.template get< prop >())>::type copy_rtype;
303
304 meta_copy<copy_rtype>::meta_copy_(src.template get< prop >(),dst.template get< prop >()[pos]);
305 }
306};
307
308template<unsigned int prop, typename T, unsigned int N1>
309struct std_array_copy_chunks<prop,T[N1]>
310{
311 template<typename Tsrc, typename Tdst>
312 static void copy(Tsrc & src, Tdst & dst, size_t pos)
313 {
314 typedef typename std::remove_reference<decltype(dst.template get<prop>()[0][pos])>::type copy_rtype;
315
316 for (int i = 0 ; i < N1 ; i++)
317 {
318 meta_copy<copy_rtype>::meta_copy_(dst.template get<prop>()[i][pos],src.template get<prop>()[i][0]);
319 }
320 }
321
322 template<typename Tsrc, typename Tdst>
323 static void copy_unpack(Tsrc & src, Tdst & dst, size_t pos)
324 {
325 // Remove the reference from the type to copy
326 typedef typename boost::remove_reference<decltype(src.template get< prop >()[0])>::type copy_rtype;
327
328 for (int i = 0 ; i < N1 ; i++)
329 {
330 meta_copy<copy_rtype>::meta_copy_(src.template get< prop >()[i],dst.template get< prop >()[i][pos]);
331 }
332 }
333};
334
335//! It copy one element of the chunk for each property
336template<typename e_src, typename e_dst>
337struct copy_unpacker_chunk
338{
339 //! encapsulated object source
340 const e_src & src;
341 //! encapsulated object destination
342 e_dst & dst;
343
344 //! element to copy
345 size_t sub_id;
346
347 /*! \brief constructor
348 *
349 *
350 * \param src source encapsulated object
351 * \param dst destination encapsulated object
352 *
353 */
354 inline copy_unpacker_chunk(const e_src & src, e_dst & dst, size_t sub_id)
355 :src(src),dst(dst),sub_id(sub_id)
356 {
357 };
358
359
360
361 //! It call the copy function for each property
362 template<typename T>
363 inline void operator()(T& t) const
364 {
365 typedef typename std::remove_reference<decltype(src.template get<T::value>())>::type copy_rtype;
366
367 std_array_copy_chunks<T::value,copy_rtype>::copy_unpack(src,dst,sub_id);
368 }
369};
370
371/*! \brief Unpacker for encapsulated objects
372 *
373 * \tparam T object type to unpack
374 * \tparam Mem Memory origin HeapMemory CudaMemory ...
375 *
376 */
377template<typename T, typename Mem>
378class Unpacker<T,Mem,PACKER_ENCAP_OBJECTS_CHUNKING>
379{
380public:
381
382 /*! \brief
383 *
384 * is this needed
385 *
386 */
387 template<typename T_nc, unsigned int ... prp>
388 static void unpack(ExtPreAlloc<Mem> & mem,
389 T & obj,
390 size_t sub_id,
391 Unpack_stat & ps)
392 {
393 if (has_pack_encap<T,prp ...>::result::value == true)
394 {call_encapUnpackChunking<T,Mem,prp ...>::call_unpack(obj,sub_id,mem,ps);}
395 else
396 {
397 // get the first element to get the chunking size
398 typedef typename boost::mpl::at<typename T::T_type::type,boost::mpl::int_<0>>::type cnk_size;
399
400 if (sizeof...(prp) == 0)
401 {
402 encapc<1,T_nc,typename memory_traits_lin< T_nc >::type> enc(*static_cast<typename T_nc::type *>((void *)((unsigned char *)mem.getPointerBase() + ps.getOffset())));
403 copy_unpacker_chunk<encapc<1,T_nc,typename memory_traits_lin< T_nc >::type>,
404 decltype(obj)> cp(enc,obj,sub_id);
405
406 boost::mpl::for_each_ref<boost::mpl::range_c<int,0,T::T_type::max_prop>>(cp);
407 ps.addOffset(sizeof(T_nc));
408 }
409 else
410 {
411 typedef object<typename object_creator_chunking<typename T::type,prp...>::type> prp_object;
412 encapc<1,prp_object,typename memory_traits_lin< prp_object >::type> enc(*static_cast<typename prp_object::type *>((void *)((unsigned char *)mem.getPointerBase() + ps.getOffset())));
413 object_s_di<decltype(enc),T,OBJ_ENCAP_CHUNKING,prp ... >(enc,obj,sub_id);
414 ps.addOffset(sizeof(prp_object));
415 }
416 }
417
418 // update statistic
419 }
420
421 /*! \brief
422 *
423 * is this needed
424 *
425 */
426 template<template<typename,typename> class op, unsigned int ... prp>
427 static void unpack_op(ExtPreAlloc<Mem> & mem,
428 T & obj,
429 size_t sub_id,
430 Unpack_stat & ps)
431 {
432 if (has_pack_encap<T,prp ...>::result::value == true)
433 {call_encapUnpackChunking<T,Mem,prp ...>::call_unpack(obj,sub_id,mem,ps);}
434 else
435 {
436 if (sizeof...(prp) == 0)
437 {
438 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()));
439 copy_unpacker_chunk<encapc<1,typename T::T_type,typename memory_traits_lin< typename T::T_type >::type>,
440 decltype(obj)>(enc,obj,sub_id);
441 ps.addOffset(sizeof(typename T::T_type));
442 }
443 else
444 {
445 typedef object<typename object_creator_chunking<typename T::type,prp...>::type> prp_object;
446 encapc<1,prp_object,typename memory_traits_lin< prp_object >::type> enc(*static_cast<typename prp_object::type *>((void *)((unsigned char *)mem.getPointerBase() + ps.getOffset())));
447 object_s_di_op<op,decltype(enc),T,OBJ_ENCAP_CHUNKING,prp ... >(enc,obj,sub_id);
448 ps.addOffset(sizeof(prp_object));
449 }
450 }
451
452 // update statistic
453 }
454};
455
456
457
458#endif /* SRC_UNPACKER_HPP_ */
459