allocator.h 7.7 KB

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