Pool.inl 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * This source file is part of libRocket, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://www.librocket.com
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. template < typename PoolType >
  28. Pool< PoolType >::Pool(int _chunk_size, bool _grow)
  29. {
  30. chunk_size = 0;
  31. grow = _grow;
  32. num_allocated_objects = 0;
  33. pool = NULL;
  34. first_allocated_node = NULL;
  35. first_free_node = NULL;
  36. if (_chunk_size > 0)
  37. Initialise(_chunk_size, _grow);
  38. }
  39. template < typename PoolType >
  40. Pool< PoolType >::~Pool()
  41. {
  42. PoolChunk* chunk = pool;
  43. while (chunk)
  44. {
  45. PoolChunk* next_chunk = chunk->next;
  46. delete[] chunk->chunk;
  47. delete chunk;
  48. chunk = next_chunk;
  49. }
  50. }
  51. // Initialises the pool to a given size.
  52. template < typename PoolType >
  53. void Pool< PoolType >::Initialise(int _chunk_size, bool _grow)
  54. {
  55. // Should resize the pool here ... ?
  56. if (chunk_size > 0)
  57. return;
  58. if (_chunk_size <= 0)
  59. return;
  60. grow = _grow;
  61. chunk_size = _chunk_size;
  62. pool = NULL;
  63. // Create the initial chunk.
  64. CreateChunk();
  65. }
  66. // Returns the head of the linked list of allocated objects.
  67. template < typename PoolType >
  68. typename Pool< PoolType >::Iterator Pool< PoolType >::Begin()
  69. {
  70. return typename Pool< PoolType >::Iterator(first_allocated_node);
  71. }
  72. // Attempts to allocate a deallocated object in the memory pool.
  73. template < typename PoolType >
  74. PoolType* Pool< PoolType >::AllocateObject()
  75. {
  76. // We can't allocate a new object if the deallocated list is empty.
  77. if (first_free_node == NULL)
  78. {
  79. // Attempt to grow the pool first.
  80. if (grow)
  81. {
  82. CreateChunk();
  83. if (first_free_node == NULL)
  84. return NULL;
  85. }
  86. else
  87. return NULL;
  88. }
  89. // We're about to allocate an object.
  90. ++num_allocated_objects;
  91. // This one!
  92. PoolNode* allocated_object = first_free_node;
  93. // Remove the newly allocated object from the list of deallocated objects.
  94. first_free_node = first_free_node->next;
  95. if (first_free_node != NULL)
  96. first_free_node->previous = NULL;
  97. // Add the newly allocated object to the head of the list of allocated objects.
  98. if (first_allocated_node != NULL)
  99. {
  100. allocated_object->previous = NULL;
  101. allocated_object->next = first_allocated_node;
  102. first_allocated_node->previous = allocated_object;
  103. }
  104. else
  105. {
  106. // This object is the only allocated object.
  107. allocated_object->previous = NULL;
  108. allocated_object->next = NULL;
  109. }
  110. first_allocated_node = allocated_object;
  111. return new (&allocated_object->object) PoolType();
  112. }
  113. // Deallocates the object pointed to by the given iterator.
  114. template < typename PoolType >
  115. void Pool< PoolType >::DeallocateObject(Iterator& iterator)
  116. {
  117. // We're about to deallocate an object.
  118. --num_allocated_objects;
  119. PoolNode* object = iterator.node;
  120. object->object.~PoolType();
  121. // Get the previous and next pointers now, because they will be overwritten
  122. // before we're finished.
  123. PoolNode* previous_object = object->previous;
  124. PoolNode* next_object = object->next;
  125. if (previous_object != NULL)
  126. previous_object->next = next_object;
  127. else
  128. {
  129. ROCKET_ASSERT(first_allocated_node == object);
  130. first_allocated_node = next_object;
  131. }
  132. if (next_object != NULL)
  133. next_object->previous = previous_object;
  134. // Insert the freed node at the beginning of the free object list.
  135. if (first_free_node == NULL)
  136. {
  137. object->previous = NULL;
  138. object->next = NULL;
  139. }
  140. else
  141. {
  142. object->previous = NULL;
  143. object->next = first_free_node;
  144. }
  145. first_free_node = object;
  146. // Increment the iterator, so it points to the next active object.
  147. iterator.node = next_object;
  148. }
  149. // Deallocates the given object.
  150. template < typename PoolType >
  151. void Pool< PoolType >::DeallocateObject(PoolType* object)
  152. {
  153. // This assumes the object has the same address as the node, which will be
  154. // true as long as the struct definition does not change.
  155. Iterator iterator((PoolNode*) object);
  156. DeallocateObject(iterator);
  157. }
  158. // Returns the number of objects in the pool.
  159. template < typename PoolType >
  160. int Pool< PoolType >::GetSize() const
  161. {
  162. return chunk_size * GetNumChunks();
  163. }
  164. /// Returns the number of object chunks in the pool.
  165. template < typename PoolType >
  166. int Pool< PoolType >::GetNumChunks() const
  167. {
  168. int num_chunks = 0;
  169. PoolChunk* chunk = pool;
  170. while (chunk != NULL)
  171. {
  172. ++num_chunks;
  173. chunk = chunk->next;
  174. }
  175. return num_chunks;
  176. }
  177. // Returns the number of allocated objects in the pool.
  178. template < typename PoolType >
  179. int Pool< PoolType >::GetNumAllocatedObjects() const
  180. {
  181. return num_allocated_objects;
  182. }
  183. // Creates a new pool chunk and appends its nodes to the beginning of the free list.
  184. template < typename PoolType >
  185. void Pool< PoolType >::CreateChunk()
  186. {
  187. if (chunk_size <= 0)
  188. return;
  189. // Create the new chunk and mark it as the first chunk.
  190. PoolChunk* new_chunk = new PoolChunk();
  191. new_chunk->next = pool;
  192. pool = new_chunk;
  193. // Create chunk's pool nodes.
  194. new_chunk->chunk = new PoolNode[chunk_size];
  195. // Initialise the linked list.
  196. for (int i = 0; i < chunk_size; i++)
  197. {
  198. if (i == 0)
  199. new_chunk->chunk[i].previous = NULL ;
  200. else
  201. new_chunk->chunk[i].previous = &new_chunk->chunk[i - 1];
  202. if (i == chunk_size - 1)
  203. new_chunk->chunk[i].next = first_free_node;
  204. else
  205. new_chunk->chunk[i].next = &new_chunk->chunk[i + 1];
  206. }
  207. first_free_node = new_chunk->chunk;
  208. }