nlalloc_test.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright 2010-2018 Branimir Karadzic. All rights reserved.
  3. * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
  4. */
  5. #include "test.h"
  6. #include <bx/sort.h>
  7. #include <bx/allocator.h>
  8. bx::DefaultAllocator g_allocator0;
  9. struct TinyStlAllocator
  10. {
  11. static void* static_allocate(size_t _bytes)
  12. {
  13. return BX_ALLOC(&g_allocator0, _bytes);
  14. }
  15. static void static_deallocate(void* _ptr, size_t /*_bytes*/)
  16. {
  17. if (NULL != _ptr)
  18. {
  19. BX_FREE(&g_allocator0, _ptr);
  20. }
  21. }
  22. };
  23. #define TINYSTL_ALLOCATOR ::TinyStlAllocator
  24. #include <tinystl/vector.h>
  25. namespace tinystl
  26. {
  27. template<typename T, typename Alloc = TINYSTL_ALLOCATOR>
  28. class list : public vector<T, Alloc>
  29. {
  30. public:
  31. void push_front(const T& _value)
  32. {
  33. this->insert(this->begin(), _value);
  34. }
  35. void pop_front()
  36. {
  37. this->erase(this->begin() );
  38. }
  39. void sort()
  40. {
  41. bx::quickSort(
  42. this->begin()
  43. , uint32_t(this->end() - this->begin() )
  44. , sizeof(T)
  45. , [](const void* _a, const void* _b) -> int32_t {
  46. const T& lhs = *(const T*)(_a);
  47. const T& rhs = *(const T*)(_b);
  48. return lhs < rhs ? -1 : 1;
  49. });
  50. }
  51. };
  52. } // namespace tinystl
  53. namespace stl = tinystl;
  54. namespace bx
  55. {
  56. struct Blk
  57. {
  58. static const uint64_t kInvalid = UINT64_MAX;
  59. Blk()
  60. : ptr(kInvalid)
  61. , size(0)
  62. {
  63. }
  64. Blk(uint64_t _ptr, uint32_t _size)
  65. : ptr(_ptr)
  66. , size(_size)
  67. {
  68. }
  69. uint64_t ptr;
  70. uint32_t size;
  71. };
  72. inline bool operator<(const Blk& _lhs, const Blk& _rhs)
  73. {
  74. return _lhs.ptr < _rhs.ptr;
  75. }
  76. inline bool isValid(const Blk& _blk)
  77. {
  78. return Blk::kInvalid != _blk.ptr;
  79. }
  80. // First-fit non-local allocator.
  81. class NonLocalAllocator
  82. {
  83. public:
  84. NonLocalAllocator()
  85. {
  86. }
  87. ~NonLocalAllocator()
  88. {
  89. }
  90. void reset()
  91. {
  92. m_free.clear();
  93. m_used = 0;
  94. }
  95. void add(const Blk& _blk)
  96. {
  97. m_free.push_back(_blk);
  98. }
  99. Blk remove()
  100. {
  101. BX_CHECK(0 == m_used, "");
  102. if (0 < m_free.size() )
  103. {
  104. Blk freeBlock = m_free.front();
  105. m_free.pop_front();
  106. return freeBlock;
  107. }
  108. return Blk{};
  109. }
  110. Blk alloc(uint32_t _size)
  111. {
  112. _size = max(_size, 16u);
  113. for (FreeList::iterator it = m_free.begin(), itEnd = m_free.end(); it != itEnd; ++it)
  114. {
  115. if (it->size >= _size)
  116. {
  117. uint64_t ptr = it->ptr;
  118. if (it->size != _size)
  119. {
  120. it->size -= _size;
  121. it->ptr += _size;
  122. }
  123. else
  124. {
  125. m_free.erase(it);
  126. }
  127. m_used += _size;
  128. return Blk{ ptr, _size };
  129. }
  130. }
  131. // there is no block large enough.
  132. return Blk{};
  133. }
  134. void free(const Blk& _blk)
  135. {
  136. m_used -= _blk.size;
  137. m_free.push_front(_blk);
  138. }
  139. bool compact()
  140. {
  141. m_free.sort();
  142. for (FreeList::iterator it = m_free.begin(), next = it, itEnd = m_free.end(); next != itEnd;)
  143. {
  144. if ( (it->ptr + it->size) == next->ptr)
  145. {
  146. it->size += next->size;
  147. next = m_free.erase(next);
  148. }
  149. else
  150. {
  151. it = next;
  152. ++next;
  153. }
  154. }
  155. return 0 == m_used;
  156. }
  157. uint32_t getUsed() const
  158. {
  159. return m_used;
  160. }
  161. private:
  162. typedef stl::list<Blk> FreeList;
  163. FreeList m_free;
  164. uint32_t m_used;
  165. };
  166. } // namespace bx
  167. TEST_CASE("nlalloc")
  168. {
  169. bx::NonLocalAllocator nla;
  170. bx::Blk blk;
  171. blk = nla.alloc(100);
  172. REQUIRE(!isValid(blk) );
  173. nla.add(bx::Blk{0x1000, 100});
  174. blk = nla.alloc(100);
  175. REQUIRE(isValid(blk) );
  176. nla.free(blk);
  177. REQUIRE(0 == nla.getUsed() );
  178. }