1 | /*! |
2 | * This file contains the implemetation of packer and unpacker for vector |
3 | * Created on: Jan 5, 2016 |
4 | * Author: Yaroslav Zaluzhnyi and Pietro Incardona |
5 | */ |
6 | |
7 | /*! This Function to indicate the vector class has a packer function |
8 | * |
9 | * \return true vector has a pack function |
10 | * |
11 | */ |
12 | static bool pack() |
13 | { |
14 | return true; |
15 | } |
16 | |
17 | /*! This Function indicate that vector class has a packRequest function |
18 | * |
19 | * \return true vector has a packRequest function |
20 | * |
21 | */ |
22 | static bool packRequest() |
23 | { |
24 | return true; |
25 | } |
26 | |
27 | /*! This Function indicate that vector class has a packMem function |
28 | * |
29 | * \return true vector has a packMem function |
30 | * |
31 | */ |
32 | static bool packMem() |
33 | { |
34 | return true; |
35 | } |
36 | |
37 | //! Structures that do a nested packing, depending on the existence of 'pack()' function inside the object |
38 | //There is no pack() inside |
39 | template<bool cond, typename T1, typename Memory1, int ... prp> |
40 | struct pack_cond |
41 | { |
42 | //! Trivial case it serialize the vector object as simply an array of objects |
43 | void packing(ExtPreAlloc<Memory1> & mem, openfpm::vector<T1> & obj, Pack_stat & sts) |
44 | { |
45 | Packer<openfpm::vector<T1>, Memory1, PACKER_ARRAY_PRIMITIVE>::pack(mem,obj,sts,obj.size()); |
46 | } |
47 | |
48 | }; |
49 | |
50 | //! Structures that do a nested packing, depending on the existence of 'pack()' function inside the object |
51 | //There is pack() inside |
52 | template<typename T1, typename Memory1, int ... prp> |
53 | struct pack_cond<true, T1, Memory1, prp...> |
54 | { |
55 | //! It traverse the type-tree structure to serialize the vector object into memory |
56 | void packing(ExtPreAlloc<Memory1> & mem, openfpm::vector<T1> & obj, Pack_stat & sts) |
57 | { |
58 | for (size_t i = 0; i < obj.size(); i++) |
59 | obj.get(i).template pack<prp...>(mem, sts); |
60 | } |
61 | }; |
62 | |
63 | //! Structures that calculate how many bytes are required to serialize an object |
64 | // depending on the existence of 'packMem()' function inside of the object |
65 | // There is no packMem() inside |
66 | template<bool cond, typename T1> |
67 | struct packMem_cond |
68 | { |
69 | //! calculate how many bytes are needed to serialize the object |
70 | size_t packMemory(T1 & obj, size_t n, size_t e) |
71 | { |
72 | return grow_policy_double::grow(0,n) * sizeof(T); |
73 | } |
74 | |
75 | }; |
76 | |
77 | //! Structures that calculate memory for an object, depending on the existence of 'packMem()' |
78 | // function inside of the object |
79 | // There is packMem() inside |
80 | template<typename T1> |
81 | struct packMem_cond<true, T1> |
82 | { |
83 | //! calculate how many bytes are needed to serialize the object |
84 | size_t packMemory(T1 & obj, size_t n, size_t e) |
85 | { |
86 | size_t res = 0; |
87 | size_t count = grow_policy_double::grow(0,n) - obj.size(); |
88 | for (size_t i = 0; i < n; i++) { |
89 | res += obj.get(i).packMem(n,0); |
90 | } |
91 | return res+count*sizeof(T); |
92 | } |
93 | }; |
94 | |
95 | |
96 | //! These structures serialize a simple (no "pack()" inside) object |
97 | // With specified properties |
98 | template<bool sel, int ... prp> |
99 | struct pack_simple_cond |
100 | { |
101 | //! serialize the vector |
102 | template<typename Memory2> static inline void pack(const openfpm::vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> & obj, ExtPreAlloc<Memory2> & mem, Pack_stat & sts) |
103 | { |
104 | //Pack the size of a vector |
105 | Packer<size_t, Memory2>::pack(mem,obj.size(),sts); |
106 | |
107 | // Sending property object |
108 | typedef openfpm::vector<T,Memory,layout_base,grow_p> vctr; |
109 | typedef object<typename object_creator<typename vctr::value_type::type,prp...>::type> prp_object; |
110 | |
111 | typedef openfpm::vector<prp_object,ExtPreAlloc<Memory2>, layout_base ,openfpm::grow_policy_identity> dtype; |
112 | |
113 | // Create an object over the preallocated memory (No allocation is produced) |
114 | dtype dest; |
115 | dest.setMemory(mem); |
116 | dest.resize(obj.size()); |
117 | |
118 | auto obj_it = obj.getIterator(); |
119 | |
120 | while (obj_it.isNext()) |
121 | { |
122 | // copy all the object in the send buffer |
123 | typedef encapc<1,typename vctr::value_type,typename vctr::layout_type > encap_src; |
124 | // destination object type |
125 | typedef encapc<1,prp_object,typename dtype::layout_type > encap_dst; |
126 | |
127 | // Copy only the selected properties |
128 | object_si_d<encap_src,encap_dst,OBJ_ENCAP,prp...>(obj.get(obj_it.get()),dest.get(obj_it.get())); |
129 | |
130 | ++obj_it; |
131 | } |
132 | |
133 | // Update statistic |
134 | sts.incReq(); |
135 | } |
136 | }; |
137 | |
138 | //! These structures serialize a simple (no "pack()" inside) object |
139 | // Without specified properties |
140 | template<int ... prp> |
141 | struct pack_simple_cond<true, prp ...> |
142 | { |
143 | //! serialize the vector |
144 | template<typename Memory2> |
145 | static inline void pack(const openfpm::vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> & obj , ExtPreAlloc<Memory2> & mem, Pack_stat & sts) |
146 | { |
147 | //Pack the size of a vector |
148 | Packer<size_t, Memory2>::pack(mem,obj.size(),sts); |
149 | |
150 | // Sending property object |
151 | typedef openfpm::vector<T,ExtPreAlloc<Memory2>,memory_traits_lin,openfpm::grow_policy_identity> dtype; |
152 | |
153 | // Create an object over the preallocated memory (No allocation is produced) |
154 | dtype dest; |
155 | dest.setMemory(mem); |
156 | dest.resize(obj.size()); |
157 | |
158 | auto obj_it = obj.getIterator(); |
159 | |
160 | while (obj_it.isNext()) |
161 | { |
162 | // Copy |
163 | dest.get(obj_it.get()) = obj.get(obj_it.get()); |
164 | |
165 | ++obj_it; |
166 | } |
167 | |
168 | // Update statistic |
169 | sts.incReq(); |
170 | } |
171 | }; |
172 | |
173 | //! These structures do an de-serialize a simple object (no pack() inside) |
174 | // With specified properties |
175 | template<bool sel, int ... prp> |
176 | struct unpack_simple_cond |
177 | { |
178 | //! De-serialize an object |
179 | template<typename Memory2> |
180 | static inline void unpack(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> & obj , ExtPreAlloc<Memory2> & mem, Unpack_stat & ps) |
181 | { |
182 | //Unpack a size of a source vector |
183 | size_t u2 = 0; |
184 | Unpacker<size_t, Memory2>::unpack(mem,u2,ps); |
185 | |
186 | //Resize a destination vector |
187 | obj.resize(u2); |
188 | |
189 | size_t id = 0; |
190 | |
191 | // Sending property object |
192 | typedef openfpm::vector<T> vctr; |
193 | typedef object<typename object_creator<typename vctr::value_type::type,prp...>::type> prp_object; |
194 | typedef openfpm::vector<prp_object,PtrMemory, memory_traits_lin,openfpm::grow_policy_identity> stype; |
195 | |
196 | |
197 | // Calculate the size to pack the object |
198 | size_t size = obj.packMem<prp...>(obj.size(),0); |
199 | |
200 | // Create a Pointer object over the preallocated memory (No allocation is produced) |
201 | PtrMemory & ptr = *(new PtrMemory(mem.getPointerOffset(ps.getOffset()),size)); |
202 | |
203 | stype src; |
204 | src.setMemory(ptr); |
205 | src.resize(obj.size()); |
206 | auto obj_it = obj.getIterator(); |
207 | |
208 | while (obj_it.isNext()) |
209 | { |
210 | // copy all the object in the send buffer |
211 | typedef encapc<1,typename vctr::value_type,typename vctr::layout_type > encap_dst; |
212 | // destination object type |
213 | typedef encapc<1,prp_object,typename stype::layout_type > encap_src; |
214 | |
215 | // Copy only the selected properties |
216 | object_s_di<encap_src,encap_dst,OBJ_ENCAP,prp...>(src.get(id),obj.get(obj_it.get())); |
217 | |
218 | ++id; |
219 | ++obj_it; |
220 | } |
221 | |
222 | ps.addOffset(size); |
223 | } |
224 | }; |
225 | |
226 | //! These structures de-serialize a simple object (no pack() inside) |
227 | //! unpack Without specified properties |
228 | template<int ... prp> |
229 | struct unpack_simple_cond<true, prp ...> |
230 | { |
231 | /*! \brief unpack from the memory the data structure and put it into obj |
232 | * |
233 | * \param obj object to deserialize |
234 | * \param mem object containing the raw data to deserialize |
235 | * \param ps statistic |
236 | * |
237 | */ |
238 | template<typename Memory2> |
239 | static inline void unpack(openfpm::vector<T,Memory,layout_base, grow_p,OPENFPM_NATIVE> & obj , ExtPreAlloc<Memory2> & mem, Unpack_stat & ps) |
240 | { |
241 | //Unpack a size of a source vector |
242 | size_t u2 = 0; |
243 | Unpacker<size_t, Memory2>::unpack(mem,u2,ps); |
244 | |
245 | //Resize a destination vector |
246 | obj.resize(u2); |
247 | |
248 | size_t id = 0; |
249 | |
250 | // Sending property object |
251 | typedef openfpm::vector<T,PtrMemory,memory_traits_lin,openfpm::grow_policy_identity> stype; |
252 | |
253 | // Calculate the size to pack the object |
254 | size_t size = obj.packMem<prp...>(obj.size(),0); |
255 | |
256 | // Create a Pointer object over the preallocated memory (No allocation is produced) |
257 | PtrMemory & ptr = *(new PtrMemory(mem.getPointerOffset(ps.getOffset()),size)); |
258 | |
259 | stype src; |
260 | src.setMemory(ptr); |
261 | src.resize(obj.size()); |
262 | auto obj_it = obj.getIterator(); |
263 | |
264 | while (obj_it.isNext()) |
265 | { |
266 | // Copy |
267 | obj.get(obj_it.get()) = src.get(id); |
268 | |
269 | ++id; |
270 | ++obj_it; |
271 | } |
272 | |
273 | ps.addOffset(size); |
274 | } |
275 | }; |
276 | |
277 | |
278 | /*! \brief It calculate the number of byte required to serialize the object |
279 | * |
280 | * \tparam prp list of properties |
281 | * |
282 | * \param req reference to the total counter required to pack the information |
283 | * |
284 | */ |
285 | template<int ... prp> inline void packRequest(size_t & req) const |
286 | { |
287 | //Pushback a sizeof number of elements of the internal vectors |
288 | req += sizeof(this->size()); |
289 | |
290 | // If all of the aggregate properties do not have a "pack()" member |
291 | if (has_pack_agg<T,prp...>::result::value == false) |
292 | { |
293 | size_t alloc_ele = this->packMem<prp...>(this->size(),0); |
294 | req += alloc_ele; |
295 | } |
296 | //If at least one property has "pack()" |
297 | else |
298 | { |
299 | for (size_t i = 0 ; i < this->size() ; i++) |
300 | { |
301 | //Call a pack request |
302 | call_aggregatePackRequest<decltype(this->get(i)),Memory,prp ... >::call_packRequest(this->get(i),req); |
303 | } |
304 | } |
305 | } |
306 | |
307 | |
308 | /*! \brief pack a vector selecting the properties to pack |
309 | * |
310 | * \param mem preallocated memory where to pack the vector |
311 | * \param sts pack-stat info |
312 | * |
313 | */ |
314 | template<int ... prp> inline void pack(ExtPreAlloc<HeapMemory> & mem, Pack_stat & sts) const |
315 | { |
316 | //If all of the aggregate properties are simple (don't have "pack()" member) |
317 | if (has_pack_agg<T,prp...>::result::value == false) |
318 | //if (has_aggregatePack<T,prp ... >::has_pack() == false) |
319 | { |
320 | //Call a packer |
321 | pack_simple_cond<sizeof...(prp) == 0,prp...>::template pack(*this,mem,sts); |
322 | } |
323 | //If at least one property has a "pack()" member |
324 | else |
325 | { |
326 | //Pack the size of a vector |
327 | Packer<size_t, HeapMemory>::pack(mem,this->size(),sts); |
328 | |
329 | for (size_t i = 0 ; i < this->size() ; i++) |
330 | { |
331 | //Call a packer in nested way |
332 | call_aggregatePack<decltype(this->get(i)),HeapMemory,prp ... >::call_pack(this->get(i),mem,sts); |
333 | } |
334 | } |
335 | } |
336 | |
337 | /*! \brief unpack a vector |
338 | * |
339 | * \param mem preallocated memory from where to unpack the vector |
340 | * \param ps unpack-stat info |
341 | */ |
342 | template<int ... prp> inline void unpack(ExtPreAlloc<HeapMemory> & mem, Unpack_stat & ps) |
343 | { |
344 | //if all of the aggregate properties are simple (don't have "pack()" member) |
345 | if (has_pack_agg<T,prp...>::result::value == false) |
346 | //if (has_aggregatePack<T,prp ... >::has_pack() == false) |
347 | { |
348 | //Call an unpacker |
349 | unpack_simple_cond<sizeof...(prp) == 0,prp...>::unpack(*this,mem,ps); |
350 | } |
351 | //If at least one is not simple (has a "pack()" member) |
352 | else |
353 | { |
354 | //Unpack a size of a source vector |
355 | size_t u2 = 0; |
356 | Unpacker<size_t, HeapMemory>::unpack(mem,u2,ps); |
357 | |
358 | //Resize a destination vector |
359 | this->resize(u2); |
360 | |
361 | for (size_t i = 0 ; i < this->size() ; i++) |
362 | { |
363 | //Call an unpacker in nested way |
364 | call_aggregateUnpack<decltype(this->get(i)),HeapMemory,prp ... >::call_unpack(this->get(i),mem,ps); |
365 | } |
366 | } |
367 | } |
368 | |
369 | |