1 | /* |
2 | * grid_base_impl_layout.hpp |
3 | * |
4 | * Created on: May 2, 2016 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef OPENFPM_DATA_SRC_GRID_GRID_BASE_IMPL_LAYOUT_HPP_ |
9 | #define OPENFPM_DATA_SRC_GRID_GRID_BASE_IMPL_LAYOUT_HPP_ |
10 | |
11 | #include <boost/fusion/include/mpl.hpp> |
12 | #include "memory_ly/memory_conf.hpp" |
13 | #include <boost/fusion/include/for_each.hpp> |
14 | #include "memory_ly/Encap.hpp" |
15 | #include "Space/Shape/Box.hpp" |
16 | |
17 | /*! \brief this class is a functor for "for_each" algorithm |
18 | * |
19 | * This class is a functor for "for_each" algorithm. For each |
20 | * element of the boost::vector the operator() is called |
21 | * |
22 | * \param T Type of memory allocator |
23 | * |
24 | */ |
25 | |
26 | template<typename S> |
27 | struct allocate |
28 | { |
29 | //! size to allocate |
30 | size_t sz; |
31 | |
32 | //! constructor it fix the size |
33 | allocate(size_t sz) |
34 | :sz(sz){}; |
35 | |
36 | //! It call the allocate function for each member |
37 | template<typename T> |
38 | void operator()(T& t) const |
39 | { |
40 | //! Create and set the memory allocator |
41 | t.setMemory(*new S()); |
42 | |
43 | //! Allocate the memory and create the reppresentation |
44 | if (sz != 0) t.allocate(sz); |
45 | } |
46 | }; |
47 | |
48 | |
49 | /*! \brief this class is a functor for "for_each" algorithm |
50 | * |
51 | * This class is a functor for "for_each" algorithm. For each |
52 | * element of the boost::vector the operator() is called |
53 | * |
54 | * \param T Type of memory allocator |
55 | * |
56 | */ |
57 | |
58 | template<typename s_m> |
59 | struct frswap |
60 | { |
61 | s_m & swap_src; |
62 | s_m & swap_dst; |
63 | |
64 | //! constructor |
65 | frswap(s_m & swap_dst, s_m & swap_src) |
66 | :swap_src(swap_src),swap_dst(swap_dst) |
67 | {}; |
68 | |
69 | //! It call the allocate function for each member |
70 | template<typename T> |
71 | void operator()(T& t) const |
72 | { |
73 | boost::fusion::at_c<T::value>(swap_dst).swap(boost::fusion::at_c<T::value>(swap_src)); |
74 | } |
75 | }; |
76 | |
77 | |
78 | /*! \brief this class is a functor for "for_each" algorithm |
79 | * |
80 | * This class is a functor for "for_each" algorithm. For each |
81 | * element of the boost::vector the operator() is called |
82 | * |
83 | * \param T Type of memory allocator |
84 | * \param Mem_type Memory type |
85 | * |
86 | */ |
87 | |
88 | template<typename s_m, typename Mem_type> |
89 | struct frswap_nomode |
90 | { |
91 | s_m & swap_src; |
92 | s_m & swap_dst; |
93 | |
94 | //! constructor |
95 | frswap_nomode(s_m & swap_dst, s_m & swap_src) |
96 | :swap_src(swap_src),swap_dst(swap_dst) |
97 | {}; |
98 | |
99 | //! It call the allocate function for each member |
100 | template<typename T> |
101 | void operator()(T& t) const |
102 | { |
103 | boost::fusion::at_c<T::value>(swap_dst).template swap_nomode<Mem_type>(boost::fusion::at_c<T::value>(swap_src)); |
104 | } |
105 | }; |
106 | |
107 | //! Case memory_traits_lin |
108 | template<typename S, typename layout, typename data_type, typename g1_type, unsigned int sel = 2*is_layout_mlin<layout>::value + is_layout_inte<layout>::value > |
109 | struct mem_setm |
110 | { |
111 | static inline void setMemory(data_type & data_, const g1_type & g1, bool & is_mem_init) |
112 | { |
113 | S * mem = new S(); |
114 | |
115 | //! Create and set the memory allocator |
116 | data_.setMemory(*mem); |
117 | |
118 | //! Allocate the memory and create the representation |
119 | if (g1.size() != 0) data_.allocate(g1.size()); |
120 | |
121 | is_mem_init = true; |
122 | } |
123 | }; |
124 | |
125 | //! Case memory_traits_inte |
126 | template<typename S, typename layout, typename data_type, typename g1_type> |
127 | struct mem_setm<S,layout,data_type,g1_type,1> |
128 | { |
129 | static inline void setMemory(data_type & data_, const g1_type & g1, bool & is_mem_init) |
130 | { |
131 | //! Create an allocate object |
132 | allocate<S> all(g1.size()); |
133 | |
134 | //! for each element in the vector allocate the buffer |
135 | boost::fusion::for_each(data_,all); |
136 | |
137 | is_mem_init = true; |
138 | } |
139 | }; |
140 | |
141 | |
142 | //! Case memory_traits_lin |
143 | template<typename grid_type, typename S , typename layout, typename data_type, unsigned int sel = 2*is_layout_mlin<layout>::value + is_layout_inte<layout>::value > |
144 | struct mem_setext |
145 | { |
146 | static inline void set(grid_type & grid_new, grid_type & old, data_type & data_) |
147 | { |
148 | grid_new.setMemory(static_cast<S&>(data_.getMemory())); |
149 | |
150 | // Create an empty memory allocator for the actual structure |
151 | |
152 | old.setMemory(); |
153 | } |
154 | }; |
155 | |
156 | /*! \brief this class is a functor for "for_each" algorithm |
157 | * |
158 | * This class is a functor for "for_each" algorithm. For each |
159 | * element of the boost::vector the operator() is called. |
160 | * Is mainly used to set each property with external memory |
161 | * |
162 | * |
163 | */ |
164 | template<typename grid_type, typename data_type, typename S> |
165 | struct mem_setext_prp |
166 | { |
167 | grid_type & grid_new; |
168 | |
169 | grid_type & old; |
170 | |
171 | data_type & data_; |
172 | |
173 | /*! \brief constructor |
174 | * |
175 | * |
176 | * |
177 | */ |
178 | inline mem_setext_prp(grid_type & g_new, grid_type & old, data_type & data_) |
179 | :grid_new(g_new),old(old),data_(data_) |
180 | {}; |
181 | |
182 | //! It call the copy function for each property |
183 | template<typename T> |
184 | inline void operator()(T& t) |
185 | { |
186 | grid_new.template setMemory<T::value>(static_cast<S&>(boost::fusion::at_c<T::value>(data_).getMemory())); |
187 | |
188 | |
189 | } |
190 | }; |
191 | |
192 | |
193 | /*! \brief this class is a functor for "for_each" algorithm |
194 | * |
195 | * This class is a functor for "for_each" algorithm. For each |
196 | * element of the boost::vector the operator() is called. |
197 | * Is mainly used to set an external memory for each |
198 | * |
199 | * |
200 | */ |
201 | template<typename grid_type, typename Memory> |
202 | struct mem_setarray |
203 | { |
204 | grid_type & grid_new; |
205 | |
206 | Memory * mem; |
207 | |
208 | size_t sz; |
209 | |
210 | bool np; |
211 | |
212 | /*! \brief constructor |
213 | * |
214 | * |
215 | * |
216 | */ |
217 | inline mem_setarray(grid_type & g_new, Memory * mem, size_t sz, bool np) |
218 | :grid_new(g_new),mem(mem),sz(sz),np(np) |
219 | {}; |
220 | |
221 | //! It call the copy function for each property |
222 | template<typename T> |
223 | inline void operator()(T& t) |
224 | { |
225 | grid_new.template setMemory<T::value>(mem[T::value]); |
226 | |
227 | //! Allocate the memory and create the reppresentation |
228 | if (sz != 0) boost::fusion::at_c<T::value>(grid_new.get_internal_data_()).allocate(sz,np); |
229 | } |
230 | }; |
231 | |
232 | //! Case memory_traits_inte |
233 | template<typename grid_type, typename S , typename layout, typename data_type> |
234 | struct mem_setext<grid_type,S,layout,data_type,1> |
235 | { |
236 | static inline void set(grid_type & grid_new, grid_type & old, data_type & data_) |
237 | { |
238 | // std::cerr << __FILE__ << ":" << "__LINE__" << " Error, " << demangle(typeid(grid_type).name()) << " this structure does not support setting from external memory" << std::endl; |
239 | mem_setext_prp<grid_type,data_type,S> mst(grid_new,old,data_); |
240 | |
241 | // Create an empty memory allocator for the actual structure |
242 | boost::mpl::for_each_ref<boost::mpl::range_c<int,0,grid_type::value_type::max_prop>>(mst); |
243 | |
244 | old.setMemory(); |
245 | } |
246 | }; |
247 | |
248 | |
249 | //! Case memory_traits_lin |
250 | template<typename T , typename layout, typename data_type, typename grid_type, unsigned int sel = 2*is_layout_mlin<layout>::value + is_layout_inte<layout>::value > |
251 | struct mem_swap |
252 | { |
253 | static inline void swap(data_type & data_dst, data_type & data_src) |
254 | { |
255 | // move the data |
256 | data_dst.swap(data_src); |
257 | } |
258 | |
259 | template<typename Mem_type> |
260 | static inline void swap_nomode(data_type & data_dst, data_type & data_src) |
261 | { |
262 | // move the data |
263 | data_dst.swap_nomode(data_src); |
264 | } |
265 | }; |
266 | |
267 | //! Case memory_traits_inte |
268 | template<typename T , typename layout, typename data_type, typename grid_type> |
269 | struct mem_swap<T,layout,data_type,grid_type,1> |
270 | { |
271 | static inline void swap(data_type & data_dst, data_type & data_src) |
272 | { |
273 | // swap the data for each property |
274 | frswap<decltype(data_dst)> sw(data_dst,data_src); |
275 | |
276 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(sw); |
277 | } |
278 | |
279 | template<typename Mem_type> |
280 | static inline void swap_nomode(data_type & data_dst, data_type & data_src) |
281 | { |
282 | // swap the data for each property |
283 | frswap_nomode<decltype(data_dst),Mem_type> sw(data_dst,data_src); |
284 | |
285 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(sw); |
286 | } |
287 | }; |
288 | |
289 | template<typename data_type, typename layout, unsigned int sel = 2*is_layout_mlin<layout>::value + is_layout_inte<layout>::value> |
290 | struct mem_getpointer |
291 | { |
292 | template<unsigned int d> __device__ __host__ static void * getPointer(data_type & data_) |
293 | { |
294 | return data_.mem_r.get_pointer(); |
295 | } |
296 | |
297 | template<unsigned int d> __device__ __host__ static void * getPointer(const data_type & data_) |
298 | { |
299 | return data_.mem_r.get_pointer(); |
300 | } |
301 | }; |
302 | |
303 | template<typename data_type, typename layout> |
304 | struct mem_getpointer<data_type,layout,1> |
305 | { |
306 | template<unsigned int p> __device__ __host__ static void * getPointer(data_type & data_) |
307 | { |
308 | return boost::fusion::at_c<p>(data_).mem_r.get_pointer(); |
309 | } |
310 | |
311 | template<unsigned int p> __device__ __host__ static const void * getPointer(const data_type & data_) |
312 | { |
313 | return boost::fusion::at_c<p>(data_).mem_r.get_pointer(); |
314 | } |
315 | }; |
316 | |
317 | template<typename data_type, typename Mem_type, typename layout, unsigned int sel = 2*is_layout_mlin<layout>::value + is_layout_inte<layout>::value> |
318 | struct mem_setmemory |
319 | { |
320 | template<unsigned int d> static void setMemory(data_type & data_, Mem_type & m, size_t sz, bool np) |
321 | { |
322 | //! Create and set the memory allocator |
323 | data_.setMemory(m); |
324 | |
325 | //! Allocate the memory and create the reppresentation |
326 | if (sz != 0) data_.allocate(sz,np); |
327 | } |
328 | |
329 | static void setMemoryArray(data_type & data_, Mem_type * m, size_t sz, bool np) |
330 | { |
331 | //! Create and set the memory allocator |
332 | data_.setMemory(m[0]); |
333 | |
334 | //! Allocate the memory and create the reppresentation |
335 | if (sz != 0) data_.allocate(sz,np); |
336 | } |
337 | }; |
338 | |
339 | template<typename data_type, typename Mem_type, typename layout> |
340 | struct mem_setmemory<data_type,Mem_type,layout,1> |
341 | { |
342 | template<unsigned int p> static void setMemory(data_type & data_, Mem_type & m, size_t sz,bool np) |
343 | { |
344 | //! Create and set the memory allocator |
345 | boost::fusion::at_c<p>(data_).setMemory(m); |
346 | |
347 | //! Allocate the memory and create the reppresentation |
348 | if (sz != 0) boost::fusion::at_c<p>(data_).allocate(sz,np); |
349 | } |
350 | |
351 | template<typename grid_type> static void setMemoryArray(grid_type & grid, Mem_type * m, size_t sz,bool np) |
352 | { |
353 | mem_setarray<grid_type,Mem_type> ma(grid,m,sz,np); |
354 | |
355 | // Create an empty memory allocator for the actual structure |
356 | boost::mpl::for_each_ref<boost::mpl::range_c<int,0,grid_type::value_type::max_prop>>(ma); |
357 | } |
358 | }; |
359 | |
360 | |
361 | #endif /* OPENFPM_DATA_SRC_GRID_GRID_BASE_IMPL_LAYOUT_HPP_ */ |
362 | |