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