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 | */ |
32 | template<typename T, typename Mem, int pack_type > |
33 | class Unpacker |
34 | { |
35 | public: |
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 | */ |
54 | template<typename T, typename Mem> |
55 | class Unpacker<T,Mem,PACKER_PRIMITIVE> |
56 | { |
57 | public: |
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 | |
75 | template<typename T, typename Mem> |
76 | class Unpacker<T,Mem,PACKER_ARRAY_PRIMITIVE> |
77 | { |
78 | |
79 | |
80 | public: |
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 | |
105 | template <typename T, bool is_array> |
106 | struct get_pointer_unpack |
107 | { |
108 | static void * getpointer(T & obj) |
109 | { |
110 | return &obj; |
111 | } |
112 | }; |
113 | |
114 | template <typename T> |
115 | struct get_pointer_unpack<T,true> |
116 | { |
117 | static void * getpointer(T & obj) |
118 | { |
119 | return obj; |
120 | } |
121 | }; |
122 | |
123 | template<typename T, typename Mem> |
124 | class 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 | |
134 | public: |
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 | */ |
175 | template<typename T, typename Mem> |
176 | class Unpacker<T,Mem,PACKER_OBJECTS_WITH_WARNING_POINTERS> |
177 | { |
178 | public: |
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 | */ |
203 | template<typename T, typename Mem> |
204 | class Unpacker<T,Mem,PACKER_OBJECTS_WITH_POINTER_CHECK> |
205 | { |
206 | public: |
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 | */ |
228 | template<typename T, typename Mem> |
229 | class Unpacker<T,Mem,PACKER_GENERAL> |
230 | { |
231 | public: |
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 | */ |
253 | template<typename T, typename Mem> |
254 | class Unpacker<T,Mem,PACKER_GRID> |
255 | { |
256 | public: |
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 (ExtPreAlloc<Mem> & mem, |
274 | grid_sub_it_type & sub_it, |
275 | T & obj, |
276 | header_type & , |
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 | |
287 | template<unsigned int prop, typename T> |
288 | struct 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 | |
308 | template<unsigned int prop, typename T, unsigned int N1> |
309 | struct 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 |
336 | template<typename e_src, typename e_dst> |
337 | struct 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 | */ |
377 | template<typename T, typename Mem> |
378 | class Unpacker<T,Mem,PACKER_ENCAP_OBJECTS_CHUNKING> |
379 | { |
380 | public: |
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 | |