|
|
@@ -1,247 +0,0 @@
|
|
|
-/*
|
|
|
- * This source file is part of libRocket, the HTML/CSS Interface Middleware
|
|
|
- *
|
|
|
- * For the latest information, see http://www.librocket.com
|
|
|
- *
|
|
|
- * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
|
|
|
- *
|
|
|
- * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
- * of this software and associated documentation files (the "Software"), to deal
|
|
|
- * in the Software without restriction, including without limitation the rights
|
|
|
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
- * copies of the Software, and to permit persons to whom the Software is
|
|
|
- * furnished to do so, subject to the following conditions:
|
|
|
- *
|
|
|
- * The above copyright notice and this permission notice shall be included in
|
|
|
- * all copies or substantial portions of the Software.
|
|
|
- *
|
|
|
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
- * THE SOFTWARE.
|
|
|
- *
|
|
|
- */
|
|
|
-
|
|
|
-template < typename PoolType >
|
|
|
-Pool< PoolType >::Pool(int _chunk_size, bool _grow)
|
|
|
-{
|
|
|
- chunk_size = 0;
|
|
|
- grow = _grow;
|
|
|
-
|
|
|
- num_allocated_objects = 0;
|
|
|
-
|
|
|
- pool = NULL;
|
|
|
- first_allocated_node = NULL;
|
|
|
- first_free_node = NULL;
|
|
|
-
|
|
|
- if (_chunk_size > 0)
|
|
|
- Initialise(_chunk_size, _grow);
|
|
|
-}
|
|
|
-
|
|
|
-template < typename PoolType >
|
|
|
-Pool< PoolType >::~Pool()
|
|
|
-{
|
|
|
- PoolChunk* chunk = pool;
|
|
|
- while (chunk)
|
|
|
- {
|
|
|
- PoolChunk* next_chunk = chunk->next;
|
|
|
-
|
|
|
- delete[] chunk->chunk;
|
|
|
- delete chunk;
|
|
|
-
|
|
|
- chunk = next_chunk;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Initialises the pool to a given size.
|
|
|
-template < typename PoolType >
|
|
|
-void Pool< PoolType >::Initialise(int _chunk_size, bool _grow)
|
|
|
-{
|
|
|
- // Should resize the pool here ... ?
|
|
|
- if (chunk_size > 0)
|
|
|
- return;
|
|
|
-
|
|
|
- if (_chunk_size <= 0)
|
|
|
- return;
|
|
|
-
|
|
|
- grow = _grow;
|
|
|
- chunk_size = _chunk_size;
|
|
|
- pool = NULL;
|
|
|
-
|
|
|
- // Create the initial chunk.
|
|
|
- CreateChunk();
|
|
|
-}
|
|
|
-
|
|
|
-// Returns the head of the linked list of allocated objects.
|
|
|
-template < typename PoolType >
|
|
|
-typename Pool< PoolType >::Iterator Pool< PoolType >::Begin()
|
|
|
-{
|
|
|
- return typename Pool< PoolType >::Iterator(first_allocated_node);
|
|
|
-}
|
|
|
-
|
|
|
-// Attempts to allocate a deallocated object in the memory pool.
|
|
|
-template < typename PoolType >
|
|
|
-PoolType* Pool< PoolType >::AllocateObject()
|
|
|
-{
|
|
|
- // We can't allocate a new object if the deallocated list is empty.
|
|
|
- if (first_free_node == NULL)
|
|
|
- {
|
|
|
- // Attempt to grow the pool first.
|
|
|
- if (grow)
|
|
|
- {
|
|
|
- CreateChunk();
|
|
|
- if (first_free_node == NULL)
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- else
|
|
|
- return NULL;
|
|
|
- }
|
|
|
-
|
|
|
- // We're about to allocate an object.
|
|
|
- ++num_allocated_objects;
|
|
|
-
|
|
|
- // This one!
|
|
|
- PoolNode* allocated_object = first_free_node;
|
|
|
-
|
|
|
- // Remove the newly allocated object from the list of deallocated objects.
|
|
|
- first_free_node = first_free_node->next;
|
|
|
- if (first_free_node != NULL)
|
|
|
- first_free_node->previous = NULL;
|
|
|
-
|
|
|
- // Add the newly allocated object to the head of the list of allocated objects.
|
|
|
- if (first_allocated_node != NULL)
|
|
|
- {
|
|
|
- allocated_object->previous = NULL;
|
|
|
- allocated_object->next = first_allocated_node;
|
|
|
- first_allocated_node->previous = allocated_object;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // This object is the only allocated object.
|
|
|
- allocated_object->previous = NULL;
|
|
|
- allocated_object->next = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- first_allocated_node = allocated_object;
|
|
|
-
|
|
|
- return new (&allocated_object->object) PoolType();
|
|
|
-}
|
|
|
-
|
|
|
-// Deallocates the object pointed to by the given iterator.
|
|
|
-template < typename PoolType >
|
|
|
-void Pool< PoolType >::DeallocateObject(Iterator& iterator)
|
|
|
-{
|
|
|
- // We're about to deallocate an object.
|
|
|
- --num_allocated_objects;
|
|
|
-
|
|
|
- PoolNode* object = iterator.node;
|
|
|
- object->object.~PoolType();
|
|
|
-
|
|
|
- // Get the previous and next pointers now, because they will be overwritten
|
|
|
- // before we're finished.
|
|
|
- PoolNode* previous_object = object->previous;
|
|
|
- PoolNode* next_object = object->next;
|
|
|
-
|
|
|
- if (previous_object != NULL)
|
|
|
- previous_object->next = next_object;
|
|
|
- else
|
|
|
- {
|
|
|
- ROCKET_ASSERT(first_allocated_node == object);
|
|
|
- first_allocated_node = next_object;
|
|
|
- }
|
|
|
-
|
|
|
- if (next_object != NULL)
|
|
|
- next_object->previous = previous_object;
|
|
|
-
|
|
|
- // Insert the freed node at the beginning of the free object list.
|
|
|
- if (first_free_node == NULL)
|
|
|
- {
|
|
|
- object->previous = NULL;
|
|
|
- object->next = NULL;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- object->previous = NULL;
|
|
|
- object->next = first_free_node;
|
|
|
- }
|
|
|
-
|
|
|
- first_free_node = object;
|
|
|
-
|
|
|
- // Increment the iterator, so it points to the next active object.
|
|
|
- iterator.node = next_object;
|
|
|
-}
|
|
|
-
|
|
|
-// Deallocates the given object.
|
|
|
-template < typename PoolType >
|
|
|
-void Pool< PoolType >::DeallocateObject(PoolType* object)
|
|
|
-{
|
|
|
- // This assumes the object has the same address as the node, which will be
|
|
|
- // true as long as the struct definition does not change.
|
|
|
- Iterator iterator((PoolNode*) object);
|
|
|
- DeallocateObject(iterator);
|
|
|
-}
|
|
|
-
|
|
|
-// Returns the number of objects in the pool.
|
|
|
-template < typename PoolType >
|
|
|
-int Pool< PoolType >::GetSize() const
|
|
|
-{
|
|
|
- return chunk_size * GetNumChunks();
|
|
|
-}
|
|
|
-
|
|
|
-/// Returns the number of object chunks in the pool.
|
|
|
-template < typename PoolType >
|
|
|
-int Pool< PoolType >::GetNumChunks() const
|
|
|
-{
|
|
|
- int num_chunks = 0;
|
|
|
-
|
|
|
- PoolChunk* chunk = pool;
|
|
|
- while (chunk != NULL)
|
|
|
- {
|
|
|
- ++num_chunks;
|
|
|
- chunk = chunk->next;
|
|
|
- }
|
|
|
-
|
|
|
- return num_chunks;
|
|
|
-}
|
|
|
-
|
|
|
-// Returns the number of allocated objects in the pool.
|
|
|
-template < typename PoolType >
|
|
|
-int Pool< PoolType >::GetNumAllocatedObjects() const
|
|
|
-{
|
|
|
- return num_allocated_objects;
|
|
|
-}
|
|
|
-
|
|
|
-// Creates a new pool chunk and appends its nodes to the beginning of the free list.
|
|
|
-template < typename PoolType >
|
|
|
-void Pool< PoolType >::CreateChunk()
|
|
|
-{
|
|
|
- if (chunk_size <= 0)
|
|
|
- return;
|
|
|
-
|
|
|
- // Create the new chunk and mark it as the first chunk.
|
|
|
- PoolChunk* new_chunk = new PoolChunk();
|
|
|
- new_chunk->next = pool;
|
|
|
- pool = new_chunk;
|
|
|
-
|
|
|
- // Create chunk's pool nodes.
|
|
|
- new_chunk->chunk = new PoolNode[chunk_size];
|
|
|
-
|
|
|
- // Initialise the linked list.
|
|
|
- for (int i = 0; i < chunk_size; i++)
|
|
|
- {
|
|
|
- if (i == 0)
|
|
|
- new_chunk->chunk[i].previous = NULL ;
|
|
|
- else
|
|
|
- new_chunk->chunk[i].previous = &new_chunk->chunk[i - 1];
|
|
|
-
|
|
|
- if (i == chunk_size - 1)
|
|
|
- new_chunk->chunk[i].next = first_free_node;
|
|
|
- else
|
|
|
- new_chunk->chunk[i].next = &new_chunk->chunk[i + 1];
|
|
|
- }
|
|
|
-
|
|
|
- first_free_node = new_chunk->chunk;
|
|
|
-}
|