allocator.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef BX_ALLOCATOR_H_HEADER_GUARD
  6. #define BX_ALLOCATOR_H_HEADER_GUARD
  7. #include "bx.h"
  8. #include <memory.h>
  9. #include <new>
  10. #if BX_CONFIG_ALLOCATOR_CRT
  11. # include <malloc.h>
  12. #endif // BX_CONFIG_ALLOCATOR_CRT
  13. #if BX_CONFIG_ALLOCATOR_DEBUG
  14. # define BX_ALLOC(_allocator, _size) bx::alloc(_allocator, _size, __FILE__, __LINE__)
  15. # define BX_REALLOC(_allocator, _ptr, _size) bx::realloc(_allocator, _ptr, _size, __FILE__, __LINE__)
  16. # define BX_FREE(_allocator, _ptr) bx::free(_allocator, _ptr, __FILE__, __LINE__)
  17. # define BX_ALIGNED_ALLOC(_allocator, _size, _align) bx::alignedAlloc(_allocator, _size, _align, __FILE__, __LINE__)
  18. # define BX_ALIGNED_REALLOC(_allocator, _ptr, _size, _align) bx::alignedRealloc(_allocator, _ptr, _size, _align, __FILE__, __LINE__)
  19. # define BX_ALIGNED_FREE(_allocator, _ptr) bx::alignedFree(_allocator, _ptr, __FILE__, __LINE__)
  20. # define BX_NEW(_allocator, _type) new(BX_ALLOC(_allocator, sizeof(_type) ) ) _type
  21. # define BX_DELETE(_allocator, _ptr) bx::deleteObject(_allocator, _ptr, __FILE__, __LINE__)
  22. #else
  23. # define BX_ALLOC(_allocator, _size) bx::alloc(_allocator, _size)
  24. # define BX_REALLOC(_allocator, _ptr, _size) bx::realloc(_allocator, _ptr, _size)
  25. # define BX_FREE(_allocator, _ptr) bx::free(_allocator, _ptr)
  26. # define BX_ALIGNED_ALLOC(_allocator, _size, _align) bx::alignedAlloc(_allocator, _size, _align)
  27. # define BX_ALIGNED_REALLOC(_allocator, _ptr, _size, _align) bx::alignedRealloc(_allocator, _ptr, _size, _align)
  28. # define BX_ALIGNED_FREE(_allocator, _ptr) bx::alignedFree(_allocator, _ptr)
  29. # define BX_NEW(_allocator, _type) ::new(BX_ALLOC(_allocator, sizeof(_type) ) ) _type
  30. # define BX_DELETE(_allocator, _ptr) bx::deleteObject(_allocator, _ptr)
  31. #endif // BX_CONFIG_DEBUG_ALLOC
  32. #ifndef BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT
  33. # define BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT 8
  34. #endif // BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT
  35. namespace bx
  36. {
  37. /// Aligns pointer to nearest next aligned address. _align must be power of two.
  38. inline void* alignPtr(void* _ptr, size_t _extra, size_t _align = BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT)
  39. {
  40. union { void* ptr; size_t addr; } un;
  41. un.ptr = _ptr;
  42. size_t unaligned = un.addr + _extra; // space for header
  43. size_t mask = _align-1;
  44. size_t aligned = BX_ALIGN_MASK(unaligned, mask);
  45. un.addr = aligned;
  46. return un.ptr;
  47. }
  48. /// Check if pointer is aligned. _align must be power of two.
  49. inline bool isPtrAligned(const void* _ptr, size_t _align = BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT)
  50. {
  51. union { const void* ptr; size_t addr; } un;
  52. un.ptr = _ptr;
  53. return 0 == (un.addr & (_align-1) );
  54. }
  55. struct BX_NO_VTABLE AllocatorI
  56. {
  57. virtual ~AllocatorI() = 0;
  58. virtual void* alloc(size_t _size, const char* _file, uint32_t _line) = 0;
  59. virtual void free(void* _ptr, const char* _file, uint32_t _line) = 0;
  60. };
  61. inline AllocatorI::~AllocatorI()
  62. {
  63. }
  64. struct BX_NO_VTABLE ReallocatorI : public AllocatorI
  65. {
  66. virtual void* realloc(void* _ptr, size_t _size, const char* _file, uint32_t _line) = 0;
  67. };
  68. struct BX_NO_VTABLE AlignedAllocatorI
  69. {
  70. virtual void* alignedAlloc(size_t _size, size_t _align, const char* _file, uint32_t _line) = 0;
  71. virtual void alignedFree(void* _ptr, const char* _file, uint32_t _line) = 0;
  72. };
  73. struct BX_NO_VTABLE AlignedReallocatorI : public AlignedAllocatorI
  74. {
  75. virtual void* alignedRealloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) = 0;
  76. };
  77. inline void* alloc(AllocatorI* _allocator, size_t _size, const char* _file = NULL, uint32_t _line = 0)
  78. {
  79. return _allocator->alloc(_size, _file, _line);
  80. }
  81. inline void free(AllocatorI* _allocator, void* _ptr, const char* _file = NULL, uint32_t _line = 0)
  82. {
  83. _allocator->free(_ptr, _file, _line);
  84. }
  85. inline void* alloc(AlignedAllocatorI* _allocator, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0)
  86. {
  87. return _allocator->alignedAlloc(_size, _align, _file, _line);
  88. }
  89. inline void free(AlignedAllocatorI* _allocator, void* _ptr, const char* _file = NULL, uint32_t _line = 0)
  90. {
  91. _allocator->alignedFree(_ptr, _file, _line);
  92. }
  93. inline void* realloc(ReallocatorI* _allocator, void* _ptr, size_t _size, const char* _file = NULL, uint32_t _line = 0)
  94. {
  95. return _allocator->realloc(_ptr, _size, _file, _line);
  96. }
  97. inline void* realloc(AlignedReallocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0)
  98. {
  99. return _allocator->alignedRealloc(_ptr, _size, _align, _file, _line);
  100. }
  101. static inline void* alignedAlloc(AllocatorI* _allocator, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0)
  102. {
  103. size_t total = _size + _align;
  104. uint8_t* ptr = (uint8_t*)alloc(_allocator, total, _file, _line);
  105. uint8_t* aligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), _align);
  106. uint32_t* header = (uint32_t*)aligned - 1;
  107. *header = uint32_t(aligned - ptr);
  108. return aligned;
  109. }
  110. static inline void alignedFree(AllocatorI* _allocator, void* _ptr, const char* _file = NULL, uint32_t _line = 0)
  111. {
  112. uint8_t* aligned = (uint8_t*)_ptr;
  113. uint32_t* header = (uint32_t*)aligned - 1;
  114. uint8_t* ptr = aligned - *header;
  115. free(_allocator, ptr, _file, _line);
  116. }
  117. static inline void* alignedRealloc(ReallocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0)
  118. {
  119. if (NULL == _ptr)
  120. {
  121. return alignedAlloc(_allocator, _size, _align, _file, _line);
  122. }
  123. uint8_t* aligned = (uint8_t*)_ptr;
  124. uint32_t offset = *( (uint32_t*)aligned - 1);
  125. uint8_t* ptr = aligned - offset;
  126. size_t total = _size + _align;
  127. ptr = (uint8_t*)realloc(_allocator, ptr, total, _file, _line);
  128. uint8_t* newAligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), _align);
  129. if (newAligned == aligned)
  130. {
  131. return aligned;
  132. }
  133. aligned = ptr + offset;
  134. ::memmove(newAligned, aligned, _size);
  135. uint32_t* header = (uint32_t*)newAligned - 1;
  136. *header = uint32_t(newAligned - ptr);
  137. return newAligned;
  138. }
  139. inline void* alignedAlloc(AlignedAllocatorI* _allocator, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0)
  140. {
  141. return _allocator->alignedAlloc(_size, _align, _file, _line);
  142. }
  143. inline void alignedFree(AlignedAllocatorI* _allocator, void* _ptr, const char* _file = NULL, uint32_t _line = 0)
  144. {
  145. _allocator->alignedFree(_ptr, _file, _line);
  146. }
  147. inline void* alignedRealloc(AlignedReallocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const char* _file = NULL, uint32_t _line = 0)
  148. {
  149. return _allocator->alignedRealloc(_ptr, _size, _align, _file, _line);
  150. }
  151. template <typename ObjectT>
  152. inline void deleteObject(AllocatorI* _allocator, ObjectT* _object, const char* _file = NULL, uint32_t _line = 0)
  153. {
  154. if (NULL != _object)
  155. {
  156. _object->~ObjectT();
  157. free(_allocator, _object, _file, _line);
  158. }
  159. }
  160. #if BX_CONFIG_ALLOCATOR_CRT
  161. class CrtAllocator : public ReallocatorI, public AlignedReallocatorI
  162. {
  163. public:
  164. CrtAllocator()
  165. {
  166. }
  167. virtual ~CrtAllocator()
  168. {
  169. }
  170. virtual void* alloc(size_t _size, const char* _file, uint32_t _line) BX_OVERRIDE
  171. {
  172. BX_UNUSED(_file, _line);
  173. return ::malloc(_size);
  174. }
  175. virtual void free(void* _ptr, const char* _file, uint32_t _line) BX_OVERRIDE
  176. {
  177. BX_UNUSED(_file, _line);
  178. ::free(_ptr);
  179. }
  180. virtual void* realloc(void* _ptr, size_t _size, const char* _file, uint32_t _line) BX_OVERRIDE
  181. {
  182. BX_UNUSED(_file, _line);
  183. return ::realloc(_ptr, _size);
  184. }
  185. virtual void* alignedAlloc(size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
  186. {
  187. # if BX_COMPILER_MSVC
  188. BX_UNUSED(_file, _line);
  189. return _aligned_malloc(_size, _align);
  190. # else
  191. return bx::alignedAlloc(static_cast<AlignedReallocatorI*>(this), _size, _align, _file, _line);
  192. # endif // BX_
  193. }
  194. virtual void alignedFree(void* _ptr, const char* _file, uint32_t _line) BX_OVERRIDE
  195. {
  196. # if BX_COMPILER_MSVC
  197. BX_UNUSED(_file, _line);
  198. return _aligned_free(_ptr);
  199. # else
  200. return bx::alignedFree(static_cast<AlignedReallocatorI*>(this), _ptr, _file, _line);
  201. # endif // BX_
  202. }
  203. virtual void* alignedRealloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) BX_OVERRIDE
  204. {
  205. # if BX_COMPILER_MSVC
  206. BX_UNUSED(_file, _line);
  207. return _aligned_realloc(_ptr, _size, _align);
  208. # else
  209. return bx::alignedRealloc(static_cast<AlignedReallocatorI*>(this), _ptr, _size, _align, _file, _line);
  210. # endif // BX_
  211. }
  212. };
  213. #endif // BX_CONFIG_ALLOCATOR_CRT
  214. } // namespace bx
  215. #endif // BX_ALLOCATOR_H_HEADER_GUARD