memory.h
1 /*************************************************************************/
2 /* memory.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef MEMORY_H
30 #define MEMORY_H
31 
32 #include <stddef.h>
33 #include "safe_refcount.h"
34 #include "os/memory_pool_dynamic.h"
35 #include "os/memory_pool_static.h"
36 
37 
42 class MID {
43 
44  struct Data {
45 
46  SafeRefCount refcount;
47  MemoryPoolDynamic::ID id;
48  };
49 
50  mutable Data *data;
51 
52  void unref() {
53 
54  if (!data)
55  return;
56  if (data->refcount.unref()) {
57 
58  if (data->id!=MemoryPoolDynamic::INVALID_ID)
59  MemoryPoolDynamic::get_singleton()->free(data->id);
60  MemoryPoolStatic::get_singleton()->free(data);
61  }
62 
63  data=NULL;
64  }
65 
66  void ref(Data *p_data) {
67 
68  if (data==p_data)
69  return;
70  unref();
71 
72  if (p_data && p_data->refcount.ref())
73  data=p_data;
74  }
75 
76 friend class MID_Lock;
77 
78  inline void lock() {
79 
80  if (data && data->id!=MemoryPoolDynamic::INVALID_ID)
81  MemoryPoolDynamic::get_singleton()->lock(data->id);
82  }
83  inline void unlock() {
84 
85  if (data && data->id!=MemoryPoolDynamic::INVALID_ID)
86  MemoryPoolDynamic::get_singleton()->unlock(data->id);
87 
88  }
89 
90  inline void * get() {
91 
92  if (data && data->id!=MemoryPoolDynamic::INVALID_ID)
93  return MemoryPoolDynamic::get_singleton()->get(data->id);
94 
95  return NULL;
96  }
97 
98  Error _resize(size_t p_size) {
99 
100  if (p_size==0 && (!data || data->id==MemoryPoolDynamic::INVALID_ID))
101  return OK;
102  if (p_size && !data) {
103  // create data because we'll need it
104  data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
105  ERR_FAIL_COND_V( !data,ERR_OUT_OF_MEMORY );
106  data->refcount.init();
107  data->id=MemoryPoolDynamic::INVALID_ID;
108  }
109 
110  if (p_size==0 && data && data->id==MemoryPoolDynamic::INVALID_ID) {
111 
112  MemoryPoolDynamic::get_singleton()->free(data->id);
113  data->id=MemoryPoolDynamic::INVALID_ID;
114  }
115 
116  if (p_size>0) {
117 
118  if (data->id==MemoryPoolDynamic::INVALID_ID) {
119 
120  data->id=MemoryPoolDynamic::get_singleton()->alloc(p_size,"Unnamed MID");
121  ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
122 
123  } else {
124 
125  MemoryPoolDynamic::get_singleton()->realloc(data->id,p_size);
126  ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
127 
128  }
129  }
130 
131  return OK;
132  }
133 friend class Memory;
134 
135  MID(MemoryPoolDynamic::ID p_id) {
136 
137  data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
138  data->refcount.init();
139  data->id=p_id;
140  }
141 public:
142 
143  bool is_valid() const { return data; }
144  operator bool() const { return data; }
145 
146 
147  size_t get_size() const { return (data && data->id!=MemoryPoolDynamic::INVALID_ID) ? MemoryPoolDynamic::get_singleton()->get_size(data->id) : 0; }
148  Error resize(size_t p_size) { return _resize(p_size); }
149  inline void operator=(const MID& p_mid) { ref( p_mid.data ); }
150  inline bool is_locked() const { return (data && data->id!=MemoryPoolDynamic::INVALID_ID) ? MemoryPoolDynamic::get_singleton()->is_locked(data->id) : false; }
151  inline MID(const MID& p_mid) { data=NULL; ref( p_mid.data ); }
152  inline MID() { data = NULL; }
153  ~MID() { unref(); }
154 };
155 
156 
157 class MID_Lock {
158 
159  MID mid;
160 
161 public:
162 
163  void *data() { return mid.get(); }
164 
165  void operator=(const MID_Lock& p_lock ) { mid.unlock(); mid = p_lock.mid; mid.lock(); }
166  inline MID_Lock(const MID& p_mid) { mid=p_mid; mid.lock(); }
167  inline MID_Lock(const MID_Lock& p_lock) { mid=p_lock.mid; mid.lock(); }
168  MID_Lock() {}
169  ~MID_Lock() { mid.unlock(); }
170 };
171 
172 
173 class Memory{
174 
175  Memory();
176 public:
177 
178  static void * alloc_static(size_t p_bytes,const char *p_descr="");
179  static void * realloc_static(void *p_memory,size_t p_bytes);
180  static void free_static(void *p_ptr);
181  static size_t get_static_mem_available();
182  static size_t get_static_mem_usage();
183  static size_t get_static_mem_max_usage();
184  static void dump_static_mem_to_file(const char* p_file);
185 
186  static MID alloc_dynamic(size_t p_bytes, const char *p_descr="");
187  static Error realloc_dynamic(MID p_mid,size_t p_bytes);
188 
189  static size_t get_dynamic_mem_available();
190  static size_t get_dynamic_mem_usage();
191 
192 };
193 
194 template<class T>
195 struct MemAalign {
196  static _FORCE_INLINE_ int get_align() { return DEFAULT_ALIGNMENT; }
197 };
198 
200 public:
201  _FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, ""); }
202  _FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr); }
203 
204 };
205 
206 
207 void * operator new(size_t p_size,const char *p_description);
208 void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size));
209 
210 void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description);
211 
212 #ifdef DEBUG_MEMORY_ENABLED
213 
214 #define memalloc(m_size) Memory::alloc_static(m_size, __FILE__ ":" __STR(__LINE__) ", memalloc.")
215 #define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
216 #define memfree(m_size) Memory::free_static(m_size)
217 
218 #else
219 
220 #define memalloc(m_size) Memory::alloc_static(m_size)
221 #define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
222 #define memfree(m_size) Memory::free_static(m_size)
223 
224 #endif
225 
226 #ifdef DEBUG_MEMORY_ENABLED
227 #define dynalloc(m_size) Memory::alloc_dynamic(m_size, __FILE__ ":" __STR(__LINE__) ", type: DYNAMIC")
228 #define dynrealloc(m_mem,m_size) m_mem.resize(m_size)
229 
230 #else
231 
232 #define dynalloc(m_size) Memory::alloc_dynamic(m_size)
233 #define dynrealloc(m_mem,m_size) m_mem.resize(m_size)
234 
235 #endif
236 
237 
238 _ALWAYS_INLINE_ void postinitialize_handler(void *) {}
239 
240 
241 template<class T>
242 _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
243 
244  postinitialize_handler(p_obj);
245  return p_obj;
246 }
247 
248 #ifdef DEBUG_MEMORY_ENABLED
249 
250 #define memnew(m_class) _post_initialize(new(__FILE__ ":" __STR(__LINE__) ", memnew type: " __STR(m_class)) m_class)
251 
252 #else
253 
254 #define memnew(m_class) _post_initialize(new("") m_class)
255 
256 #endif
257 
258 _ALWAYS_INLINE_ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) {
259 // void *failptr=0;
260 // ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */
261 
262  return p_pointer;
263 }
264 
265 
266 #define memnew_allocator(m_class,m_allocator) _post_initialize(new(m_allocator::alloc) m_class)
267 #define memnew_placement(m_placement,m_class) _post_initialize(new(m_placement,sizeof(m_class),"") m_class)
268 
269 
270 _ALWAYS_INLINE_ bool predelete_handler(void *) { return true; }
271 
272 template<class T>
273 void memdelete(T *p_class) {
274 
275  if (!predelete_handler(p_class))
276  return; // doesn't want to be deleted
277  p_class->~T();
278  Memory::free_static(p_class);
279 }
280 
281 template<class T,class A>
282 void memdelete_allocator(T *p_class) {
283 
284  if (!predelete_handler(p_class))
285  return; // doesn't want to be deleted
286  p_class->~T();
287  A::free(p_class);
288 }
289 
290 #define memdelete_notnull(m_v) { if (m_v) memdelete(m_v); }
291 #ifdef DEBUG_MEMORY_ENABLED
292 
293 #define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count,__FILE__ ":" __STR(__LINE__) ", memnew_arr type: " _STR(m_class))
294 
295 #else
296 
297 #define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count)
298 
299 #endif
300 
301 template<typename T>
302 T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
303 
304  if (p_elements==0)
305  return 0;
309  size_t len = sizeof(T) * p_elements;
310  unsigned int *mem = (unsigned int*)Memory::alloc_static( len + MAX(sizeof(size_t), DEFAULT_ALIGNMENT), p_descr );
311  T *failptr=0; //get rid of a warning
312  ERR_FAIL_COND_V( !mem, failptr );
313  *mem=p_elements;
314  mem = (unsigned int *)( ((uint8_t*)mem) + MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
315  T* elems = (T*)mem;
316 
317  /* call operator new */
318  for (size_t i=0;i<p_elements;i++) {
319  new(&elems[i],sizeof(T),p_descr) T;
320  }
321 
322  return (T*)mem;
323 }
324 
330 template<typename T>
331 size_t memarr_len(const T *p_class) {
332 
333  uint8_t* ptr = ((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT);
334  return *(size_t*)ptr;
335 }
336 
337 template<typename T>
338 void memdelete_arr(T *p_class) {
339 
340  unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
341 
342  for (unsigned int i=0;i<*elems;i++) {
343 
344  p_class[i].~T();
345  };
346  Memory::free_static(elems);
347 }
348 
349 
350 struct _GlobalNil {
351 
352  int color;
353  _GlobalNil *right;
354  _GlobalNil *left;
355  _GlobalNil *parent;
356 
357  _GlobalNil();
358 
359 };
360 
362 
363  static _GlobalNil _nil;
364 };
365 
366 
367 
368 #endif
Definition: safe_refcount.h:336
virtual void * alloc(size_t p_bytes, const char *p_description)=0
Pointer in p_description shold be to a const char const like "hello".
Definition: memory.h:42
Definition: memory.h:195
Definition: memory.h:173
Definition: memory.h:361
Definition: memory.h:350
virtual void free(void *p_ptr)=0
Pointer in p_description shold be to a const char const.
Definition: memory.h:157
Definition: memory.h:199