HermesCommon  3.0
memory_handling.h
Go to the documentation of this file.
1 // This file is part of HermesCommon.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
15 
19 #ifndef __HERMES_COMMON_MEMORY_HANDLING_H
20 #define __HERMES_COMMON_MEMORY_HANDLING_H
21 
22 #ifdef WITH_PJLIB
23 #include "pjlib.h"
24 #endif
25 
26 #include "exceptions.h"
27 #include "api.h"
28 #include <cstddef>
29 
30 // If C++ 11 is not supported
31 namespace std
32 {
33 #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ >= 5))
34 # define HACK_GCC_ITS_CPP0X 1
35 #endif
36 #if defined(nullptr_t) || (__cplusplus >= 199711L) || defined(HACK_GCC_ITS_CPP0X)
37 #include <type_traits>
38 #else
39  template<typename ArrayItem>
40  class is_pod
41  {
42  public:
43  static const bool value = true;
44  };
45 #define static_assert(expr, msg) true
46 #endif
47 }
48 namespace Hermes
49 {
50 #ifdef WITH_PJLIB
51  HERMES_COMMON_API extern pj_caching_pool HermesCommonMemoryPoolCache;
52  class GlobalPoolCache
53  {
54  public:
55  GlobalPoolCache()
56  {
57  pj_init();
58  pj_caching_pool_init(&HermesCommonMemoryPoolCache, NULL, 1024 * 1024 * 1024);
59 
60  pj_thread_desc rtpdesc;
61  pj_thread_t *thread;
62  pj_bzero(rtpdesc, sizeof(rtpdesc));
63  if (!pj_thread_is_registered())
64  pj_thread_register(NULL, rtpdesc, &thread);
65 
66  this->globalPool = pj_pool_create(&HermesCommonMemoryPoolCache.factory, // the factory
67  "pool-Global", // pool's name
68  100000000, // initial size
69  10000000, // increment size
70  NULL);
71  };
72 
73  ~GlobalPoolCache()
74  {
75  pj_pool_release(this->globalPool);
76  pj_caching_pool_destroy(&HermesCommonMemoryPoolCache);
77  }
78 
79  inline void* pool_calloc(pj_size_t count, pj_size_t elem)
80  {
81  return pj_pool_calloc(globalPool, count, elem);
82  };
83 
84  inline void* pool_alloc(pj_size_t size)
85  {
86  return pj_pool_alloc(globalPool, size);
87  };
88 
89  pj_pool_t* globalPool;
90  };
91  HERMES_COMMON_API extern GlobalPoolCache hermesCommonGlobalPoolCache;
92 #endif
93 
94  template<typename Caller, typename ArrayItem>
95  ArrayItem* calloc_with_check(int size, Caller* const caller, bool force_malloc = false)
96  {
97  if (size == 0)
98  return nullptr;
99  ArrayItem* new_array;
100  if (force_malloc)
101  new_array = (ArrayItem*)calloc(size, sizeof(ArrayItem));
102  else
103  {
104 #ifdef WITH_PJLIB
105  new_array = (ArrayItem*)hermesCommonGlobalPoolCache.pool_calloc(size, sizeof(ArrayItem));
106 #else
107  new_array = new ArrayItem[size];
108  memset(new_array, 0, sizeof(ArrayItem)* size);
109 #endif
110  }
111  if (new_array)
112  return new_array;
113  else
114  {
115  caller->free();
116  throw Hermes::Exceptions::Exception("Hermes::calloc_with_check() failed to allocate %i bytes.", size * sizeof(ArrayItem));
117  return nullptr;
118  }
119  }
120 
121  template<typename ArrayItem>
122  ArrayItem* calloc_with_check(int size, bool force_malloc = false)
123  {
124  if (size == 0)
125  return nullptr;
126  ArrayItem* new_array;
127  if (force_malloc)
128  new_array = (ArrayItem*)calloc(size, sizeof(ArrayItem));
129  else
130  {
131 #ifdef WITH_PJLIB
132  new_array = (ArrayItem*)hermesCommonGlobalPoolCache.pool_calloc(size, sizeof(ArrayItem));
133 #else
134  new_array = new ArrayItem[size];
135  memset(new_array, 0, sizeof(ArrayItem)* size);
136 #endif
137  }
138  if (new_array)
139  return new_array;
140  else
141  {
142  throw Hermes::Exceptions::Exception("Hermes::calloc_with_check() failed to allocate %i bytes.", size * sizeof(ArrayItem));
143  return nullptr;
144  }
145  }
146 
147  template<typename Caller, typename ArrayItem>
148  ArrayItem* malloc_with_check(int size, Caller* const caller, bool force_malloc = false)
149  {
150  if (size == 0)
151  return nullptr;
152 
153  ArrayItem* new_array;
154 
155  if (force_malloc)
156  new_array = (ArrayItem*)malloc(size * sizeof(ArrayItem));
157  else
158 #ifdef WITH_PJLIB
159  new_array = (ArrayItem*)hermesCommonGlobalPoolCache.pool_alloc(size * sizeof(ArrayItem));
160 #else
161  new_array = new ArrayItem[size];
162 #endif
163  if (new_array)
164  return new_array;
165  else
166  {
167  if (caller)
168  caller->free();
169  throw Hermes::Exceptions::Exception("Hermes::malloc_with_check() failed to allocate %i bytes.", size * sizeof(ArrayItem));
170  return nullptr;
171  }
172  }
173 
174  template<typename ArrayItem>
175  ArrayItem* malloc_with_check(int size, bool force_malloc = false)
176  {
177  if (size == 0)
178  return nullptr;
179  ArrayItem* new_array;
180  if (force_malloc)
181  new_array = (ArrayItem*)malloc(size * sizeof(ArrayItem));
182  else
183 #ifdef WITH_PJLIB
184  new_array = (ArrayItem*)hermesCommonGlobalPoolCache.pool_alloc(size * sizeof(ArrayItem));
185 #else
186  new_array = new ArrayItem[size];
187 #endif
188  if (new_array)
189  return new_array;
190  else
191  {
192  throw Hermes::Exceptions::Exception("Hermes::malloc_with_check() failed to allocate %i bytes.", size * sizeof(ArrayItem));
193  return nullptr;
194  }
195  }
196 
197  template<typename ArrayItem>
198  ArrayItem* malloc_with_check_direct_size(int size)
199  {
200  if (size == 0)
201  return nullptr;
202  ArrayItem* new_array;
203 #ifdef WITH_PJLIB
204  new_array = (ArrayItem*)hermesCommonGlobalPoolCache.pool_alloc(size * sizeof(ArrayItem));
205 #else
206  new_array = (ArrayItem*)malloc(size);
207 #endif
208  if (new_array)
209  return new_array;
210  else
211  {
212  throw Hermes::Exceptions::Exception("Hermes::malloc_with_check_direct_size() failed to allocate %i bytes.", size);
213  return nullptr;
214  }
215  }
216 
217  template<typename ArrayItem>
218  ArrayItem* calloc_with_check_direct_size(int size)
219  {
220  if (size == 0)
221  return nullptr;
222  ArrayItem* new_array;
223 #ifdef WITH_PJLIB
224  new_array = (ArrayItem*)hermesCommonGlobalPoolCache.pool_calloc(size * sizeof(ArrayItem));
225 #else
226  new_array = (ArrayItem*)malloc(size);
227  if (new_array)
228  memset(new_array, 0, size);
229 #endif
230  if (new_array)
231  return new_array;
232  else
233  {
234  throw Hermes::Exceptions::Exception("Hermes::malloc_with_check_direct_size() failed to allocate %i bytes.", size);
235  return nullptr;
236  }
237  }
238 
239  template<typename Caller, typename ArrayItem>
240  ArrayItem* realloc_with_check(ArrayItem*& original_array, int new_size, Caller* const caller)
241  {
242  if (new_size == 0)
243  return nullptr;
244 
245  ArrayItem* new_array = (ArrayItem*)realloc(original_array, new_size * sizeof(ArrayItem));
246  if (new_array)
247  return original_array = new_array;
248  else
249  {
250  caller->free();
251  throw Hermes::Exceptions::Exception("Hermes::realloc_with_check() failed to reallocate %i bytes.", new_size * sizeof(ArrayItem));
252  return nullptr;
253  }
254  }
255 
256  template<typename ArrayItem>
257  ArrayItem* realloc_with_check(ArrayItem*& original_array, int new_size)
258  {
259  if (new_size == 0)
260  return nullptr;
261 
262  ArrayItem* new_array = (ArrayItem*)realloc(original_array, new_size * sizeof(ArrayItem));
263  if (new_array)
264  return original_array = new_array;
265  else
266  {
267  throw Hermes::Exceptions::Exception("Hermes::realloc_with_check() failed to reallocate %i bytes.", new_size * sizeof(ArrayItem));
268  return nullptr;
269  }
270  }
271 
272  template<typename ArrayItem>
273  void free_with_check(ArrayItem*& ptr, bool force_malloc = false)
274  {
275  if (ptr)
276  {
277  if (force_malloc)
278  {
279  ::free(ptr);
280  ptr = nullptr;
281  }
282  else
283  {
284 #ifndef WITH_PJLIB
285  delete[] ptr;
286  ptr = nullptr;
287 #endif
288  }
289  }
290  }
291 }
292 #endif
General namespace for the Hermes library.
Exception interface Basically a std::exception, but with a constructor with string and with print_msg...
Definition: exceptions.h:49
Main Hermes API.
Definition: compat.h:85
File containing definition of exceptions classes.