nlalloc_test.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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 stl = tinystl;
  26. namespace bx
  27. {
  28. struct Blk
  29. {
  30. static const uint64_t kInvalid = UINT64_MAX;
  31. Blk()
  32. : ptr(kInvalid)
  33. , size(0)
  34. {
  35. }
  36. Blk(uint64_t _ptr, uint32_t _size)
  37. : ptr(_ptr)
  38. , size(_size)
  39. {
  40. }
  41. uint64_t ptr;
  42. uint32_t size;
  43. };
  44. inline bool operator<(const Blk& _lhs, const Blk& _rhs)
  45. {
  46. return _lhs.ptr < _rhs.ptr;
  47. }
  48. inline bool isValid(const Blk& _blk)
  49. {
  50. return Blk::kInvalid != _blk.ptr;
  51. }
  52. // First-fit non-local allocator.
  53. class NonLocalAllocator
  54. {
  55. public:
  56. NonLocalAllocator()
  57. {
  58. reset();
  59. }
  60. ~NonLocalAllocator()
  61. {
  62. }
  63. void reset()
  64. {
  65. m_free.clear();
  66. m_used = 0;
  67. }
  68. void add(const Blk& _blk)
  69. {
  70. m_free.push_back(_blk);
  71. }
  72. Blk remove()
  73. {
  74. BX_CHECK(0 == m_used, "");
  75. if (0 < m_free.size() )
  76. {
  77. Blk freeBlock = m_free.back();
  78. m_free.pop_back();
  79. return freeBlock;
  80. }
  81. return Blk{};
  82. }
  83. Blk alloc(uint32_t _size)
  84. {
  85. _size = max(_size, 16u);
  86. for (FreeList::iterator it = m_free.begin(), itEnd = m_free.end(); it != itEnd; ++it)
  87. {
  88. if (it->size >= _size)
  89. {
  90. uint64_t ptr = it->ptr;
  91. if (it->size != _size)
  92. {
  93. it->size -= _size;
  94. it->ptr += _size;
  95. }
  96. else
  97. {
  98. m_free.erase(it);
  99. }
  100. m_used += _size;
  101. return Blk{ ptr, _size };
  102. }
  103. }
  104. // there is no block large enough.
  105. return Blk{};
  106. }
  107. void free(const Blk& _blk)
  108. {
  109. m_used -= _blk.size;
  110. m_free.push_back(_blk);
  111. compact();
  112. }
  113. bool compact()
  114. {
  115. bx::quickSort(
  116. m_free.begin()
  117. , uint32_t(m_free.end() - m_free.begin() )
  118. , sizeof(Blk)
  119. , [](const void* _a, const void* _b) -> int32_t {
  120. const Blk& lhs = *(const Blk*)(_a);
  121. const Blk& rhs = *(const Blk*)(_b);
  122. return lhs < rhs ? -1 : 1;
  123. });
  124. for (FreeList::iterator it = m_free.begin(), next = it, itEnd = m_free.end(); next != itEnd;)
  125. {
  126. if ( (it->ptr + it->size) == next->ptr)
  127. {
  128. it->size += next->size;
  129. next = m_free.erase(next);
  130. }
  131. else
  132. {
  133. it = next;
  134. ++next;
  135. }
  136. }
  137. return 0 == m_used;
  138. }
  139. uint32_t getUsed() const
  140. {
  141. return m_used;
  142. }
  143. private:
  144. typedef stl::vector<Blk> FreeList;
  145. FreeList m_free;
  146. uint32_t m_used;
  147. };
  148. } // namespace bx
  149. TEST_CASE("nlalloc")
  150. {
  151. bx::NonLocalAllocator nla;
  152. bx::Blk blk;
  153. blk = nla.alloc(100);
  154. REQUIRE(!isValid(blk) );
  155. nla.add(bx::Blk{0x1000, 100});
  156. blk = nla.alloc(100);
  157. REQUIRE(isValid(blk) );
  158. nla.free(blk);
  159. REQUIRE(0 == nla.getUsed() );
  160. }