handlealloc.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. * Copyright 2010-2015 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef BX_HANDLE_ALLOC_H_HEADER_GUARD
  6. #define BX_HANDLE_ALLOC_H_HEADER_GUARD
  7. #include "bx.h"
  8. #include "allocator.h"
  9. namespace bx
  10. {
  11. class HandleAlloc
  12. {
  13. public:
  14. static const uint16_t invalid = UINT16_MAX;
  15. HandleAlloc(uint16_t _maxHandles)
  16. : m_numHandles(0)
  17. , m_maxHandles(_maxHandles)
  18. {
  19. reset();
  20. }
  21. ~HandleAlloc()
  22. {
  23. }
  24. const uint16_t* getHandles() const
  25. {
  26. return getDensePtr();
  27. }
  28. uint16_t getHandleAt(uint16_t _at) const
  29. {
  30. return getDensePtr()[_at];
  31. }
  32. uint16_t getNumHandles() const
  33. {
  34. return m_numHandles;
  35. }
  36. uint16_t getMaxHandles() const
  37. {
  38. return m_maxHandles;
  39. }
  40. uint16_t alloc()
  41. {
  42. if (m_numHandles < m_maxHandles)
  43. {
  44. uint16_t index = m_numHandles;
  45. ++m_numHandles;
  46. uint16_t* dense = getDensePtr();
  47. uint16_t handle = dense[index];
  48. uint16_t* sparse = getSparsePtr();
  49. sparse[handle] = index;
  50. return handle;
  51. }
  52. return invalid;
  53. }
  54. bool isValid(uint16_t _handle) const
  55. {
  56. uint16_t* dense = getDensePtr();
  57. uint16_t* sparse = getSparsePtr();
  58. uint16_t index = sparse[_handle];
  59. return index < m_numHandles
  60. && dense[index] == _handle
  61. ;
  62. }
  63. void free(uint16_t _handle)
  64. {
  65. uint16_t* dense = getDensePtr();
  66. uint16_t* sparse = getSparsePtr();
  67. uint16_t index = sparse[_handle];
  68. --m_numHandles;
  69. uint16_t temp = dense[m_numHandles];
  70. dense[m_numHandles] = _handle;
  71. sparse[temp] = index;
  72. dense[index] = temp;
  73. }
  74. void reset()
  75. {
  76. m_numHandles = 0;
  77. uint16_t* dense = getDensePtr();
  78. for (uint16_t ii = 0, num = m_maxHandles; ii < num; ++ii)
  79. {
  80. dense[ii] = ii;
  81. }
  82. }
  83. private:
  84. HandleAlloc();
  85. uint16_t* getDensePtr() const
  86. {
  87. uint8_t* ptr = (uint8_t*)reinterpret_cast<const uint8_t*>(this);
  88. return (uint16_t*)&ptr[sizeof(HandleAlloc)];
  89. }
  90. uint16_t* getSparsePtr() const
  91. {
  92. return &getDensePtr()[m_maxHandles];
  93. }
  94. uint16_t m_numHandles;
  95. uint16_t m_maxHandles;
  96. };
  97. inline HandleAlloc* createHandleAlloc(AllocatorI* _allocator, uint16_t _maxHandles)
  98. {
  99. uint8_t* ptr = (uint8_t*)BX_ALLOC(_allocator, sizeof(HandleAlloc) + 2*_maxHandles*sizeof(uint16_t) );
  100. return ::new (ptr) HandleAlloc(_maxHandles);
  101. }
  102. inline void destroyHandleAlloc(AllocatorI* _allocator, HandleAlloc* _handleAlloc)
  103. {
  104. _handleAlloc->~HandleAlloc();
  105. BX_FREE(_allocator, _handleAlloc);
  106. }
  107. template <uint16_t MaxHandlesT>
  108. class HandleAllocT : public HandleAlloc
  109. {
  110. public:
  111. HandleAllocT()
  112. : HandleAlloc(MaxHandlesT)
  113. {
  114. }
  115. ~HandleAllocT()
  116. {
  117. }
  118. private:
  119. uint16_t m_padding[2*MaxHandlesT];
  120. };
  121. template <uint16_t MaxHandlesT>
  122. class HandleListT
  123. {
  124. public:
  125. static const uint16_t invalid = UINT16_MAX;
  126. HandleListT()
  127. : m_front(invalid)
  128. , m_back(invalid)
  129. {
  130. reset();
  131. }
  132. void pushBack(uint16_t _handle)
  133. {
  134. insertAfter(m_back, _handle);
  135. }
  136. uint16_t popBack()
  137. {
  138. uint16_t last = invalid != m_back
  139. ? m_back
  140. : m_front
  141. ;
  142. if (invalid != last)
  143. {
  144. remove(last);
  145. }
  146. return last;
  147. }
  148. void pushFront(uint16_t _handle)
  149. {
  150. insertBefore(m_front, _handle);
  151. }
  152. uint16_t popFront()
  153. {
  154. uint16_t front = m_front;
  155. if (invalid != front)
  156. {
  157. remove(front);
  158. }
  159. return front;
  160. }
  161. uint16_t getFront() const
  162. {
  163. return m_front;
  164. }
  165. uint16_t getBack() const
  166. {
  167. return m_back;
  168. }
  169. uint16_t getNext(uint16_t _handle) const
  170. {
  171. BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle);
  172. const Link& curr = m_links[_handle];
  173. return curr.m_next;
  174. }
  175. uint16_t getPrev(uint16_t _handle) const
  176. {
  177. BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle);
  178. const Link& curr = m_links[_handle];
  179. return curr.m_prev;
  180. }
  181. void remove(uint16_t _handle)
  182. {
  183. BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle);
  184. Link& curr = m_links[_handle];
  185. if (invalid != curr.m_prev)
  186. {
  187. Link& prev = m_links[curr.m_prev];
  188. prev.m_next = curr.m_next;
  189. }
  190. else
  191. {
  192. m_front = curr.m_next;
  193. }
  194. if (invalid != curr.m_next)
  195. {
  196. Link& next = m_links[curr.m_next];
  197. next.m_prev = curr.m_prev;
  198. }
  199. else
  200. {
  201. m_back = curr.m_prev;
  202. }
  203. curr.m_prev = invalid;
  204. curr.m_next = invalid;
  205. }
  206. void reset()
  207. {
  208. memset(m_links, 0xff, sizeof(m_links) );
  209. }
  210. private:
  211. void insertBefore(int16_t _before, uint16_t _handle)
  212. {
  213. Link& curr = m_links[_handle];
  214. curr.m_next = _before;
  215. if (invalid != _before)
  216. {
  217. Link& link = m_links[_before];
  218. if (invalid != link.m_prev)
  219. {
  220. Link& prev = m_links[link.m_prev];
  221. prev.m_next = _handle;
  222. }
  223. curr.m_prev = link.m_prev;
  224. link.m_prev = _handle;
  225. }
  226. updateFrontBack(_handle);
  227. }
  228. void insertAfter(uint16_t _after, uint16_t _handle)
  229. {
  230. Link& curr = m_links[_handle];
  231. curr.m_prev = _after;
  232. if (invalid != _after)
  233. {
  234. Link& link = m_links[_after];
  235. if (invalid != link.m_next)
  236. {
  237. Link& next = m_links[link.m_next];
  238. next.m_prev = _handle;
  239. }
  240. curr.m_next = link.m_next;
  241. link.m_next = _handle;
  242. }
  243. updateFrontBack(_handle);
  244. }
  245. bool isValid(uint16_t _handle) const
  246. {
  247. return _handle < MaxHandlesT;
  248. }
  249. void updateFrontBack(uint16_t _handle)
  250. {
  251. Link& curr = m_links[_handle];
  252. if (invalid == curr.m_prev)
  253. {
  254. m_front = _handle;
  255. }
  256. if (invalid == curr.m_next)
  257. {
  258. m_back = _handle;
  259. }
  260. }
  261. uint16_t m_front;
  262. uint16_t m_back;
  263. struct Link
  264. {
  265. uint16_t m_prev;
  266. uint16_t m_next;
  267. };
  268. Link m_links[MaxHandlesT];
  269. };
  270. template <uint16_t MaxHandlesT>
  271. class HandleAllocLruT
  272. {
  273. public:
  274. static const uint16_t invalid = UINT16_MAX;
  275. HandleAllocLruT()
  276. {
  277. reset();
  278. }
  279. ~HandleAllocLruT()
  280. {
  281. }
  282. const uint16_t* getHandles() const
  283. {
  284. return m_alloc.getHandles();
  285. }
  286. uint16_t getHandleAt(uint16_t _at) const
  287. {
  288. return m_alloc.getHandleAt(_at);
  289. }
  290. uint16_t getNumHandles() const
  291. {
  292. return m_alloc.getNumHandles();
  293. }
  294. uint16_t getMaxHandles() const
  295. {
  296. return m_alloc.getMaxHandles();
  297. }
  298. uint16_t alloc()
  299. {
  300. uint16_t handle = m_alloc.alloc();
  301. if (invalid != handle)
  302. {
  303. m_list.pushFront(handle);
  304. }
  305. return handle;
  306. }
  307. bool isValid(uint16_t _handle) const
  308. {
  309. return m_alloc.isValid(_handle);
  310. }
  311. void free(uint16_t _handle)
  312. {
  313. BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle);
  314. m_list.remove(_handle);
  315. m_alloc.free(_handle);
  316. }
  317. void touch(uint16_t _handle)
  318. {
  319. BX_CHECK(isValid(_handle), "Invalid handle %d!", _handle);
  320. m_list.remove(_handle);
  321. m_list.pushFront(_handle);
  322. }
  323. uint16_t getFront() const
  324. {
  325. return m_list.getFront();
  326. }
  327. uint16_t getBack() const
  328. {
  329. return m_list.getBack();
  330. }
  331. uint16_t getNext(uint16_t _handle) const
  332. {
  333. return m_list.getNext(_handle);
  334. }
  335. uint16_t getPrev(uint16_t _handle) const
  336. {
  337. return m_list.getPrev(_handle);
  338. }
  339. void reset()
  340. {
  341. m_list.reset();
  342. m_alloc.reset();
  343. }
  344. private:
  345. HandleListT<MaxHandlesT> m_list;
  346. HandleAllocT<MaxHandlesT> m_alloc;
  347. };
  348. } // namespace bx
  349. #endif // BX_HANDLE_ALLOC_H_HEADER_GUARD