1 | /* |
2 | * Packer_util.hpp |
3 | * |
4 | * Created on: Jan 25, 2016 |
5 | * Author: Yaroslav Zaluzhnyi |
6 | */ |
7 | |
8 | #ifndef PACKER_UTIL_HPP_ |
9 | #define PACKER_UTIL_HPP_ |
10 | |
11 | #include "prp_all_zero.hpp" |
12 | #include "Packer_Unpacker/Pack_selector.hpp" |
13 | #include "memory/HeapMemory.hpp" |
14 | #include "Vector/map_vector_grow_p.hpp" |
15 | #include "Vector/vect_isel.hpp" |
16 | #include "memory_ly/memory_conf.hpp" |
17 | #include "util/Pack_stat.hpp" |
18 | |
19 | template<typename T, typename Mem, int pack_type=Pack_selector<T>::value > class Packer; |
20 | template<typename T, typename Mem, int pack_type=Pack_selector<T>::value > class Unpacker; |
21 | |
22 | #include "Vector/vector_def.hpp" |
23 | |
24 | /////////////////////////////////////////////////////////////////////////////////// |
25 | //////////////////////////////// FUNCTORS FOR ENCAP //////////////////////////////// |
26 | //////////////////////////////////////////////////////////////////////////////////// |
27 | |
28 | |
29 | //A functor for call_aggregatePackRequest |
30 | template<typename encap, typename Mem> |
31 | struct call_packRequest_enc_functor |
32 | { |
33 | //! encap object to pack (serialize) |
34 | encap & obj; |
35 | |
36 | //! byte counter |
37 | size_t & req; |
38 | |
39 | /* \brief Constructor |
40 | * |
41 | * \param obj object to pack/serialize |
42 | * \param req byte to pack/serialize |
43 | * |
44 | */ |
45 | call_packRequest_enc_functor(encap & obj, size_t & req) |
46 | :obj(obj),req(req) |
47 | {} |
48 | |
49 | //! It calls the pack request for each property |
50 | template<typename T> |
51 | inline void operator()(T& t) |
52 | { |
53 | typedef typename boost::mpl::at<typename encap::T_type,T>::type obj_type; |
54 | |
55 | Packer<obj_type,Mem>::packRequest(obj.template get<T::value>(),req); |
56 | } |
57 | }; |
58 | |
59 | |
60 | //Calls a pack request in nested way |
61 | template<typename encap, typename Mem, int ... prp> |
62 | struct call_encapPackRequest |
63 | { |
64 | /*! \brief pack/serialize |
65 | * |
66 | * \param obj object to serialize |
67 | * \param req byte counter needed to pack/serialize the object |
68 | * |
69 | */ |
70 | static inline void call_packRequest(encap & obj, size_t & req) |
71 | { |
72 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
73 | typedef typename prp_all_zero<encap,sizeof...(prp) == 0,prp...>::type b_prp; |
74 | |
75 | call_packRequest_enc_functor<encap,Mem> functor(obj,req); |
76 | |
77 | //Apply functor for each property |
78 | boost::mpl::for_each_ref<b_prp>(functor); |
79 | } |
80 | }; |
81 | |
82 | //A functor for call_aggregatePack |
83 | template<typename encap, typename Mem> |
84 | struct call_pack_enc_functor |
85 | { |
86 | //! Memory that pack/serialize the object |
87 | ExtPreAlloc<Mem> & mem; |
88 | |
89 | //! Object to serialize |
90 | const encap & obj; |
91 | |
92 | //! serialization status |
93 | Pack_stat & sts; |
94 | |
95 | call_pack_enc_functor(ExtPreAlloc<Mem> & mem,const encap & obj, Pack_stat & sts) |
96 | :mem(mem), obj(obj), sts(sts) |
97 | { |
98 | } |
99 | |
100 | //! It calls the packer for each property |
101 | template<typename T> |
102 | inline void operator()(T& t) |
103 | { |
104 | typedef typename boost::mpl::at<typename encap::type,T>::type obj_type; |
105 | |
106 | Packer<obj_type,Mem>::pack(mem,obj.template get<T::value>(),sts); |
107 | } |
108 | }; |
109 | |
110 | //A functor for call_aggregatePack |
111 | template<typename encap, typename Mem> |
112 | struct call_pack_enc_functor_chunking |
113 | { |
114 | //! Memory that pack/serialize the object |
115 | ExtPreAlloc<Mem> & mem; |
116 | |
117 | //! Object to serialize |
118 | const encap & obj; |
119 | |
120 | //! Element id |
121 | size_t sub_id; |
122 | |
123 | //! serialization status |
124 | Pack_stat & sts; |
125 | |
126 | call_pack_enc_functor_chunking(ExtPreAlloc<Mem> & mem,const encap & obj, size_t sub_id, Pack_stat & sts) |
127 | :mem(mem), obj(obj),sub_id(sub_id),sts(sts) |
128 | { |
129 | } |
130 | |
131 | //! It calls the packer for each property |
132 | template<typename T> |
133 | inline void operator()(T& t) |
134 | { |
135 | typedef typename boost::mpl::at<typename encap::type,T>::type::value_type obj_type; |
136 | |
137 | Packer<obj_type,Mem>::pack(mem,obj.template get<T::value>()[sub_id],sts); |
138 | } |
139 | }; |
140 | |
141 | //Calls a packer in nested way |
142 | template<typename encap, typename Mem, int ... prp> |
143 | struct call_encapPack |
144 | { |
145 | static inline void call_pack(const encap & obj, ExtPreAlloc<Mem> & mem, Pack_stat & sts) |
146 | { |
147 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
148 | typedef typename prp_all_zero<typename encap::T_type,sizeof...(prp) == 0,prp...>::type b_prp; |
149 | |
150 | call_pack_enc_functor<encap,Mem> functor(mem,obj,sts); |
151 | |
152 | //Apply functor for each property |
153 | boost::mpl::for_each_ref<b_prp>(functor); |
154 | } |
155 | }; |
156 | |
157 | //Calls a packer in nested way |
158 | template<typename encap, typename Mem, int ... prp> |
159 | struct call_encapPackChunking |
160 | { |
161 | static inline void call_pack(const encap & obj, size_t sub_id, ExtPreAlloc<Mem> & mem, Pack_stat & sts) |
162 | { |
163 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
164 | typedef typename prp_all_zero<typename encap::T_type,sizeof...(prp) == 0,prp...>::type b_prp; |
165 | |
166 | call_pack_enc_functor_chunking<encap,Mem> functor(mem,obj,sub_id,sts); |
167 | |
168 | //Apply functor for each property |
169 | boost::mpl::for_each_ref<b_prp>(functor); |
170 | } |
171 | }; |
172 | |
173 | //A functor for call_aggregateUnpack |
174 | template<typename encap, typename Mem, int ... prp> |
175 | struct call_unpack_encap_functor |
176 | { |
177 | ExtPreAlloc<Mem> & mem; |
178 | const encap & obj; |
179 | Unpack_stat & ps; |
180 | |
181 | call_unpack_encap_functor(ExtPreAlloc<Mem> & mem, const encap & obj, Unpack_stat & ps) |
182 | :mem(mem), obj(obj), ps(ps) |
183 | { |
184 | } |
185 | |
186 | //! It calls the unpacker for each property |
187 | template<typename T> |
188 | inline void operator()(T& t) |
189 | { |
190 | typedef typename boost::mpl::at<typename encap::type,T>::type obj_type; |
191 | |
192 | Unpacker<obj_type,Mem>::unpack(mem,obj.template get<T::value>(),ps); |
193 | } |
194 | }; |
195 | |
196 | //A functor for call_aggregateUnpack |
197 | template<typename encap, typename Mem, int ... prp> |
198 | struct call_unpack_encap_functor_chunking |
199 | { |
200 | ExtPreAlloc<Mem> & mem; |
201 | const encap & obj; |
202 | Unpack_stat & ps; |
203 | |
204 | size_t sub_id; |
205 | |
206 | call_unpack_encap_functor_chunking(ExtPreAlloc<Mem> & mem, const encap & obj, size_t sub_id, Unpack_stat & ps) |
207 | :mem(mem), obj(obj), ps(ps),sub_id(sub_id) |
208 | { |
209 | } |
210 | |
211 | //! It calls the unpacker for each property |
212 | template<typename T> |
213 | inline void operator()(T& t) |
214 | { |
215 | typedef typename boost::mpl::at<typename encap::type,T>::type::value_type obj_type; |
216 | |
217 | Unpacker<obj_type,Mem>::unpack(mem,obj.template get<T::value>()[sub_id],ps); |
218 | } |
219 | }; |
220 | |
221 | //Calls an unpacker in nested way |
222 | template<typename encap, typename Mem, int ... prp> |
223 | struct call_encapUnpack |
224 | { |
225 | static inline void call_unpack(encap & obj, ExtPreAlloc<Mem> & mem, Unpack_stat & ps) |
226 | { |
227 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
228 | typedef typename prp_all_zero<encap,sizeof...(prp) == 0,prp...>::type b_prp; |
229 | |
230 | call_unpack_encap_functor_chunking<encap,Mem,prp ... > functor(mem,obj,ps); |
231 | |
232 | //Apply functor for each property |
233 | boost::mpl::for_each_ref<b_prp>(functor); |
234 | } |
235 | }; |
236 | |
237 | //Calls an unpacker in nested way |
238 | template<typename encap, typename Mem, int ... prp> |
239 | struct call_encapUnpackChunking |
240 | { |
241 | static inline void call_unpack(encap & obj, size_t sub_id, ExtPreAlloc<Mem> & mem, Unpack_stat & ps) |
242 | { |
243 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
244 | typedef typename prp_all_zero<encap,sizeof...(prp) == 0,prp...>::type b_prp; |
245 | |
246 | call_unpack_encap_functor_chunking<encap,Mem,prp ... > functor(mem,obj,sub_id,ps); |
247 | |
248 | //Apply functor for each property |
249 | boost::mpl::for_each_ref<b_prp>(functor); |
250 | } |
251 | }; |
252 | |
253 | |
254 | //////////////////////////////////////////////////////////////////////////////////// |
255 | /////////////////////////////// FUNCTORS FOR AGGREGATE //////////////////////////// |
256 | //////////////////////////////////////////////////////////////////////////////////// |
257 | |
258 | |
259 | template<bool inte_layout, typename obj_type, typename Mem> |
260 | struct pack_request_op |
261 | { |
262 | template<unsigned int p> static inline void call_pack_req(const obj_type & obj,size_t & req) |
263 | { |
264 | typedef typename boost::mpl::at<typename obj_type::type,boost::mpl::int_<p>>::type obj_t; |
265 | |
266 | Packer<obj_t,Mem>::packRequest(obj.template get<p>(),req); |
267 | } |
268 | }; |
269 | |
270 | template<typename obj_type, typename Mem> |
271 | struct pack_request_op<true,obj_type,Mem> |
272 | { |
273 | template<unsigned int p> static inline void call_pack_req(const obj_type & obj,size_t & req) |
274 | { |
275 | typedef typename boost::mpl::at<typename obj_type::type,boost::mpl::int_<p>>::type obj_t; |
276 | |
277 | Packer<obj_t,Mem>::packRequest(obj.template get<p>(),req); |
278 | } |
279 | }; |
280 | |
281 | template<typename> struct Debug; |
282 | |
283 | //A functor for call_aggregatePackRequest |
284 | |
285 | template<typename obj_type, typename Mem> |
286 | struct call_packRequest_agg_functor |
287 | { |
288 | //! object to pack |
289 | const obj_type & obj; |
290 | |
291 | //! offset of the packed memory |
292 | size_t & req; |
293 | |
294 | call_packRequest_agg_functor(const obj_type & obj, size_t & req) |
295 | :obj(obj),req(req) |
296 | {} |
297 | |
298 | //! It calls the pack request for each property |
299 | template<typename T> |
300 | inline void operator()(T& t) |
301 | { |
302 | pack_request_op<openfpm::is_multi_array<decltype(obj.template get<T::value>())>::value,obj_type,Mem>::template call_pack_req<T::value>(obj,req); |
303 | } |
304 | }; |
305 | |
306 | template<typename obj_type, typename Mem> |
307 | struct call_packRequest_agg_functor_cnk |
308 | { |
309 | //! object to pack |
310 | const obj_type & obj; |
311 | |
312 | //! offset of the packed memory |
313 | size_t & req; |
314 | |
315 | //! element id |
316 | size_t sub_id; |
317 | |
318 | call_packRequest_agg_functor_cnk(const obj_type & obj, size_t sub_id ,size_t & req) |
319 | :obj(obj),req(req),sub_id(sub_id) |
320 | {} |
321 | |
322 | //! It calls the pack request for each property |
323 | template<typename T> |
324 | inline void operator()(T& t) |
325 | { |
326 | typedef decltype(obj.template get<T::value>()[sub_id]) obj_t; |
327 | |
328 | //for (size_t i = 0; i < obj_type::max_prop ; i++) |
329 | Packer<obj_t,Mem>::packRequest(obj.template get<T::value>()[sub_id],req); |
330 | } |
331 | }; |
332 | |
333 | //Calls a pack request in nested way |
334 | template<typename obj_type, typename Mem, int ... prp> |
335 | struct call_aggregatePackRequest |
336 | { |
337 | /*! \brief Pack the object |
338 | * |
339 | * \param obj object to pack |
340 | * \param req offset of the packed memory |
341 | * |
342 | */ |
343 | static inline void call_packRequest(const obj_type & obj, size_t & req) |
344 | { |
345 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
346 | typedef typename prp_all_zero<obj_type,sizeof...(prp) == 0,prp...>::type b_prp; |
347 | |
348 | call_packRequest_agg_functor<obj_type,Mem> functor(obj,req); |
349 | |
350 | //Apply functor for each property |
351 | boost::mpl::for_each_ref<b_prp>(functor); |
352 | } |
353 | }; |
354 | |
355 | template<bool inte_layout, typename obj_type, typename Mem> |
356 | struct pack_pack_op |
357 | { |
358 | template<unsigned int p> static inline void call_pack_pack(ExtPreAlloc<Mem> & mem, const obj_type & obj,Pack_stat & sts) |
359 | { |
360 | typedef typename boost::mpl::at<typename obj_type::type,boost::mpl::int_<p>>::type obj_t; |
361 | |
362 | Packer<obj_t,Mem>::pack(mem,obj.template get<p>(),sts); |
363 | } |
364 | }; |
365 | |
366 | //Calls a pack request in nested way |
367 | template<typename obj_type, typename Mem, int ... prp> |
368 | struct call_aggregatePackRequestChunking |
369 | { |
370 | /*! \brief Pack the object |
371 | * |
372 | * \param obj object to pack |
373 | * \param req offset of the packed memory |
374 | * |
375 | */ |
376 | static inline void call_packRequest(const obj_type & obj, size_t sub_id, size_t & req) |
377 | { |
378 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
379 | typedef typename prp_all_zero<obj_type,sizeof...(prp) == 0,prp...>::type b_prp; |
380 | |
381 | call_packRequest_agg_functor_cnk<obj_type,Mem> functor(obj,sub_id,req); |
382 | |
383 | //Apply functor for each property |
384 | boost::mpl::for_each_ref<b_prp>(functor); |
385 | } |
386 | }; |
387 | |
388 | //A functor for call_aggregatePack |
389 | template<typename obj_type, typename Mem> |
390 | struct call_pack_agg_functor |
391 | { |
392 | ExtPreAlloc<Mem> & mem; |
393 | const obj_type & obj; |
394 | Pack_stat & sts; |
395 | |
396 | call_pack_agg_functor(ExtPreAlloc<Mem> & mem, const obj_type & obj, Pack_stat & sts) |
397 | :mem(mem), obj(obj), sts(sts) |
398 | { |
399 | } |
400 | |
401 | //! It calls the packer for each property |
402 | template<typename T> |
403 | inline void operator()(T& t) |
404 | { |
405 | // typedef typename boost::mpl::at<typename obj_type::type,T>::type obj_t; |
406 | |
407 | pack_pack_op<openfpm::is_multi_array<decltype(obj.template get<T::value>())>::value,obj_type,Mem>::template call_pack_pack<T::value>(mem,obj,sts); |
408 | |
409 | // Packer<obj_t,Mem>::pack(mem,obj.template get<T::value>(),sts); |
410 | } |
411 | }; |
412 | |
413 | //! Calls a packer in nested way |
414 | template<typename obj_type, typename Mem, int ... prp> |
415 | struct call_aggregatePack |
416 | { |
417 | /*! \brief Call the packer |
418 | * |
419 | * \param obj object to pack |
420 | * \param mem memory where to pack |
421 | * \param sts information about the packing |
422 | * |
423 | */ |
424 | static inline void call_pack(const obj_type & obj, ExtPreAlloc<Mem> & mem, Pack_stat & sts) |
425 | { |
426 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
427 | typedef typename prp_all_zero<obj_type,sizeof...(prp) == 0,prp...>::type b_prp; |
428 | |
429 | call_pack_agg_functor<obj_type,Mem> functor(mem,obj,sts); |
430 | |
431 | //Apply functor for each property |
432 | boost::mpl::for_each_ref<b_prp>(functor); |
433 | } |
434 | }; |
435 | |
436 | |
437 | //A functor for call_aggregateUnpack |
438 | template<typename obj_type, typename Mem> |
439 | struct call_unpack_agg_functor |
440 | { |
441 | //! Memory where to pack |
442 | ExtPreAlloc<Mem> & mem; |
443 | |
444 | //! object to pack |
445 | obj_type & obj; |
446 | |
447 | //! statistic about packing |
448 | Unpack_stat & ps; |
449 | |
450 | /*! \brief constructor |
451 | * |
452 | * \param mem memory where to pack |
453 | * \param obj object to pack |
454 | * \param ps packing statistic |
455 | * |
456 | */ |
457 | call_unpack_agg_functor(ExtPreAlloc<Mem> & mem, obj_type & obj, Unpack_stat & ps) |
458 | :mem(mem), obj(obj), ps(ps) |
459 | { |
460 | } |
461 | |
462 | //! It calls the unpacker for each property |
463 | template<typename T> |
464 | inline void operator()(T& t) |
465 | { |
466 | typedef typename boost::mpl::at<typename obj_type::type,T>::type obj_t; |
467 | |
468 | Unpacker<obj_t,Mem>::unpack(mem,obj.template get<T::value>(),ps); |
469 | } |
470 | }; |
471 | |
472 | //! Calls an unpacker in nested way |
473 | template<typename obj_type, typename Mem, int ... prp> |
474 | struct call_aggregateUnpack |
475 | { |
476 | /*! \brief constructor |
477 | * |
478 | * \param mem memory from where to unpack |
479 | * \param obj object to pack |
480 | * \param ps packing statistic |
481 | * |
482 | */ |
483 | static inline void call_unpack(obj_type && obj, ExtPreAlloc<Mem> & mem, Unpack_stat & ps) |
484 | { |
485 | //Property sequence into boost::mpl::range_c or boost::mpl::vector, depending on sizeof...(prp) |
486 | typedef typename prp_all_zero<obj_type,sizeof...(prp) == 0,prp...>::type b_prp; |
487 | |
488 | call_unpack_agg_functor<obj_type,Mem> functor(mem,obj,ps); |
489 | |
490 | //Apply functor for each property |
491 | boost::mpl::for_each_ref<b_prp>(functor); |
492 | } |
493 | }; |
494 | |
495 | #endif /* PACKER_UTIL_HPP_ */ |
496 | |