handle_pool_vs.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. ////////////////////////////////////////////////////////////////////////////////////////
  2. // RAVEN STANDARD TEMPLATE LIBRARY
  3. // (c) 2002 Activision
  4. //
  5. //
  6. // Handle Pool
  7. // -----------
  8. // The memory pool class is a simple routine for constant time allocation and deallocation
  9. // from a fixed size pool of objects. The class uses a simple array to hold the actual
  10. // data, a queue for the free list, and a bit field to mark which spots in the array
  11. // are allocated.
  12. //
  13. // In addition to the standard memory pool features, this Handle Pool provides a fast
  14. // iterator, asserts on attempting to access unused data, and a unique ID "handle" for
  15. // the external system to use.
  16. //
  17. //
  18. //
  19. // NOTES:
  20. //
  21. //
  22. //
  23. ////////////////////////////////////////////////////////////////////////////////////////
  24. #if !defined(RATL_HANDLE_POOL_VS_INC)
  25. #define RATL_HANDLE_POOL_VS_INC
  26. ////////////////////////////////////////////////////////////////////////////////////////
  27. // Includes
  28. ////////////////////////////////////////////////////////////////////////////////////////
  29. #if !defined(RATL_COMMON_INC)
  30. #include "ratl_common.h"
  31. #endif
  32. #if !defined(RATL_POOL_VS_INC)
  33. #include "pool_vs.h"
  34. #endif
  35. namespace ratl
  36. {
  37. template <class T>
  38. class handle_pool_base : public pool_root<T>
  39. {
  40. public:
  41. typedef typename T TStorageTraits;
  42. typedef typename T::TValue TTValue;
  43. ////////////////////////////////////////////////////////////////////////////////////
  44. // Capacity Enum
  45. ////////////////////////////////////////////////////////////////////////////////////
  46. enum
  47. {
  48. CAPACITY = T::CAPACITY
  49. };
  50. private:
  51. int mHandles[CAPACITY];
  52. int mMASK_HANDLE_TO_INDEX;
  53. int mMASK_NUM_BITS;
  54. void IncHandle(int index)
  55. {
  56. mHandles[index] += (1<<mMASK_NUM_BITS);
  57. if (mHandles[index]<0)
  58. {
  59. // we rolled over
  60. mHandles[index] = index; // Reset The ID Counter
  61. mHandles[index] |= (1<<mMASK_NUM_BITS);
  62. }
  63. }
  64. public:
  65. ////////////////////////////////////////////////////////////////////////////////////
  66. // Constructor
  67. //
  68. // We need a routine to calculate the MASK used to convert a handle to an index and
  69. // the number of bits needed to shift by.
  70. //
  71. ////////////////////////////////////////////////////////////////////////////////////
  72. handle_pool_base()
  73. {
  74. mMASK_HANDLE_TO_INDEX = 0;
  75. mMASK_NUM_BITS = 0;
  76. int value=CAPACITY-1;
  77. while(value)
  78. {
  79. value>>= 1;
  80. mMASK_HANDLE_TO_INDEX <<= 1;
  81. mMASK_HANDLE_TO_INDEX |= 1;
  82. mMASK_NUM_BITS++;
  83. }
  84. for (int i=0; i<CAPACITY; i++)
  85. {
  86. #ifdef _DEBUG
  87. mHandles[i] = i; // Reset The ID Counter
  88. mHandles[i] |= ((++HandleSaltValue)<<mMASK_NUM_BITS);
  89. #else
  90. mHandles[i] = i; // Reset The ID Counter
  91. mHandles[i] |= (1<<mMASK_NUM_BITS);
  92. #endif
  93. }
  94. }
  95. ////////////////////////////////////////////////////////////////////////////////////
  96. // Clear - Removes all allocation information
  97. ////////////////////////////////////////////////////////////////////////////////////
  98. void clear()
  99. {
  100. pool_root<T>::clear();
  101. // note that we do not refill the handles cause we want old handles to still be stale
  102. for (int i=0; i<CAPACITY; i++)
  103. {
  104. IncHandle(i);
  105. }
  106. }
  107. ////////////////////////////////////////////////////////////////////////////////////
  108. // Constant Accessor
  109. ////////////////////////////////////////////////////////////////////////////////////
  110. const TTValue& operator[](int handle) const
  111. {
  112. assert(is_used(handle)); //typically this is a stale handle (already been freed)
  113. return value_at_index(handle&mMASK_HANDLE_TO_INDEX);
  114. }
  115. ////////////////////////////////////////////////////////////////////////////////////
  116. // Accessor
  117. ////////////////////////////////////////////////////////////////////////////////////
  118. TTValue& operator[](int i)
  119. {
  120. assert(is_used(i)); //typically this is a stale handle (already been freed)
  121. return value_at_index(i&mMASK_HANDLE_TO_INDEX);
  122. }
  123. bool is_used(int i) const
  124. {
  125. if (mHandles[i&mMASK_HANDLE_TO_INDEX]==i)
  126. {
  127. return is_used_index(i&mMASK_HANDLE_TO_INDEX);
  128. }
  129. return false;
  130. }
  131. ////////////////////////////////////////////////////////////////////////////////////
  132. // Swap two items based on handle
  133. ////////////////////////////////////////////////////////////////////////////////////
  134. void swap(int i,int j)
  135. {
  136. assert(is_used(i)); //typically this is a stale handle (already been freed)
  137. assert(is_used(j)); //typically this is a stale handle (already been freed)
  138. swap_index(handle_to_index(i),handle_to_index(j));
  139. }
  140. ////////////////////////////////////////////////////////////////////////////////////
  141. // The Allocator returns a handle
  142. ////////////////////////////////////////////////////////////////////////////////////
  143. int alloc()
  144. {
  145. int index=alloc_index();
  146. return mHandles[index];
  147. }
  148. ////////////////////////////////////////////////////////////////////////////////////
  149. // The Allocator, with value, returns a handle
  150. ////////////////////////////////////////////////////////////////////////////////////
  151. int alloc(const TTValue &v)
  152. {
  153. int index=alloc_index(v);
  154. return mHandles[index];
  155. }
  156. ////////////////////////////////////////////////////////////////////////////////////
  157. // The Deallocator, by index, not something generally needed
  158. ////////////////////////////////////////////////////////////////////////////////////
  159. void free_index(int index)
  160. {
  161. pool_root<T>::free_index(index);
  162. IncHandle(index);
  163. }
  164. ////////////////////////////////////////////////////////////////////////////////////
  165. // The Deallocator, by handle
  166. ////////////////////////////////////////////////////////////////////////////////////
  167. void free(int handle)
  168. {
  169. assert(is_used(handle));
  170. free_index(handle&mMASK_HANDLE_TO_INDEX);
  171. }
  172. ////////////////////////////////////////////////////////////////////////////////////
  173. // The Deallocator, by pointer
  174. ////////////////////////////////////////////////////////////////////////////////////
  175. void free(TTValue *me)
  176. {
  177. free_index(pointer_to_index(me));
  178. }
  179. ////////////////////////////////////////////////////////////////////////////////////
  180. // Convert a handle to a raw index, not generally something you should use
  181. ////////////////////////////////////////////////////////////////////////////////////
  182. int handle_to_index(int handle) const
  183. {
  184. assert(is_used(handle));
  185. return (handle&mMASK_HANDLE_TO_INDEX);
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////////
  188. // FInd the handle for a given index, this cannot check for stale handles, so it is ill advised
  189. ////////////////////////////////////////////////////////////////////////////////////
  190. int index_to_handle(int index) const
  191. {
  192. assert(index>=0 && index<CAPACITY && is_used_index(index)); //disallowing this on stale handles
  193. return (mHandles[index]);
  194. }
  195. ////////////////////////////////////////////////////////////////////////////////////
  196. // converts a T pointer to a handle, generally not something you need, cannot check for stale handles
  197. ////////////////////////////////////////////////////////////////////////////////////
  198. int pointer_to_handle(const TTValue *me) const
  199. {
  200. return index_to_handle(pointer_to_index(me));
  201. }
  202. ////////////////////////////////////////////////////////////////////////////////////
  203. // converts a T pointer to a handle, generally not something you need, cannot check for stale handles
  204. ////////////////////////////////////////////////////////////////////////////////////
  205. int pointer_to_handle(const TRatlNew *me) const
  206. {
  207. return index_to_handle(pointer_to_index(me));
  208. }
  209. ////////////////////////////////////////////////////////////////////////////////////
  210. // Get An Iterator To The Object At handle
  211. ////////////////////////////////////////////////////////////////////////////////////
  212. pool_root<T>::iterator at(int handle)
  213. {
  214. assert(is_used(handle));
  215. return at_index(handle&mMASK_HANDLE_TO_INDEX);
  216. }
  217. ////////////////////////////////////////////////////////////////////////////////////
  218. // Get An Iterator To The Object At handle
  219. ////////////////////////////////////////////////////////////////////////////////////
  220. pool_root<T>::const_iterator at(int handle) const
  221. {
  222. assert(is_used(handle));
  223. return at_index(handle&mMASK_HANDLE_TO_INDEX);
  224. }
  225. };
  226. template<class T, int ARG_CAPACITY>
  227. class handle_pool_vs : public handle_pool_base<storage::value_semantics<T,ARG_CAPACITY> >
  228. {
  229. public:
  230. typedef typename storage::value_semantics<T,ARG_CAPACITY> TStorageTraits;
  231. typedef typename TStorageTraits::TValue TTValue;
  232. enum
  233. {
  234. CAPACITY = ARG_CAPACITY
  235. };
  236. handle_pool_vs() {}
  237. };
  238. template<class T, int ARG_CAPACITY>
  239. class handle_pool_os : public handle_pool_base<storage::object_semantics<T,ARG_CAPACITY> >
  240. {
  241. public:
  242. typedef typename storage::object_semantics<T,ARG_CAPACITY> TStorageTraits;
  243. typedef typename TStorageTraits::TValue TTValue;
  244. enum
  245. {
  246. CAPACITY = ARG_CAPACITY
  247. };
  248. handle_pool_os() {}
  249. };
  250. template<class T, int ARG_CAPACITY, int ARG_MAX_CLASS_SIZE>
  251. class handle_pool_is : public handle_pool_base<storage::virtual_semantics<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> >
  252. {
  253. public:
  254. typedef typename storage::virtual_semantics<T,ARG_CAPACITY,ARG_MAX_CLASS_SIZE> TStorageTraits;
  255. typedef typename TStorageTraits::TValue TTValue;
  256. enum
  257. {
  258. CAPACITY = ARG_CAPACITY,
  259. MAX_CLASS_SIZE = ARG_MAX_CLASS_SIZE
  260. };
  261. handle_pool_is() {}
  262. };
  263. }
  264. #endif