1/*!
2 * This file contains the implemetation of packer and unpacker for grid
3 * Created on: July 8, 2016
4 * Author: Yaroslav Zaluzhnyi
5 */
6
7
8//Functions to check if the packing object is complex
9static bool pack()
10{
11 return false;
12}
13
14/*! \brief Reset the pack calculation
15 *
16 * \note in this case does nothing
17 *
18 */
19void packReset()
20{}
21
22/*! \brief Pack calculate
23 *
24 * \note in this case does nothing
25 *
26 */
27 template<unsigned int ... prp, typename context_type>
28void packCalculate(size_t & req, const context_type & ctx)
29{}
30
31static bool packRequest()
32{
33 return false;
34}
35
36static bool packMem()
37{
38 return false;
39}
40
41//These structures do a packing of a simple (no "pack()" inside) object
42
43//With specified properties
44template<bool sel, int ... prp>
45struct pack_simple_cond
46{
47 static inline void pack(const grid_base_impl<dim,T,S,layout_base> & obj, ExtPreAlloc<S> & mem, Pack_stat & sts)
48 {
49#ifdef SE_CLASS1
50 if (mem.ref() == 0)
51 std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n";
52#endif
53
54 //Pack the size of a grid
55 for (size_t i = 0; i < dim; i++)
56 {
57 Packer<size_t, S>::pack(mem,obj.getGrid().size(i),sts);
58 }
59
60 // Sending property object and vector
61 typedef object<typename object_creator<typename grid_base_impl<dim,T,S,layout_base>::value_type::type,prp...>::type> prp_object;
62 typedef openfpm::vector<prp_object,ExtPreAlloc<S>,layout_base,openfpm::grow_policy_identity> dtype;
63
64 // Create an object over the preallocated memory (No allocation is produced)
65 dtype dest;
66 dest.setMemory(mem);
67 dest.resize(obj.size());
68
69 auto it = obj.getIterator();
70
71 // copy all the object in the send buffer
72 typedef encapc<dims,value_type,layout > encap_src;
73 // destination object type
74 typedef encapc<1,prp_object,typename dtype::layout_type > encap_dst;
75
76 pack_with_iterator<!is_contiguos<prp...>::type::value || has_pack_gen<prp_object>::value,
77 dim,
78 decltype(obj),
79 encap_src,
80 encap_dst,
81 typename grid_base_impl<dim,T,S,layout_base>::value_type::type,
82 decltype(it),
83 dtype,
84 prp...>::pack(obj,it,dest);
85
86 // Update statistic
87 sts.incReq();
88 }
89};
90
91//Without specified properties
92template<int ... prp>
93struct pack_simple_cond<true, prp ...>
94{
95 static inline void pack(const grid_base_impl<dim,T,S,layout_base> & obj, ExtPreAlloc<S> & mem, Pack_stat & sts)
96 {
97#ifdef SE_CLASS1
98 if (mem.ref() == 0)
99 std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n";
100#endif
101
102 //Pack the size of a grid
103 for (size_t i = 0; i < dim; i++)
104 {
105 Packer<size_t, S>::pack(mem,obj.getGrid().size(i),sts);
106 }
107
108 // Sending property object
109 typedef openfpm::vector<T,ExtPreAlloc<S>,layout_base,openfpm::grow_policy_identity> dtype;
110
111 // Create an object over the preallocated memory (No allocation is produced)
112 dtype dest;
113 dest.setMemory(mem);
114 dest.resize(obj.size());
115
116 auto obj_it = obj.getIterator();
117
118 size_t id = 0;
119
120 while (obj_it.isNext())
121 {
122 // Copy
123 dest.get(id).set(obj.get_o(obj_it.get()));
124
125 ++obj_it;
126 ++id;
127 }
128
129 // Update statistic
130 sts.incReq();
131 }
132};
133
134//These structures do an upacking of a simple object (no pack() inside)
135
136//With specified properties
137template<bool sel, int ... prp>
138struct unpack_simple_cond
139{
140 static inline void unpack(grid_base_impl<dim,T,S,layout_base,ord_type> & obj , ExtPreAlloc<S> & mem, Unpack_stat & ps)
141 {
142 size_t dims[dim];
143
144 //Unpack a size of a source grid
145 for (size_t i = 0; i < dim; i++)
146 {
147 size_t u2 = 0;
148 Unpacker<size_t, S>::unpack(mem,u2,ps);
149 dims[i] = u2;
150 }
151
152 //Resize a destination grid
153 obj.resize(dims);
154 obj.setMemory();
155
156 // object that store the information in mem
157 typedef object<typename object_creator<typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type::type,prp...>::type> prp_object;
158 typedef openfpm::vector<prp_object,PtrMemory,layout_base,openfpm::grow_policy_identity> stype;
159
160 // Calculate the size to pack the object
161 size_t size = obj.template packMem<prp...>(obj.size(),0);
162
163 // Create an object over the preallocated memory (No allocation is produced)
164 PtrMemory & ptr = *(new PtrMemory(mem.getPointerOffset(ps.getOffset()),size));
165
166 // Create an object over a pointer (No allocation is produced)
167 stype src;
168 src.setMemory(ptr);
169 src.resize(obj.size());
170
171 auto it = obj.getIterator();
172
173 // copy all the object in the send buffer
174 typedef encapc<dim,typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type,layout > encap_dst;
175 // destination object type
176 typedef encapc<1,prp_object,typename memory_traits_lin<prp_object>::type > encap_src;
177
178
179 unpack_with_iterator<dim,
180 decltype(obj),
181 encap_src,
182 encap_dst,
183 typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type::type,
184 decltype(it),
185 stype,
186 prp...>::unpack(obj,it,src);
187
188 ps.addOffset(size);
189 }
190};
191
192//Without specified properties
193template<int ... prp>
194struct unpack_simple_cond<true, prp ...>
195{
196 static inline void unpack(grid_base_impl<dim,T,S,layout_base,ord_type> & obj , ExtPreAlloc<S> & mem, Unpack_stat & ps)
197 {
198 size_t dims[dim];
199
200 //Unpack a size of a source grid
201 for (size_t i = 0; i < dim; i++)
202 {
203 size_t u2 = 0;
204 Unpacker<size_t, S>::unpack(mem,u2,ps);
205 dims[i] = u2;
206 }
207
208 //Resize a destination grid
209 obj.resize(dims);
210 obj.setMemory();
211
212 // Sending property object
213 typedef openfpm::vector<T,PtrMemory,layout_base,openfpm::grow_policy_identity> stype;
214
215 // Calculate the size to pack the object
216 size_t size = obj.template packMem<prp...>(obj.size(),0);
217
218 // Create a Pointer object over the preallocated memory (No allocation is produced)
219 PtrMemory & ptr = *(new PtrMemory(mem.getPointerOffset(ps.getOffset()),size));
220
221 stype src;
222 src.setMemory(ptr);
223 src.resize(obj.size());
224
225 auto obj_it = obj.getIterator();
226
227 size_t id = 0;
228
229 while (obj_it.isNext())
230 {
231 // Copy
232 obj.get_o(obj_it.get()).set(src.get(id));
233
234 ++id;
235 ++obj_it;
236 }
237
238 ps.addOffset(size);
239 }
240};
241
242 /*! \brief Insert an allocation request into the vector
243 *
244 * \tparam prp list of properties
245 *
246 * \param v vector of allocation sequence
247 *
248 */
249 template<int ... prp> inline void packRequest(size_t & req) const
250 {
251 //Pushback a "sizeof" of dimension sizes of the grid
252 for (size_t i = 0; i < dim; i++)
253 {
254 req += sizeof(this->getGrid().size(i));
255 }
256
257 // If all of the aggregate properties do not have a "pack()" member
258 if (has_pack_agg<T,prp...>::result::value == false)
259 {
260 size_t alloc_ele = this->packMem<prp...>(this->size(),0);
261 req += alloc_ele;
262 }
263 //If at least one property has "pack()"
264 else
265 {
266 auto key_it = this->getIterator();
267
268 while (key_it.isNext())
269 {
270 auto k = key_it.get();
271 //Call a pack request
272 call_aggregatePackRequest<decltype(this->get_o(k)),S,prp ... >::call_packRequest(this->get_o(k),req);
273
274 ++key_it;
275 }
276 }
277 }
278
279 /*! \brief pack a grid selecting the properties to pack
280 *
281 * \param mem preallocated memory where to pack the grid
282 * \param sts pack-stat info
283 *
284 */
285 template<int ... prp> inline void pack(ExtPreAlloc<S> & mem, Pack_stat & sts) const
286 {
287 //If all of the aggregate properties are simple (don't have "pack()" member)
288 if (has_pack_agg<T,prp...>::result::value == false)
289 {
290 //Call a packer
291 pack_simple_cond<sizeof...(prp) == 0,prp...>::pack(*this,mem,sts);
292 }
293 //If at least one property has a "pack()" member
294 else
295 {
296 //Pack the size of a grid
297 for (size_t i = 0; i < dim; i++)
298 {
299 Packer<size_t, S>::pack(mem,this->getGrid().size(i),sts);
300 }
301
302 auto key_it = this->getIterator();
303
304 while (key_it.isNext())
305 {
306 auto k = key_it.get();
307 //Call a pack request
308 call_aggregatePack<decltype(this->get_o(k)),S,prp ... >::call_pack(this->get_o(k),mem,sts);
309
310 ++key_it;
311 }
312 }
313 }
314
315 /*! \brief unpack a grid
316 *
317 * \param mem preallocated memory from where to unpack the grid
318 * \param ps unpack-stat info
319 */
320 template<int ... prp> inline void unpack(ExtPreAlloc<S> & mem, Unpack_stat & ps)
321 {
322 //if all of the aggregate properties are simple (don't have "pack()" member)
323 if (has_pack_agg<T,prp...>::result::value == false)
324 {
325 //Call an unpacker
326 unpack_simple_cond<sizeof...(prp) == 0,prp...>::unpack(*this,mem,ps);
327 }
328 //If at least one is not simple (has a "pack()" member)
329 else
330 {
331 size_t dims[dim];
332
333 //Unpack a size of a source grid
334 for (size_t i = 0; i < dim; i++)
335 {
336 size_t u2 = 0;
337 Unpacker<size_t, S>::unpack(mem,u2,ps);
338 dims[i] = u2;
339 }
340
341 //Resize a destination grid
342 this->resize(dims);
343 //this->setMemory();
344
345 auto key_it = this->getIterator();
346
347 while (key_it.isNext())
348 {
349 auto k = key_it.get();
350 //Call a pack request
351 call_aggregateUnpack<decltype(this->get_o(k)),S,prp ... >::call_unpack(this->get_o(k),mem,ps);
352
353 ++key_it;
354 }
355 }
356 }
357
358 /*! \brief Pack finalize Finalize the pack of this object. In this case it does nothing
359 *
360 * \tparam prp properties to pack
361 *
362 * \param mem preallocated memory where to pack the objects
363 * \param sts pack statistic
364 *
365 */
366 template<int ... prp> void packFinalize(ExtPreAlloc<S> & mem, Pack_stat & sts,int opt, bool is_pack_remote)
367 {}
368
369 /*! \brief Pack the object into the memory given an iterator
370 *
371 * \tparam prp properties to pack
372 *
373 * \param mem preallocated memory where to pack the objects
374 * \param sub_it sub grid iterator ( or the elements in the grid to pack )
375 * \param sts pack statistic
376 *
377 */
378 template<int ... prp> void pack(ExtPreAlloc<S> & mem, grid_key_dx_iterator_sub<dims> & sub_it, Pack_stat & sts)
379 {
380#ifdef SE_CLASS1
381 if (mem.ref() == 0)
382 std::cerr << "Error : " << __FILE__ << ":" << __LINE__ << " the reference counter of mem should never be zero when packing \n";
383#endif
384
385 // Sending property object
386 typedef object<typename object_creator<typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type::type,prp...>::type> prp_object;
387 typedef openfpm::vector<prp_object,ExtPreAlloc<S>, layout_base,openfpm::grow_policy_identity> dtype;
388
389 // Create an object over the preallocated memory (No allocation is produced)
390 dtype dest;
391 dest.setMemory(mem);
392 dest.resize(sub_it.getVolume());
393
394 // copy all the object in the send buffer
395 typedef encapc<dims,value_type,layout > encap_src;
396 // destination object type
397 typedef encapc<1,prp_object,typename dtype::layout_type > encap_dst;
398
399 pack_with_iterator<sizeof...(prp) != T::max_prop || has_pack_gen<prp_object>::value,
400 dims,
401 decltype(*this),
402 encap_src,
403 encap_dst,
404 typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type::type,
405 grid_key_dx_iterator_sub<dims>,
406 dtype,
407 prp...>::pack(*this,sub_it,dest);
408
409 // Update statistic
410 sts.incReq();
411 }
412
413
414 /*! \brief Insert an allocation request
415 *
416 * \tparam prp set of properties to pack
417 *
418
419 * \param sub sub-grid iterator
420 * \param vector of requests
421 *
422 */
423 template<int ... prp> void packRequest(grid_key_dx_iterator_sub<dims> & sub, size_t & req)
424 {
425 typedef openfpm::vector<typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type,ExtPreAlloc<S>,layout_base,openfpm::grow_policy_identity> dtype;
426 dtype dvect;
427
428 // Calculate the required memory for packing
429 size_t alloc_ele = dvect.template calculateMem<prp...>(sub.getVolume(),0);
430
431 req += alloc_ele;
432 }
433
434
435 /*! \brief unpack the sub-grid object
436 *
437 * \tparam prp properties to unpack
438 *
439 * \param mem preallocated memory from where to unpack the object
440 * \param sub sub-grid iterator
441 * \param obj object where to unpack
442 *
443 */
444 template<unsigned int ... prp,typename S2, typename context_type>
445 void unpack(ExtPreAlloc<S2> & mem, grid_key_dx_iterator_sub<dims> & sub_it, Unpack_stat & ps,context_type & context, rem_copy_opt opt)
446 {
447 // object that store the information in mem
448 typedef object<typename object_creator<typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type::type,prp...>::type> prp_object;
449 typedef openfpm::vector<prp_object,PtrMemory, memory_traits_lin ,openfpm::grow_policy_identity> stype;
450
451 size_t size = stype::template calculateMem(sub_it.getVolume(),0);
452
453 // Create an object over the preallocated memory (No allocation is produced)
454 PtrMemory & ptr = *(new PtrMemory(mem.getPointerOffset(ps.getOffset()),size));
455
456 // Create an object of the packed information over a pointer (No allocation is produced)
457 stype src;
458 src.setMemory(ptr);
459 src.resize(sub_it.getVolume());
460
461 // copy all the object in the send buffer
462 typedef encapc<dims,typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type,layout > encap_dst;
463 // destination object type
464 typedef encapc<1,prp_object,typename memory_traits_lin<prp_object>::type > encap_src;
465
466 unpack_with_iterator<dims,
467 decltype(*this),
468 encap_src,
469 encap_dst,
470 typename grid_base_impl<dim,T,S,layout_base,ord_type>::value_type::type,
471 grid_key_dx_iterator_sub<dims>,
472 stype,
473 prp...>::unpack(*this,sub_it,src);
474
475 ps.addOffset(size);
476 }
477
478 /*! \brief unpack the sub-grid object applying an operation
479 *
480 * \tparam op operation
481 * \tparam prp properties to unpack
482 *
483 * \param mem preallocated memory from where to unpack the object
484 * \param sub sub-grid iterator
485 * \param obj object where to unpack
486 *
487 */
488 template<template<typename,typename> class op, typename S2, unsigned int ... prp>
489 void unpack_with_op(ExtPreAlloc<S2> & mem, grid_key_dx_iterator_sub<dim> & sub2, Unpack_stat & ps)
490 {
491 PtrMemory * ptr1;
492
493 size_t sz[dim];
494
495 for (size_t i = 0 ; i < dim ; i++)
496 sz[i] = sub2.getStop().get(i) - sub2.getStart().get(i) + 1;
497
498 size_t tot = 1;
499
500 for (size_t i = 0 ; i < dim ; i++)
501 {tot *= sz[i];}
502
503 typedef object<typename object_creator<typename T::type,prp...>::type> prp_object;
504
505 tot *= sizeof(prp_object);
506
507#ifdef SE_CLASS1
508
509 if (ps.getOffset() + tot > mem.size())
510 std::cerr << __FILE__ << ":" << __LINE__ << " Error: overflow in the receiving buffer for ghost_put" << std::endl;
511
512#endif
513
514 // add the received particles to the vector
515 ptr1 = new PtrMemory(((char *)mem.getPointerBase()+ps.getOffset()),tot);
516
517 // create vector representation to a piece of memory already allocated
518 grid_base_impl<dim,prp_object,PtrMemory,memory_traits_lin,ord_type> gs;
519
520 gs.setMemory(*ptr1);
521
522 // resize with the number of elements
523 gs.resize(sz);
524
525 // Merge the information
526
527 auto it_src = gs.getIterator();
528
529 while (sub2.isNext())
530 {
531 object_s_di_op<op,decltype(gs.get_o(it_src.get())),decltype(this->get_o(sub2.get())),OBJ_ENCAP,prp...>(gs.get_o(it_src.get()),this->get_o(sub2.get()));
532
533 ++sub2;
534 ++it_src;
535 }
536
537 ps.addOffset(tot);
538 }
539
540 /*! \brief Calculate the memory size required to pack n elements
541 *
542 * Calculate the total size required to store n-elements in a vector
543 *
544 * \param n number of elements
545 * \param e unused
546 *
547 * \return the size of the allocation number e
548 *
549 */
550 template<int ... prp> static inline size_t packMem(size_t n, size_t e)
551 {
552 if (sizeof...(prp) == 0)
553 return n * sizeof(typename T::type);
554
555 typedef object<typename object_creator<typename T::type,prp...>::type> prp_object;
556
557 return n * sizeof(prp_object);
558 }
559
560
561