From 1d6058ffac6bcb7ea9155567a90895ba46320038 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 15 Dec 2017 13:11:08 +0000 Subject: [PATCH] Modified factory to use pool instead of custom internal allocator. --- src/factory.h | 221 +++++++++++++++++++------------------------------- 1 file changed, 82 insertions(+), 139 deletions(-) diff --git a/src/factory.h b/src/factory.h index b7c8c6db..6957fe85 100644 --- a/src/factory.h +++ b/src/factory.h @@ -39,6 +39,7 @@ SOFTWARE. #include "alignment.h" #include "static_assert.h" #include "type_lookup.h" +#include #undef ETL_FILE #define ETL_FILE "40" @@ -125,12 +126,9 @@ namespace etl static const size_t MAX_SIZE = MAX_SIZE_; //************************************************************************* - /// Constructor + /// Default constructor. //************************************************************************* factory() - : p_next(reinterpret_cast(&buffer[0])), - items_allocated(0), - items_initialised(0) { } @@ -142,11 +140,20 @@ namespace etl { STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = reinterpret_cast(allocate_item()); + T* p = nullptr; - if (p != nullptr) + if (pool.full()) { - new (p) T(); + ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create)); + } + else + { + p = pool.allocate(); + + if (p != nullptr) + { + new (p) T(); + } } return p; @@ -160,11 +167,20 @@ namespace etl { STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = reinterpret_cast(allocate_item()); + T* p = nullptr; - if (p != nullptr) + if (pool.full()) { - new (p) T(p1); + ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create)); + } + else + { + p = pool.allocate(); + + if (p != nullptr) + { + new (p) T(p1); + } } return p; @@ -178,11 +194,20 @@ namespace etl { STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = reinterpret_cast(allocate_item()); + T* p = nullptr; - if (p != nullptr) + if (pool.full()) { - new (p) T(p1, p2); + ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create)); + } + else + { + p = pool.allocate(); + + if (p != nullptr) + { + new (p) T(p1, p2); + } } return p; @@ -196,11 +221,20 @@ namespace etl { STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = reinterpret_cast(allocate_item()); + T* p = nullptr; - if (p != nullptr) + if (pool.full()) { - new (p) T(p1, p2, p3); + ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create)); + } + else + { + p = pool.allocate(); + + if (p != nullptr) + { + new (p) T(p1, p2, p3); + } } return p; @@ -214,11 +248,20 @@ namespace etl { STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = reinterpret_cast(allocate_item()); + T* p = nullptr; - if (p != nullptr) + if (pool.full()) { - new (p) T(p1, p2, p3, p4); + ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create)); + } + else + { + p = pool.allocate(); + + if (p != nullptr) + { + new (p) T(p1, p2, p3, p4); + } } return p; @@ -305,7 +348,18 @@ namespace etl p->~T(); - return release_item(reinterpret_cast(const_cast(p))); + void* vp = reinterpret_cast(const_cast(p)); + + if (pool.is_in_pool(vp)) + { + pool.release(reinterpret_cast(const_cast(p))); + return true; + } + else + { + ETL_ASSERT(false, ETL_ERROR(factory_did_not_create)); + return false; + } } //************************************************************************* @@ -321,7 +375,7 @@ namespace etl //************************************************************************* size_t available() const { - return MAX_SIZE - items_allocated; + return pool.available(); } //************************************************************************* @@ -329,7 +383,7 @@ namespace etl //************************************************************************* size_t size() const { - return items_allocated; + return pool.size(); } //************************************************************************* @@ -338,7 +392,7 @@ namespace etl //************************************************************************* bool empty() const { - return items_allocated == 0; + return pool.empty(); } //************************************************************************* @@ -347,7 +401,7 @@ namespace etl //************************************************************************* bool full() const { - return items_allocated == MAX_SIZE;; + return pool.full(); } private: @@ -355,121 +409,10 @@ namespace etl factory(const factory&); factory& operator =(const factory&); - //************************************************************************* - /// Allocate an item from the pool. - //************************************************************************* - char* allocate_item() - { - char* p_value = nullptr; - - // Any free space left? - if (items_allocated < MAX_SIZE) - { - // Initialise another one if necessary. - if (items_initialised < MAX_SIZE) - { - uintptr_t p = reinterpret_cast(reinterpret_cast(&buffer[0]) + (items_initialised * ITEM_SIZE)); - *reinterpret_cast(p) = p + ITEM_SIZE; - ++items_initialised; - } - - // Get the address of new allocated item. - p_value = p_next; - - ++items_allocated; - if (items_allocated != MAX_SIZE) - { - // Set up the pointer to the next free item - p_next = *reinterpret_cast(p_next); - } - else - { - // No more left! - p_next = nullptr; - } - } - else - { - ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create)); - } - - return p_value; - } - - //************************************************************************* - /// Release an item back to the pool. - //************************************************************************* - bool release_item(char* p_value) - { - if (is_item_in_pool(p_value)) - { - if (p_next != nullptr) - { - // Point it to the current free item. - *(uintptr_t*)p_value = reinterpret_cast(p_next); - } - else - { - // This is the only free item. - *((uintptr_t*)p_value) = 0; - } - - p_next = p_value; - - --items_allocated; - - return true; - } - else - { - ETL_ASSERT(false, ETL_ERROR(factory_did_not_create)); - } - - return false; - } - - //************************************************************************* - /// Check if the item belongs to this pool. - //************************************************************************* - bool is_item_in_pool(char* p) const - { - if (empty() || (p == nullptr)) - { - return false; - } - - // Within the range of the buffer? - intptr_t distance = p - reinterpret_cast(&buffer[0]); - bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_SIZE) - ITEM_SIZE)); - - // Modulus and division can be slow on some architectures, so only do this in debug. -#if defined(ETL_DEBUG) - // Is the address on a valid object boundary? - bool is_valid_address = ((distance % ITEM_SIZE) == 0); -#else - bool is_valid_address = true; -#endif - - return is_within_range && is_valid_address; - } - - // The pool element. - union Element - { - uintptr_t next; ///< Pointer to the next free element. - char value[etl::largest::size]; ///< Storage for value type. - typename etl::type_with_alignment::alignment>::type dummy; ///< Dummy item to get correct alignment. - }; - - ///< The memory for the pool of objects. - typename etl::aligned_storage::value>::type buffer[MAX_SIZE]; - - static const uint32_t ITEM_SIZE = sizeof(Element); - - char* p_next; - - uint32_t items_allocated; ///< The number of items allocated. - uint32_t items_initialised; ///< The number of items initialised. + // The pool. + etl::generic_pool::size, + etl::largest::alignment, + MAX_SIZE> pool; }; }