allocator.h 7.2 KB

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