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
26template<typename Mem>
27class 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
41public:
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