HAMR
The Heterogeneous Accelerator Memory Resource
hamr_malloc_allocator.h
1 #ifndef hamr_malloc_allocator_h
2 #define hamr_malloc_allocator_h
3 
4 #include "hamr_config.h"
5 #include "hamr_env.h"
6 
7 #include <iostream>
8 #include <type_traits>
9 #include <memory>
10 #include <typeinfo>
11 #include <cassert>
12 #include <cstring>
13 
14 namespace hamr
15 {
16 /// a deleter for arrays allocated with malloc
17 template <typename T, typename E = void>
18 class malloc_deleter {};
19 
20 /// a deleter for arrays allocated with malloc, specialized for objects
21 template <typename T>
22 class HAMR_EXPORT malloc_deleter<T, typename std::enable_if<!std::is_arithmetic<T>::value>::type>
23 {
24 public:
25  /** constructs the deleter
26  * @param[in] ptr the pointer to the array to delete
27  * @param[in] n the number of elements in the array
28  */
29  malloc_deleter(T *ptr, size_t n);
30 
31  /** deletes the array
32  * @param[in] ptr the pointer to the array to delete. must be the same as
33  * that passed during construction.
34  */
35  void operator()(T *ptr);
36 
37 private:
38  T *m_ptr;
39  size_t m_elem;
40 };
41 
42 // --------------------------------------------------------------------------
43 template <typename T>
45  ::malloc_deleter(T *ptr, size_t n) : m_ptr(ptr), m_elem(n)
46 {
47 #if defined(HAMR_VERBOSE)
48  if (hamr::get_verbose())
49  {
50  std::cerr << "created malloc_deleter for array of " << n
51  << " objects of type " << typeid(T).name() << sizeof(T)
52  << " at " << m_ptr << std::endl;
53  }
54 #endif
55 }
56 
57 // --------------------------------------------------------------------------
58 template <typename T>
59 void
60 malloc_deleter<T, typename std::enable_if<!std::is_arithmetic<T>::value>::type>
61  ::operator()(T *ptr)
62 {
63  assert(ptr == m_ptr);
64 
65 #if defined(HAMR_VERBOSE)
66  if (hamr::get_verbose())
67  {
68  std::cerr << "malloc_deleter deleting array of " << m_elem
69  << " objects of type " << typeid(T).name() << sizeof(T)
70  << " at " << m_ptr << std::endl;
71  }
72 #endif
73 
74  // invoke the destructor
75  for (size_t i = 0; i < m_elem; ++i)
76  ptr[i].~T();
77 
78  // free the array
79  free(ptr);
80 }
81 
82 
83 
84 
85 
86 /// a deleter for arrays allocated with malloc, specialized for numbers
87 template <typename T>
88 class HAMR_EXPORT malloc_deleter<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
89 {
90 public:
91  /** constructs the deleter
92  * @param[in] ptr the pointer to the array to delete
93  * @param[in] n the number of elements in the array
94  */
95  malloc_deleter(T *ptr, size_t n);
96 
97  /** deletes the array
98  * @param[in] ptr the pointer to the array to delete. must be the same as
99  * that passed during construction.
100  */
101  void operator()(T *ptr);
102 
103 private:
104  T *m_ptr;
105  size_t m_elem;
106 };
107 
108 // --------------------------------------------------------------------------
109 template <typename T>
111  ::malloc_deleter(T *ptr, size_t n) : m_ptr(ptr), m_elem(n)
112 {
113 #if defined(HAMR_VERBOSE)
114  if (hamr::get_verbose())
115  {
116  std::cerr << "created malloc_deleter for array of " << n
117  << " numbers of type " << typeid(T).name() << sizeof(T)
118  << " at " << m_ptr << std::endl;
119  }
120 #endif
121 }
122 
123 // --------------------------------------------------------------------------
124 template <typename T>
125 void
126 malloc_deleter<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
127  ::operator()(T *ptr)
128 {
129  assert(ptr == m_ptr);
130 
131 #if defined(HAMR_VERBOSE)
132  if (hamr::get_verbose())
133  {
134  std::cerr << "malloc_deleter deleting array of " << m_elem
135  << " numbers of type " << typeid(T).name() << sizeof(T)
136  << " at " << m_ptr << std::endl;
137  }
138 #endif
139 
140  // free the array
141  free(ptr);
142 }
143 
144 
145 
146 
147 
148 /// a class for allocating arrays with malloc
149 template <typename T, typename E = void>
151 
152 /// a class for allocating arrays with malloc, specialized for objects
153 template <typename T>
154 struct HAMR_EXPORT malloc_allocator<T, typename std::enable_if<!std::is_arithmetic<T>::value>::type>
155 {
156  /** allocate an array of n elements.
157  * @param[in] n the number of elements to allocate
158  * @returns a shared pointer to the array that holds a deleter for the memory
159  */
160  static std::shared_ptr<T> allocate(size_t n);
161 
162  /** allocate an array of n elements.
163  * @param[in] n the number of elements to allocate
164  * @param[in] val a value to initialize the elements to
165  * @returns a shared pointer to the array that holds a deleter for the memory
166  */
167 
168  static std::shared_ptr<T> allocate(size_t n, const T &val);
169 
170  /** allocate an array of n elements.
171  * @param[in] n the number of elements to allocate
172  * @param[in] vals an array of n elements to initialize the elements with
173  * @returns a shared pointer to the array that holds a deleter for the memory
174  */
175  template <typename U>
176  static std::shared_ptr<T> allocate(size_t n, const U *vals);
177 };
178 
179 // --------------------------------------------------------------------------
180 template <typename T>
181 std::shared_ptr<T>
183  ::allocate(size_t n)
184 {
185  // allocate
186  T *ptr = (T*)malloc(n*sizeof(T));
187 
188  // construct
189  for (size_t i = 0; i < n; ++i)
190  new (&ptr[i]) T();
191 
192 #if defined(HAMR_VERBOSE)
193  if (hamr::get_verbose())
194  {
195  std::cerr << "malloc_allocator allocating array of " << n
196  << " objects of type " << typeid(T).name() << sizeof(T)
197  << " at " << ptr << std::endl;
198  }
199 #endif
200 
201  // package
202  return std::shared_ptr<T>(ptr, malloc_deleter<T>(ptr, n));
203 }
204 
205 // --------------------------------------------------------------------------
206 template <typename T>
207 std::shared_ptr<T>
208 malloc_allocator<T, typename std::enable_if<!std::is_arithmetic<T>::value>::type>
209  ::allocate(size_t n, const T &val)
210 {
211  // allocate
212  T *ptr = (T*)malloc(n*sizeof(T));
213 
214  // construct
215  for (size_t i = 0; i < n; ++i)
216  new (&ptr[i]) T(val);
217 
218 #if defined(HAMR_VERBOSE)
219  if (hamr::get_verbose())
220  {
221  std::cerr << "malloc_allocator allocating array of " << n
222  << " objects of type " << typeid(T).name() << sizeof(T)
223  << " at " << ptr << " initialized to " << val << std::endl;
224  }
225 #endif
226 
227  // package
228  return std::shared_ptr<T>(ptr, malloc_deleter<T>(ptr, n));
229 }
230 
231 // --------------------------------------------------------------------------
232 template <typename T>
233 template <typename U>
234 std::shared_ptr<T>
235 malloc_allocator<T, typename std::enable_if<!std::is_arithmetic<T>::value>::type>
236  ::allocate(size_t n, const U *vals)
237 {
238  // allocate
239  T *ptr = (T*)malloc(n*sizeof(T));
240 
241  // construct
242  for (size_t i = 0; i < n; ++i)
243  new (&ptr[i]) T(vals[i]);
244 
245 #if defined(HAMR_VERBOSE)
246  if (hamr::get_verbose())
247  {
248  std::cerr << "malloc_allocator allocating array of " << n
249  << " objects of type " << typeid(T).name() << sizeof(T)
250  << " initialized from array of objects of type "
251  << typeid(U).name() << sizeof(U) << " at " << vals
252  << std::endl;
253  }
254 #endif
255 
256  // package
257  return std::shared_ptr<T>(ptr, malloc_deleter<T>(ptr, n));
258 }
259 
260 
261 
262 
263 /// a class for allocating arrays with malloc, specialized for numbers
264 template <typename T>
265 struct HAMR_EXPORT malloc_allocator<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
266 {
267  /** allocate an array of n elements.
268  * @param[in] n the number of elements to allocate
269  * @returns a shared pointer to the array that holds a deleter for the memory
270  */
271  static std::shared_ptr<T> allocate(size_t n);
272 
273  /** allocate an array of n elements.
274  * @param[in] n the number of elements to allocate
275  * @param[in] val a value to initialize the elements to
276  * @returns a shared pointer to the array that holds a deleter for the memory
277  */
278  static std::shared_ptr<T> allocate(size_t n, const T &val);
279 
280  /** allocate an array of n elements.
281  * @param[in] n the number of elements to allocate
282  * @param[in] vals an array of n elements to initialize the elements with
283  * @returns a shared pointer to the array that holds a deleter for the memory
284  */
285  template <typename U>
286  static std::shared_ptr<T> allocate(size_t n, const U *vals);
287 };
288 
289 // --------------------------------------------------------------------------
290 template <typename T>
291 std::shared_ptr<T>
293  ::allocate(size_t n)
294 {
295  size_t n_bytes = n*sizeof(T);
296 
297  // allocate
298  T *ptr = (T*)malloc(n_bytes);
299 
300  // construct
301 #if defined(HAMR_INIT_ALLOC)
302  memset(ptr, 0, n_bytes);
303 #endif
304 
305 #if defined(HAMR_VERBOSE)
306  if (hamr::get_verbose())
307  {
308  std::cerr << "malloc_allocator allocating array of " << n
309  << " numbers of type " << typeid(T).name() << sizeof(T)
310  << " at " << ptr << std::endl;
311  }
312 #endif
313 
314  // package
315  return std::shared_ptr<T>(ptr, malloc_deleter<T>(ptr, n));
316 }
317 
318 // --------------------------------------------------------------------------
319 template <typename T>
320 std::shared_ptr<T>
321 malloc_allocator<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
322  ::allocate(size_t n, const T &val)
323 {
324  size_t n_bytes = n*sizeof(T);
325 
326  // allocate
327  T *ptr = (T*)malloc(n_bytes);
328 
329  // construct
330  for (size_t i = 0; i < n; ++i)
331  ptr[i] = val;
332 
333 #if defined(HAMR_VERBOSE)
334  if (hamr::get_verbose())
335  {
336  std::cerr << "malloc_allocator allocating array of " << n
337  << " numbers of type " << typeid(T).name() << sizeof(T)
338  << " at " << ptr << " initialized to " << val << std::endl;
339  }
340 #endif
341 
342  // package
343  return std::shared_ptr<T>(ptr, malloc_deleter<T>(ptr, n));
344 }
345 
346 // --------------------------------------------------------------------------
347 template <typename T>
348 template <typename U>
349 std::shared_ptr<T>
350 malloc_allocator<T, typename std::enable_if<std::is_arithmetic<T>::value>::type>
351  ::allocate(size_t n, const U *vals)
352 {
353  size_t n_bytes = n*sizeof(T);
354 
355  // allocate
356  T *ptr = (T*)malloc(n_bytes);
357 
358  // construct
359  for (size_t i = 0; i < n; ++i)
360  ptr[i] = vals[i];
361 
362 #if defined(HAMR_VERBOSE)
363  if (hamr::get_verbose())
364  {
365  std::cerr << "malloc_allocator allocating array of " << n
366  << " numbers of type " << typeid(T).name() << sizeof(T)
367  << " at " << ptr << " initialized from an array of numbers of type "
368  << typeid(U).name() << sizeof(U) << " at " << vals << std::endl;
369  }
370 #endif
371 
372  // package
373  return std::shared_ptr<T>(ptr, malloc_deleter<T>(ptr, n));
374 }
375 
376 };
377 
378 #endif
hamr::buffer_allocator::malloc
@ malloc
allocates memory with malloc
hamr::get_verbose
constexpr HAMR_EXPORT int get_verbose()
returns the value of the HAMR_VERBOSE environment variable
Definition: hamr_env.h:14
hamr::malloc_allocator
a class for allocating arrays with malloc
Definition: hamr_malloc_allocator.h:150
hamr
heterogeneous accelerator memory resource
Definition: hamr_buffer.h:40
hamr::malloc_deleter
a deleter for arrays allocated with malloc
Definition: hamr_malloc_allocator.h:18