From e0e7d20a9b4d40a2a5d106d2ee874cac9ca9018d Mon Sep 17 00:00:00 2001 From: jwellbelove Date: Wed, 10 Dec 2014 16:45:15 +0000 Subject: [PATCH] Hoisted pool functionality --- ipool.h | 101 ++++++++++++++++++------ pool.h | 131 +------------------------------- pool_base.h | 128 +++++++++++++++++++++++++++++++ test/vs2013/etl.vcxproj | 3 + test/vs2013/etl.vcxproj.filters | 9 +++ 5 files changed, 219 insertions(+), 153 deletions(-) create mode 100644 pool_base.h diff --git a/ipool.h b/ipool.h index e507b29d5..c5370785c 100644 --- a/ipool.h +++ b/ipool.h @@ -30,33 +30,88 @@ SOFTWARE. #define __ETL_IPOOL__ #define __ETL_IN_IPOOL_H__ -//***************************************************************************** -///\defgroup pool pool -/// A fixed capacity pool. -///\ingroup containers -//***************************************************************************** +#include "pool_base.h" +#include "nullptr.h" + +#ifndef ETL_THROW_EXCEPTIONS +#include "error_handler.h" +#endif namespace etl { //************************************************************************* - /// A templated pool implementation that uses a fixed size pool. - /// SIZE_ elements will be always be constructed. + ///\ingroup pool //************************************************************************* template class ipool : public pool_base { - private: - - struct element - { - T* p_item; - }; - public: + //************************************************************************* + /// Allocate an object from the pool. + /// If ETL_THROW_EXCEPTIONS is defined and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + /// \note The state of the object returned is undefined. + //************************************************************************* T* allocate() { - if (next_free) + if (next_free != MAX_SIZE) + { + T* result = &p_buffer[next_free]; + in_use_flags.set(next_free); + next_free = in_use_flags.find_first(false); + ++items_allocated; + return result; + } + else + { +#ifdef ETL_THROW_EXCEPTIONS + throw pool_no_allocation(); +#else + error_handler::error(pool_no_allocation()); +#endif + return nullptr; + } + } + + //************************************************************************* + /// Free an object in the pool. + /// If ETL_THROW_EXCEPTIONS is defined and the object does not belong to this + /// pool then an etl::pool_object_not_in_pool is thrown. + /// \param p_object A pointer to the object to be released. + //************************************************************************* + void release(const T& object) + { + release(&object); + } + + //************************************************************************* + /// Free an object in the pool. + /// If ETL_THROW_EXCEPTIONS is defined and the object does not belong to this + /// pool then an etl::pool_object_not_in_pool is thrown. + /// \param p_object A pointer to the object to be released. + //************************************************************************* + void release(const T* const p_object) + { + // Does this object belong to this pool? + typename std::iterator_traits::difference_type distance = p_object - p_buffer; + + // Not within the range of the buffer? + if ((distance < 0) || (distance >= static_cast::difference_type>(MAX_SIZE))) + { +#ifdef ETL_THROW_EXCEPTIONS + throw pool_object_not_in_pool(); +#else + error_handler::error(pool_object_not_in_pool()); +#endif + } + else + { + // Mark the object as available. + next_free = static_cast(distance); + in_use_flags.reset(next_free); + --items_allocated; + } } protected: @@ -64,19 +119,15 @@ namespace etl //************************************************************************* /// Constructor //************************************************************************* - ipool(T* p_buffer, size_t size) - : next_free(0), - p_buffer(p_buffer), - SIZE(size) - + ipool(T* p_buffer, ibitset& in_use_flags, size_t size) + : pool_base(size), + p_buffer(nullptr), + in_use_flags(in_use_flags) { } - private: - - size_t next_free; - T* p_buffer; - const size_t SIZE; + T* p_buffer; + ibitset& in_use_flags; }; } #endif diff --git a/pool.h b/pool.h index 877e905da..b57b8b55b 100644 --- a/pool.h +++ b/pool.h @@ -30,7 +30,7 @@ SOFTWARE. #define __ETL_POOL__ #include "bitset.h" -#include "nullptr.h" +#include "ipool.h" #include @@ -42,54 +42,13 @@ SOFTWARE. namespace etl { -#ifdef ETL_THROW_EXCEPTIONS - //*************************************************************************** - /// The base class for pool exceptions. - ///\ingroup pool - //*************************************************************************** - class pool_exception : public exception - { - public: - - pool_exception(const char* what) - : exception(what) - {} - }; - - //*************************************************************************** - /// The exception thrown when the pool has no more free items. - ///\ingroup pool - //*************************************************************************** - class pool_no_allocation : public pool_exception - { - public: - - pool_no_allocation() - : pool_exception("pool: no allocation") - {} - }; - - //*************************************************************************** - /// The exception thrown when an object is released which does not belong to the pool. - ///\ingroup pool - //*************************************************************************** - class pool_object_not_in_pool : public pool_exception - { - public: - - pool_object_not_in_pool() - : pool_exception("pool: not in pool") - {} - }; -#endif - //************************************************************************* /// A templated pool implementation that uses a fixed size pool. /// SIZE_ elements will be always be constructed. ///\ingroup pool //************************************************************************* template - class pool + class pool : public ipool { public: @@ -99,96 +58,12 @@ namespace etl /// Constructor //************************************************************************* pool() - : next_free(0), - count(0) - { - } - - //************************************************************************* - /// Allocate an object from the pool. - /// If ETL_THROW_EXCEPTIONS is defined and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. - /// \note The state of the object returned is undefined. - //************************************************************************* - T* allocate() - { - if (next_free != SIZE) - { - T* result = &buffer[next_free]; - in_use.set(next_free); - next_free = in_use.find_first(false); - ++count; - return result; - } - else - { -#ifdef ETL_THROW_EXCEPTIONS - throw pool_no_allocation(); -#else - return nullptr; -#endif - } - } - - //************************************************************************* - /// Free an object in the pool. - /// If ETL_THROW_EXCEPTIONS is defined and the object does not belong to this - /// pool then an etl::pool_object_not_in_pool is thrown. - /// \param object A reference to the object to be released. - //************************************************************************* - void release(const T& object) - { - release(&object); - } - - //************************************************************************* - /// Free an object in the pool. - /// If ETL_THROW_EXCEPTIONS is defined and the object does not belong to this - /// pool then an etl::pool_object_not_in_pool is thrown. - /// \param p_object A pointer to the object to be released. - //************************************************************************* - void release(const T* const p_object) - { - // Does this object belong to this pool? - typename std::iterator_traits::difference_type distance = p_object - buffer; - - // Not within the range of the buffer? - if ((distance < 0) || (distance >= SIZE)) - { -#ifdef ETL_THROW_EXCEPTIONS - throw pool_object_not_in_pool(); -#endif - } - else - { - // Mark the object as available. - next_free = static_cast(distance); - in_use.reset(next_free); - --count; - } - } - - //************************************************************************* - /// Returns the number of free items in the pool. - //************************************************************************* - size_t available() const - { - return SIZE - in_use.count(); - } - - //************************************************************************* - /// Checks to see if there are no free items in the pool. - /// \return true if there are none free (or 'empty') - //************************************************************************* - bool empty() const + : ipool(buffer, in_use, SIZE) { - return count == SIZE; } private: - size_t next_free; ///< The position of the next free item in the pool. - size_t count; ///< The number of objects allocated. T buffer[SIZE]; ///< The pool of objects. bitset in_use; ///< The set of flags that indicate which items are free in the pool. }; diff --git a/pool_base.h b/pool_base.h new file mode 100644 index 000000000..bee9fcc45 --- /dev/null +++ b/pool_base.h @@ -0,0 +1,128 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. + +Copyright(c) 2014 jwellbelove + +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. +******************************************************************************/ + +#ifndef __ETL_IN_IPOOL_H__ +#error This header is a private element of etl::pool & etl::ipool +#endif + +#ifndef __ETL_POOL_BASE__ +#define __ETL_POOL_BASE__ + +#include + +#include "exception.h" + +#ifndef ETL_THROW_EXCEPTIONS +#include "error_handler.h" +#endif + +namespace etl +{ + //*************************************************************************** + /// The base class for pool exceptions. + ///\ingroup pool + //*************************************************************************** + class pool_exception : public exception + { + public: + + pool_exception(const char* what) + : exception(what) + {} + }; + + //*************************************************************************** + /// The exception thrown when the pool has no more free items. + ///\ingroup pool + //*************************************************************************** + class pool_no_allocation : public pool_exception + { + public: + + pool_no_allocation() + : pool_exception("pool: no allocation") + {} + }; + + //*************************************************************************** + /// The exception thrown when an object is released which does not belong to the pool. + ///\ingroup pool + //*************************************************************************** + class pool_object_not_in_pool : public pool_exception + { + public: + + pool_object_not_in_pool() + : pool_exception("pool: not in pool") + {} + }; + + //************************************************************************* + /// The base class for all templated pool types. + ///\ingroup pool + //************************************************************************* + class pool_base + { + public: + + //************************************************************************* + /// Returns the number of free items in the pool. + //************************************************************************* + size_t available() const + { + return MAX_SIZE - items_allocated; + } + + //************************************************************************* + /// Checks to see if there are no free items in the pool. + /// \return true if there are none free (or 'empty') + //************************************************************************* + bool empty() const + { + return items_allocated == MAX_SIZE; + } + + protected: + + //************************************************************************* + /// Constructor + //************************************************************************* + pool_base(size_t max_size) + : next_free(0), + items_allocated(0), + MAX_SIZE(max_size) + { + } + + size_t next_free; ///< The position of the next free item in the pool. + size_t items_allocated; ///< The number of items allocated. + const size_t MAX_SIZE; ///< The maximum number of objects that can be allocated. + }; +} +#endif + diff --git a/test/vs2013/etl.vcxproj b/test/vs2013/etl.vcxproj index 7a98cfc20..2e16805bf 100644 --- a/test/vs2013/etl.vcxproj +++ b/test/vs2013/etl.vcxproj @@ -140,11 +140,13 @@ + + @@ -159,6 +161,7 @@ + diff --git a/test/vs2013/etl.vcxproj.filters b/test/vs2013/etl.vcxproj.filters index 9e743c36a..c5c3c90f2 100644 --- a/test/vs2013/etl.vcxproj.filters +++ b/test/vs2013/etl.vcxproj.filters @@ -300,6 +300,15 @@ ETL\Maths + + ETL\Containers + + + ETL\Containers + + + ETL\Containers +