1 | /* ExtPreAlloc.hpp |
2 | * |
3 | * Created on: Apr 3, 2015 |
4 | * Author: Pietro Incardona |
5 | */ |
6 | |
7 | #ifndef EXTPREALLOC_HPP_ |
8 | #define EXTPREALLOC_HPP_ |
9 | |
10 | #include <stddef.h> |
11 | #include "memory.hpp" |
12 | #include <iostream> |
13 | |
14 | /*! Preallocated memory sequence |
15 | * |
16 | * External pre-allocated memory, is a class that preallocate memory and than it answer |
17 | * to a particular allocation pattern |
18 | * |
19 | * \warning zero sized allocation are removed from the request pattern |
20 | * |
21 | * \tparam Base memory allocation class [Example] HeapMemory or CudaMemory |
22 | * |
23 | * |
24 | */ |
25 | |
26 | template<typename Mem> |
27 | class ExtPreAlloc : public memory |
28 | { |
29 | //! Actual allocation pointer |
30 | size_t a_seq ; |
31 | |
32 | //! Last allocation size |
33 | size_t l_size; |
34 | |
35 | //! Main class for memory allocation |
36 | Mem * mem; |
37 | |
38 | //! Reference counter |
39 | long int ref_cnt; |
40 | |
41 | public: |
42 | |
43 | virtual ~ExtPreAlloc() |
44 | { |
45 | if (ref_cnt != 0) |
46 | std::cerr << "Error: " << __FILE__ << " " << __LINE__ << " destroying a live object" << "\n" ; |
47 | } |
48 | |
49 | //! Default constructor |
50 | ExtPreAlloc() |
51 | :a_seq(0),l_size(0),mem(NULL),ref_cnt(0) |
52 | { |
53 | } |
54 | |
55 | /*! \brief Preallocated memory sequence |
56 | * |
57 | * \param size number of bytes |
58 | * \param mem external memory, used if you want to keep the memory |
59 | * |
60 | */ |
61 | ExtPreAlloc(size_t size, Mem & mem) |
62 | :a_seq(0),l_size(0),mem(&mem),ref_cnt(0) |
63 | { |
64 | // Allocate the total size of memory |
65 | mem.resize(size); |
66 | } |
67 | |
68 | /*! \brief Copy the memory from device to device |
69 | * |
70 | * \param m memory from where to copy |
71 | * |
72 | */ |
73 | bool copyDeviceToDevice(const ExtPreAlloc<Mem> & m) |
74 | { |
75 | return mem->copyDeviceToDevice(*m.mem); |
76 | } |
77 | |
78 | /*! \brief special function to move memory from a raw device pointer |
79 | * |
80 | * \param start byte |
81 | * \param stop byte |
82 | * |
83 | * \param offset destination byte |
84 | * |
85 | */ |
86 | void deviceToDevice(void * ptr, size_t start, size_t stop, size_t offset) |
87 | { |
88 | mem->deviceToDevice(ptr,start,stop,offset); |
89 | } |
90 | |
91 | static bool isDeviceHostSame() |
92 | { |
93 | return Mem::isDeviceHostSame(); |
94 | } |
95 | |
96 | //! Increment the reference counter |
97 | virtual void incRef() |
98 | {ref_cnt++;} |
99 | |
100 | //! Decrement the reference counter |
101 | virtual void decRef() |
102 | {ref_cnt--;} |
103 | |
104 | //! Return the reference counter |
105 | virtual long int ref() |
106 | { |
107 | return ref_cnt; |
108 | } |
109 | |
110 | //! flush the memory |
111 | virtual bool flush() {return mem->flush();}; |
112 | |
113 | /*! \brief fill host and device memory with the selected byte |
114 | * |
115 | * |
116 | */ |
117 | virtual void fill(unsigned char c) |
118 | { |
119 | mem->fill(c); |
120 | } |
121 | |
122 | /*! \brief Allocate a chunk of memory |
123 | * |
124 | * Allocate a chunk of memory |
125 | * |
126 | * \param sz size of the chunk of memory to allocate in byte |
127 | * |
128 | */ |
129 | virtual bool allocate(size_t sz) |
130 | { |
131 | // Zero sized allocation are ignored |
132 | if (sz == 0) |
133 | return true; |
134 | |
135 | a_seq = l_size; |
136 | l_size += sz; |
137 | |
138 | // Check we do not overflow the allocated memory |
139 | #ifdef SE_CLASS1 |
140 | |
141 | if (l_size > mem->size()) |
142 | std::cerr << __FILE__ << ":" << __LINE__ << " Error requesting more memory than the allocated one" << std::endl; |
143 | |
144 | #endif |
145 | |
146 | return true; |
147 | } |
148 | |
149 | /*! \brief Allocate a chunk of memory |
150 | * |
151 | * Allocate a chunk of memory |
152 | * |
153 | * \param sz size of the chunk of memory to allocate in byte |
154 | * |
155 | */ |
156 | bool allocate_nocheck(size_t sz) |
157 | { |
158 | // Zero sized allocation are ignored |
159 | if (sz == 0) |
160 | return true; |
161 | |
162 | a_seq = l_size; |
163 | l_size += sz; |
164 | |
165 | return true; |
166 | } |
167 | |
168 | /*! \brief Return the end pointer of the previous allocated memory |
169 | * |
170 | * \return the pointer |
171 | * |
172 | */ |
173 | void * getPointerEnd() |
174 | { |
175 | return (char *)mem->getPointer() + l_size; |
176 | } |
177 | |
178 | /*! \brief Return the device end pointer of the previous allocated memory |
179 | * |
180 | * \return the pointer |
181 | * |
182 | */ |
183 | void * getDevicePointerEnd() |
184 | { |
185 | return (char *)mem->getDevicePointer() + l_size; |
186 | } |
187 | |
188 | /*! \brief The the base pointer of the preallocate memory |
189 | * |
190 | * \return the base pointer |
191 | * |
192 | */ |
193 | void * getPointerBase() |
194 | { |
195 | return mem->getPointer(); |
196 | } |
197 | |
198 | /*! \brief Return the pointer of the last allocation |
199 | * |
200 | * \return the pointer |
201 | * |
202 | */ |
203 | virtual void * getDevicePointer() |
204 | { |
205 | return (((unsigned char *)mem->getDevicePointer()) + a_seq ); |
206 | } |
207 | |
208 | /*! \brief Return the pointer of the last allocation |
209 | * |
210 | * \return the pointer |
211 | * |
212 | */ |
213 | virtual void hostToDevice() |
214 | { |
215 | mem->hostToDevice(); |
216 | } |
217 | |
218 | /*! \brief Return the pointer of the last allocation |
219 | * |
220 | * \return the pointer |
221 | * |
222 | */ |
223 | virtual void hostToDevice(size_t start, size_t stop) |
224 | { |
225 | mem->hostToDevice(start,stop); |
226 | } |
227 | |
228 | //! Do nothing |
229 | virtual void deviceToHost() |
230 | { |
231 | mem->deviceToHost(); |
232 | }; |
233 | |
234 | //! Do nothing |
235 | virtual void deviceToHost(size_t start, size_t stop) |
236 | { |
237 | mem->deviceToHost(start,stop); |
238 | }; |
239 | |
240 | /*! \brief Return the pointer of the last allocation |
241 | * |
242 | * \return the pointer |
243 | * |
244 | */ |
245 | virtual void * getPointer() |
246 | { |
247 | return (((unsigned char *)mem->getPointer()) + a_seq ); |
248 | } |
249 | |
250 | /*! \brief Return the pointer of the last allocation |
251 | * |
252 | * \return the pointer |
253 | * |
254 | */ |
255 | virtual const void * getPointer() const |
256 | { |
257 | return (((unsigned char *)mem->getPointer()) + a_seq); |
258 | } |
259 | |
260 | /*! \brief Get the base memory pointer increased with an offset |
261 | * |
262 | * \param offset memory offset |
263 | * |
264 | */ |
265 | void * getPointerOffset(size_t offset) |
266 | { |
267 | return (((unsigned char *)mem->getPointer()) + offset); |
268 | } |
269 | |
270 | /*! \brief Allocate or resize the allocated memory |
271 | * |
272 | * Resize the allocated memory, if request is smaller than the allocated, memory |
273 | * is not resized |
274 | * |
275 | * \param sz size |
276 | * \return true if the resize operation complete correctly |
277 | * |
278 | */ |
279 | |
280 | virtual bool resize(size_t sz) |
281 | { |
282 | return allocate(sz); |
283 | } |
284 | |
285 | /*! \brief Get the size of the LAST allocated memory |
286 | * |
287 | * Get the size of the allocated memory |
288 | * |
289 | * \return the size of the allocated memory |
290 | * |
291 | */ |
292 | |
293 | virtual size_t size() const |
294 | { |
295 | return l_size; |
296 | } |
297 | |
298 | /*! \brief Destroy memory |
299 | * |
300 | */ |
301 | |
302 | void destroy() |
303 | { |
304 | mem->destroy(); |
305 | } |
306 | |
307 | /*! \brief Copy memory |
308 | * |
309 | */ |
310 | |
311 | virtual bool copy(const memory & m) |
312 | { |
313 | return mem->copy(m); |
314 | } |
315 | |
316 | /*! \brief Allocated Memory is never initialized |
317 | * |
318 | * \return false |
319 | * |
320 | */ |
321 | bool isInitialized() |
322 | { |
323 | return false; |
324 | } |
325 | |
326 | /*! \brief Calculate the total memory required to pack the message |
327 | * |
328 | * \return the total required memory |
329 | * |
330 | */ |
331 | static size_t calculateMem(std::vector<size_t> & mm) |
332 | { |
333 | size_t s = 0; |
334 | |
335 | for (size_t i = 0 ; i < mm.size() ; i++) |
336 | s += mm[i]; |
337 | |
338 | return s; |
339 | } |
340 | |
341 | /*! \brief shift the pointer backward |
342 | * |
343 | * \warning when you shift backward the pointer, the last allocation is lost |
344 | * this mean that you have to do again an allocation. |
345 | * |
346 | * This function is useful to go ahead in memory and fill the memory later on |
347 | * |
348 | * \code |
349 | |
350 | mem.allocate(16); <------ Here we allocate 16 byte but we do not fill it because |
351 | subsequently we do another allocation without using mem |
352 | unsigned char * start = (unsigned char *)mem.getPointer() |
353 | mem.allocate(100) |
354 | |
355 | // ... |
356 | // ... |
357 | // Code that fill mem in some way and do other mem.allocate(...) |
358 | // ... |
359 | // ... |
360 | |
361 | unsigned char * final = (unsigned char *)mem.getPointer() |
362 | mem.shift_backward(final - start); |
363 | mem.allocate(16); <------ Here I am getting the same memory that I request for the |
364 | first allocate |
365 | |
366 | // we now fill the memory |
367 | |
368 | \endcode |
369 | * |
370 | * |
371 | * |
372 | * \param how many byte to shift |
373 | * |
374 | */ |
375 | void shift_backward(size_t sz) |
376 | { |
377 | a_seq -= sz; |
378 | l_size = a_seq; |
379 | } |
380 | |
381 | /*! \brief shift the pointer forward |
382 | * |
383 | * The same as shift backward, but in this case it move the pointer forward |
384 | * |
385 | * In general you use this function after the you went back with shift_backward |
386 | * and you have to move forward again |
387 | * |
388 | * \warning when you shift forward the pointer, the last allocation is lost |
389 | * this mean that you have to do again an allocation. |
390 | * |
391 | */ |
392 | void shift_forward(size_t sz) |
393 | { |
394 | a_seq += sz; |
395 | l_size = a_seq; |
396 | } |
397 | |
398 | /*! \brief Get offset |
399 | * |
400 | * \return the offset |
401 | * |
402 | */ |
403 | size_t getOffset() |
404 | { |
405 | return a_seq; |
406 | } |
407 | |
408 | /*! \brief Get offset |
409 | * |
410 | * \return the offset |
411 | * |
412 | */ |
413 | size_t getOffsetEnd() |
414 | { |
415 | return l_size; |
416 | } |
417 | |
418 | /*! \brief Reset the internal counters |
419 | * |
420 | * |
421 | */ |
422 | void reset() |
423 | { |
424 | a_seq = 0; |
425 | l_size = 0; |
426 | } |
427 | }; |
428 | |
429 | #endif /* PREALLOCHEAPMEMORY_HPP_ */ |
430 | |