From f3ace52884b87abb3729dccfbf0dfd74fb62f6d4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 4 May 2020 13:32:19 +0100 Subject: [PATCH] Initial design --- include/etl/fsm.h | 38 +- include/etl/generators/fsm_generator.h | 4 +- .../etl/generators/message_packet_generator.h | 12 +- .../etl/generators/message_router_generator.h | 6 +- .../etl/generators/variant_pool_generator.h | 4 +- include/etl/generic_pool.h | 209 +++++++ include/etl/ipool.h | 495 +++++++++++++++ include/etl/list.h | 2 +- include/etl/memory.h | 10 + include/etl/message.h | 92 ++- include/etl/message_bus.h | 4 +- include/etl/message_packet.h | 96 +-- include/etl/message_pool.h | 258 ++++++++ include/etl/message_router.h | 34 +- include/etl/pool.h | 584 +----------------- include/etl/reference_counted_object.h | 51 ++ include/etl/shared_message.h | 137 ++++ include/etl/variant_pool.h | 252 +------- test/test_message_packet.cpp | 38 +- test/test_message_router.cpp | 10 +- test/test_pool_message.cpp | 127 ++++ test/test_variant_pool.cpp | 4 +- test/vs2019/etl.vcxproj | 5 + test/vs2019/etl.vcxproj.filters | 15 + 24 files changed, 1553 insertions(+), 934 deletions(-) create mode 100644 include/etl/generic_pool.h create mode 100644 include/etl/ipool.h create mode 100644 include/etl/message_pool.h create mode 100644 include/etl/reference_counted_object.h create mode 100644 include/etl/shared_message.h create mode 100644 test/test_pool_message.cpp diff --git a/include/etl/fsm.h b/include/etl/fsm.h index 7bc2eefd..cfde1a2b 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -211,8 +211,10 @@ namespace etl /// Constructor. //******************************************* fsm(etl::message_router_id_t id) - : imessage_router(id), - p_state(ETL_NULLPTR) + : imessage_router(id) + , p_state(ETL_NULLPTR) + , state_list(ETL_NULLPTR) + , number_of_states(0U) { } @@ -434,7 +436,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -499,7 +501,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -563,7 +565,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -626,7 +628,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -687,7 +689,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -747,7 +749,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -806,7 +808,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -864,7 +866,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -920,7 +922,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -975,7 +977,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -1029,7 +1031,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -1082,7 +1084,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -1133,7 +1135,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -1183,7 +1185,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -1232,7 +1234,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { @@ -1280,7 +1282,7 @@ namespace etl etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message) { etl::fsm_state_id_t new_state_id; - etl::message_id_t event_id = message.message_id; + etl::message_id_t event_id = message.get_message_id(); switch (event_id) { diff --git a/include/etl/generators/fsm_generator.h b/include/etl/generators/fsm_generator.h index 85552006..4d590025 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -454,7 +454,7 @@ namespace etl cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)") cog.outl(" {") cog.outl(" etl::fsm_state_id_t new_state_id;") - cog.outl(" etl::message_id_t event_id = message.message_id;") + cog.outl(" etl::message_id_t event_id = message.get_message_id();") cog.outl("") cog.outl(" switch (event_id)") cog.outl(" {") @@ -531,7 +531,7 @@ namespace etl cog.outl(" etl::fsm_state_id_t process_event(etl::imessage_router& source, const etl::imessage& message)") cog.outl(" {") cog.outl(" etl::fsm_state_id_t new_state_id;") - cog.outl(" etl::message_id_t event_id = message.message_id;") + cog.outl(" etl::message_id_t event_id = message.get_message_id();") cog.outl("") cog.outl(" switch (event_id)") cog.outl(" {") diff --git a/include/etl/generators/message_packet_generator.h b/include/etl/generators/message_packet_generator.h index 9aa923e1..0661da8c 100644 --- a/include/etl/generators/message_packet_generator.h +++ b/include/etl/generators/message_packet_generator.h @@ -217,7 +217,7 @@ namespace etl cog.outl("#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)") cog.outl(" pmsg->~imessage();") cog.outl("#else") - cog.outl(" size_t id = pmsg->message_id;") + cog.outl(" size_t id = pmsg->get_message_id();") cog.outl("") cog.outl(" switch (id)") cog.outl(" {") @@ -232,7 +232,7 @@ namespace etl cog.outl(" //********************************************") cog.outl(" void add_new_message(const etl::imessage& msg)") cog.outl(" {") - cog.outl(" const size_t id = msg.message_id;") + cog.outl(" const size_t id = msg.get_message_id();") cog.outl(" void* p = data;") cog.outl("") cog.outl(" switch (id)") @@ -247,7 +247,7 @@ namespace etl cog.outl(" //********************************************") cog.outl(" void add_new_message(etl::imessage&& msg)") cog.outl(" {") - cog.outl(" const size_t id = msg.message_id;") + cog.outl(" const size_t id = msg.get_message_id();") cog.outl(" void* p = data;") cog.outl("") cog.outl(" switch (id)") @@ -416,7 +416,7 @@ namespace etl cog.outl("#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)") cog.outl(" pmsg->~imessage();") cog.outl("#else") - cog.outl(" size_t id = pmsg->message_id;") + cog.outl(" size_t id = pmsg->get_message_id();") cog.outl("") cog.outl(" switch (id)") cog.outl(" {") @@ -431,7 +431,7 @@ namespace etl cog.outl(" //********************************************") cog.outl(" void add_new_message(const etl::imessage& msg)") cog.outl(" {") - cog.outl(" const size_t id = msg.message_id;") + cog.outl(" const size_t id = msg.get_message_id();") cog.outl(" void* p = data;") cog.outl("") cog.outl(" switch (id)") @@ -446,7 +446,7 @@ namespace etl cog.outl(" //********************************************") cog.outl(" void add_new_message(etl::imessage&& msg)") cog.outl(" {") - cog.outl(" const size_t id = msg.message_id;") + cog.outl(" const size_t id = msg.get_message_id();") cog.outl(" void* p = data;") cog.outl("") cog.outl(" switch (id)") diff --git a/include/etl/generators/message_router_generator.h b/include/etl/generators/message_router_generator.h index 791b3297..4f0294b2 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -126,7 +126,7 @@ namespace etl //******************************************** bool accepts(const etl::imessage& msg) const { - return accepts(msg.message_id); + return accepts(msg.get_message_id()); } //******************************************** @@ -376,7 +376,7 @@ namespace etl cog.outl(" //**********************************************") cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE") cog.outl(" {") - cog.outl(" const etl::message_id_t id = msg.message_id;") + cog.outl(" const etl::message_id_t id = msg.get_message_id();") cog.outl("") cog.outl(" switch (id)") cog.outl(" {") @@ -509,7 +509,7 @@ namespace etl cog.outl(" //**********************************************") cog.outl(" void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE") cog.outl(" {") - cog.outl(" const size_t id = msg.message_id;") + cog.outl(" const size_t id = msg.get_message_id();") cog.outl("") cog.outl(" switch (id)") cog.outl(" {") diff --git a/include/etl/generators/variant_pool_generator.h b/include/etl/generators/variant_pool_generator.h index cd9489d1..6cd00657 100644 --- a/include/etl/generators/variant_pool_generator.h +++ b/include/etl/generators/variant_pool_generator.h @@ -369,7 +369,7 @@ namespace etl /// Destroys the object. //************************************************************************* template - bool destroy(const T* const p) + void destroy(const T* const p) { /*[[[cog import cog @@ -395,12 +395,10 @@ namespace etl if (pool.is_in_pool(vp)) { pool.release(vp); - return true; } else { ETL_ASSERT(false, ETL_ERROR(variant_pool_did_not_create)); - return false; } } diff --git a/include/etl/generic_pool.h b/include/etl/generic_pool.h new file mode 100644 index 00000000..ac1fdbf1 --- /dev/null +++ b/include/etl/generic_pool.h @@ -0,0 +1,209 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +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_GENERIC_POOL_INCLUDED +#define ETL_GENERIC_POOL_INCLUDED + +#include "platform.h" +#include "ipool.h" +#include "type_traits.h" +#include "static_assert.h" +#include "alignment.h" + +#define ETL_POOL_CPP03_CODE 0 + +//***************************************************************************** +///\defgroup pool pool +/// A fixed capacity pool. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + //************************************************************************* + /// A templated abstract pool implementation that uses a fixed size pool. + ///\ingroup pool + //************************************************************************* + template + class generic_pool : public etl::ipool + { + public: + + static const size_t SIZE = SIZE_; + static const size_t ALIGNMENT = ALIGNMENT_; + static const size_t TYPE_SIZE = TYPE_SIZE_; + + //************************************************************************* + /// Constructor + //************************************************************************* + generic_pool() + : etl::ipool(reinterpret_cast(&buffer[0]), ELEMENT_SIZE, SIZE) + { + } + + //************************************************************************* + /// Allocate an object from the pool. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + /// Static asserts if the specified type is too large for the pool. + //************************************************************************* + template + U* allocate() + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::allocate(); + } + +#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_STLPORT) + //************************************************************************* + /// Allocate storage for an object from the pool and create with default. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + U* create() + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 1 parameter. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + U* create(const T1& value1) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 2 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1, value2); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 3 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2, const T3& value3) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1, value2, value3); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 4 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1, value2, value3, value4); + } +#else + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + U* create(Args&&... args) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(etl::forward(args)...); + } +#endif + + //************************************************************************* + /// Releases the object. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void release(const U* const p_object) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + ipool::release(p_object); + } + + //************************************************************************* + /// Destroys the object. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void destroy(const U* const p_object) + { + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + ipool::destroy(p_object); + } + + private: + + // The pool element. + union Element + { + char* next; ///< Pointer to the next free element. + char value[TYPE_SIZE_]; ///< Storage for value type. + typename etl::type_with_alignment::type dummy; ///< Dummy item to get correct alignment. + }; + + ///< The memory for the pool of objects. + typename etl::aligned_storage::value>::type buffer[SIZE]; + + static ETL_CONST_OR_CONSTEXPR uint32_t ELEMENT_SIZE = sizeof(Element); + + // Should not be copied. + generic_pool(const generic_pool&); + generic_pool& operator =(const generic_pool&); + }; +} + +#endif + diff --git a/include/etl/ipool.h b/include/etl/ipool.h new file mode 100644 index 00000000..018181ed --- /dev/null +++ b/include/etl/ipool.h @@ -0,0 +1,495 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +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_IPOOL_INCLUDED +#define ETL_IPOOL_INCLUDED + +#include "platform.h" +#include "error_handler.h" +#include "exception.h" +#include "static_assert.h" +#include "utility.h" +#include "memory.h" + +#include + +#undef ETL_FILE +#define ETL_FILE "11" + +#define ETL_POOL_CPP03_CODE 0 + +//***************************************************************************** +///\defgroup pool pool +/// A fixed capacity pool. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + //*************************************************************************** + /// The base class for pool exceptions. + ///\ingroup pool + //*************************************************************************** + class pool_exception : public exception + { + public: + + pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + {} + }; + + //*************************************************************************** + /// The exception thrown when the pool has no more free items. + ///\ingroup pool + //*************************************************************************** + class pool_no_allocation : public pool_exception + { + public: + + explicit pool_no_allocation(string_type file_name_, numeric_type line_number_) + : pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name_, line_number_) + {} + }; + + //*************************************************************************** + /// 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(string_type file_name_, numeric_type line_number_) + : pool_exception(ETL_ERROR_TEXT("pool:not in pool", ETL_FILE"B"), file_name_, line_number_) + {} + }; + + //*************************************************************************** + /// The exception thrown when an the type requested is larger than the element size. + ///\ingroup pool + //*************************************************************************** + class pool_element_size : public pool_exception + { + public: + + pool_element_size(string_type file_name_, numeric_type line_number_) + : pool_exception(ETL_ERROR_TEXT("pool:element size", ETL_FILE"C"), file_name_, line_number_) + {} + }; + + //*************************************************************************** + /// The base implementation of a pool. + /// Implements the imemory_block_pool interface. + //*************************************************************************** + class ipool : public imemory_block_pool + { + public: + + typedef size_t size_type; + + //************************************************************************* + /// Implementation of the low level imemory_block_pool interface. + //************************************************************************* + void* allocate_memory_block(size_t require_size) ETL_OVERRIDE + { + return allocate(); + } + + //************************************************************************* + /// Implementation of the low level imemory_block_pool interface. + //************************************************************************* + void release_memory_block(const void* const ptr) ETL_OVERRIDE + { + release(ptr); + } + + //************************************************************************* + /// Implementation of the low level imemory_block_pool interface. + //************************************************************************* + size_t get_memory_block_size() ETL_OVERRIDE + { + return ITEM_SIZE; + } + + //************************************************************************* + /// Allocate storage for an object from the pool. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + T* allocate() + { + if (sizeof(T) > ITEM_SIZE) + { + ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size)); + } + + return reinterpret_cast(allocate_item()); + } + +#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_STLPORT) + //************************************************************************* + /// Allocate storage for an object from the pool and create default. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + T* create() + { + T* p = allocate(); + + if (p) + { + ::new (p) T(); + } + + return p; + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 1 parameter. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. + //************************************************************************* + template + T* create(const T1& value1) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1); + } + + return p; + } + + template + T* create(const T1& value1, const T2& value2) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1, value2); + } + + return p; + } + + template + T* create(const T1& value1, const T2& value2, const T3& value3) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1, value2, value3); + } + + return p; + } + + template + T* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1, value2, value3, value4); + } + + return p; + } +#else + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + T* create(Args&&... args) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(etl::forward(args)...); + } + + return p; + } +#endif + + //************************************************************************* + /// Destroys the object. + /// If asserts or exceptions are enabled and the object does not belong to this + /// pool then an etl::pool_object_not_in_pool is thrown. + /// Undefined behaviour if p_object is not a 'T' or derived from 'T'. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void destroy(const T* const p_object) + { + // Does it belong to us? + if (is_in_pool(p_object)) + { + p_object->~T(); + release_item((char*)p_object); + } + else + { + ETL_ALWAYS_ASSERT(ETL_ERROR(pool_object_not_in_pool)); + } + } + + //************************************************************************* + /// Release an object in the pool. + /// If asserts or exceptions are enabled 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 void* const p_object) + { + // Does it belong to us? + if (is_in_pool(p_object)) + { + release_item((char*)p_object); + } + else + { + ETL_ALWAYS_ASSERT(ETL_ERROR(pool_object_not_in_pool)); + } + } + + //************************************************************************* + /// Release all objects in the pool. + //************************************************************************* + void release_all() + { + items_allocated = 0; + items_initialised = 0; + p_next = p_buffer; + } + + //************************************************************************* + /// Check to see if the object belongs to the pool. + /// \param p_object A pointer to the object to be checked. + /// \return true<\b> if it does, otherwise false + //************************************************************************* + bool is_in_pool(const void* p_object) const + { + return is_item_in_pool((const char*)p_object); + } + + //************************************************************************* + /// Returns the maximum number of items in the pool. + //************************************************************************* + size_t max_size() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Returns the maximum number of items in the pool. + //************************************************************************* + size_t capacity() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Returns the number of free items in the pool. + //************************************************************************* + size_t available() const + { + return MAX_SIZE - items_allocated; + } + + //************************************************************************* + /// Returns the number of allocated items in the pool. + //************************************************************************* + size_t size() const + { + return items_allocated; + } + + //************************************************************************* + /// Checks to see if there are no allocated items in the pool. + /// \return true if there are none allocated. + //************************************************************************* + bool empty() const + { + return items_allocated == 0; + } + + //************************************************************************* + /// Checks to see if there are no free items in the pool. + /// \return true if there are none free. + //************************************************************************* + bool full() const + { + return items_allocated == MAX_SIZE; + } + + protected: + + //************************************************************************* + /// Constructor + //************************************************************************* + ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_) + : p_buffer(p_buffer_), + p_next(p_buffer_), + items_allocated(0), + items_initialised(0), + ITEM_SIZE(item_size_), + MAX_SIZE(max_size_) + { + } + + private: + + //************************************************************************* + /// Allocate an item from the pool. + //************************************************************************* + char* allocate_item() + { + char* p_value = ETL_NULLPTR; + + // Any free space left? + if (items_allocated < MAX_SIZE) + { + // Initialise another one if necessary. + if (items_initialised < MAX_SIZE) + { + char* p = p_buffer + (items_initialised * ITEM_SIZE); + char* np = p + ITEM_SIZE; + *reinterpret_cast(p) = np; + ++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 = ETL_NULLPTR; + } + } + else + { + ETL_ASSERT(false, ETL_ERROR(pool_no_allocation)); + } + + return p_value; + } + + //************************************************************************* + /// Release an item back to the pool. + //************************************************************************* + void release_item(char* p_value) + { + if (p_next != ETL_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; + } + + //************************************************************************* + /// Check if the item belongs to this pool. + //************************************************************************* + bool is_item_in_pool(const char* p) const + { + // Within the range of the buffer? + intptr_t distance = p - p_buffer; + 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; + } + + // Disable copy construction and assignment. + ipool(const ipool&); + ipool& operator =(const ipool&); + + char* p_buffer; + char* p_next; + + uint32_t items_allocated; ///< The number of items allocated. + uint32_t items_initialised; ///< The number of items initialised. + + const uint32_t ITEM_SIZE; ///< The size of allocated items. + const uint32_t MAX_SIZE; ///< The maximum number of objects that can be allocated. + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_POOL) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ipool() + { + } +#else + protected: + ~ipool() + { + } +#endif + }; +} + +#undef ETL_FILE + +#endif + diff --git a/include/etl/list.h b/include/etl/list.h index c82b5cf7..c210d702 100644 --- a/include/etl/list.h +++ b/include/etl/list.h @@ -40,7 +40,6 @@ SOFTWARE. #include "algorithm.h" #include "iterator.h" #include "functional.h" - #include "container.h" #include "pool.h" #include "exception.h" @@ -51,6 +50,7 @@ SOFTWARE. #include "algorithm.h" #include "memory.h" #include "iterator.h" +#include "parameter_type.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include diff --git a/include/etl/memory.h b/include/etl/memory.h index 2d61360f..3787165f 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -1900,6 +1900,16 @@ namespace etl memory_clear(static_cast(*this)); } }; + + //************************************************************************* + /// The interface for a memory block pool. + //************************************************************************* + struct imemory_block_pool + { + virtual void* allocate_memory_block(size_t required_size) = 0; + virtual void release_memory_block(const void* const) = 0; + virtual size_t get_memory_block_size() = 0; + }; } #endif diff --git a/include/etl/message.h b/include/etl/message.h index 02baf2d5..c0e3dcaf 100644 --- a/include/etl/message.h +++ b/include/etl/message.h @@ -35,6 +35,7 @@ SOFTWARE. #include "error_handler.h" #include "exception.h" #include "message_types.h" +#include "reference_counted_object.h" #undef ETL_FILE #define ETL_FILE "38" @@ -68,39 +69,90 @@ namespace etl { public: - imessage(etl::message_id_t id) - : message_id(id) - { - } - - const etl::message_id_t message_id; - -#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) virtual ~imessage() { } -#else - ~imessage() - { - } -#endif + + ETL_NODISCARD virtual etl::message_id_t get_message_id() const ETL_NOEXCEPT = 0; }; //*************************************************************************** - template - class message : public imessage + class ireference_counted_message : public etl::imessage, public etl::ireference_counted_object + { + }; + + //*************************************************************************** + template + class reference_counted_message : public etl::ireference_counted_message + { + private: + + //*************************************************************************** + void set_reference_count(uint32_t value) ETL_OVERRIDE + { + reference_count = value; + } + + //*************************************************************************** + void increment_reference_count() ETL_OVERRIDE + { + ++reference_count; + } + + //*************************************************************************** + ETL_NODISCARD uint32_t decrement_reference_count() ETL_OVERRIDE + { + return uint32_t(--reference_count); + } + + //*************************************************************************** + ETL_NODISCARD uint32_t get_reference_count() const ETL_OVERRIDE + { + return uint32_t(reference_count); + } + + private: + + /// The reference counter. + TCounter reference_count; + }; + + //*************************************************************************** + // Reference counted message. + //*************************************************************************** + template + class message : public reference_counted_message { public: - message() - : imessage(ID_) - { - } - enum { ID = ID_ }; + + ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT + { + return ID; + } + }; + + //*************************************************************************** + // Non-reference counted message. + //*************************************************************************** + template + class message : public imessage + { + public: + + enum + { + ID = ID_ + }; + + ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT + { + return ID; + } }; } diff --git a/include/etl/message_bus.h b/include/etl/message_bus.h index e981fe48..048ecc7e 100644 --- a/include/etl/message_bus.h +++ b/include/etl/message_bus.h @@ -187,7 +187,7 @@ namespace etl { etl::imessage_router& router = **irouter; - if (router.accepts(message.message_id)) + if (router.accepts(message.get_message_id())) { router.receive(source, message); } @@ -213,7 +213,7 @@ namespace etl // Call all of them. while (range.first != range.second) { - if ((*(range.first))->accepts(message.message_id)) + if ((*(range.first))->accepts(message.get_message_id())) { (*(range.first))->receive(source, message); } diff --git a/include/etl/message_packet.h b/include/etl/message_packet.h index eec72724..fa76295a 100644 --- a/include/etl/message_packet.h +++ b/include/etl/message_packet.h @@ -190,7 +190,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -219,7 +219,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -248,7 +248,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -403,7 +403,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -431,7 +431,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -459,7 +459,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -613,7 +613,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -640,7 +640,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -667,7 +667,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -820,7 +820,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -846,7 +846,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -872,7 +872,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1023,7 +1023,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -1048,7 +1048,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1073,7 +1073,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1223,7 +1223,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -1247,7 +1247,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1271,7 +1271,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1420,7 +1420,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -1443,7 +1443,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1466,7 +1466,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1614,7 +1614,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -1636,7 +1636,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1658,7 +1658,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1804,7 +1804,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -1825,7 +1825,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1846,7 +1846,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -1991,7 +1991,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -2011,7 +2011,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2031,7 +2031,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2175,7 +2175,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -2194,7 +2194,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2213,7 +2213,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2356,7 +2356,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -2374,7 +2374,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2392,7 +2392,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2533,7 +2533,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -2550,7 +2550,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2567,7 +2567,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2707,7 +2707,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -2723,7 +2723,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2739,7 +2739,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2878,7 +2878,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -2893,7 +2893,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -2908,7 +2908,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -3046,7 +3046,7 @@ namespace etl #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) pmsg->~imessage(); #else - size_t id = pmsg->message_id; + size_t id = pmsg->get_message_id(); switch (id) { @@ -3060,7 +3060,7 @@ namespace etl //******************************************** void add_new_message(const etl::imessage& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) @@ -3074,7 +3074,7 @@ namespace etl //******************************************** void add_new_message(etl::imessage&& msg) { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); void* p = data; switch (id) diff --git a/include/etl/message_pool.h b/include/etl/message_pool.h new file mode 100644 index 00000000..e1c19b3f --- /dev/null +++ b/include/etl/message_pool.h @@ -0,0 +1,258 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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_MESSAGE_POOL_INCLUDED +#define ETL_MESSAGE_POOL_INCLUDED + +#include "platform.h" +#include "message.h" +#include "static_assert.h" +#include "error_handler.h" +#include "utility.h" + +namespace etl +{ + //*************************************************************************** + /// + //*************************************************************************** + class message_pool_allocation_exception : public etl::exception + { + public: + + message_pool_allocation_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + class message_pool_allocation_failure : etl::message_pool_allocation_exception + { + public: + + message_pool_allocation_failure(string_type file_name_, numeric_type line_number_) + : message_pool_allocation_exception(ETL_ERROR_TEXT("message_pool:allocation failure", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + class message_pool + { + public: + + //************************************************************************* + /// Constructor + //************************************************************************* + message_pool(imemory_block_pool& memory_block_pool_) + : memory_block_pool(memory_block_pool_) + { + } + +#if ETL_CPP11_SUPPORTED && !defined(ETL_MESSAGE_POOL_FORCE_CPP03) + //************************************************************************* + /// Create a message from the pool. + //************************************************************************* + template + TMessage* create(TArgs&&... args) + { + ETL_STATIC_ASSERT((etl::is_base_of::value), "Not a message type"); + + void* p = ETL_NULLPTR; + + if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size()) + { + p = memory_block_pool.allocate_memory_block(sizeof(TMessage)); + + if (p != ETL_NULLPTR) + { + ::new(p) TMessage(etl::forward(args)...); + } + else + { + ETL_ALWAYS_ASSERT(ETL_ERROR(etl::message_pool_allocation_failure)); + } + } + + return reinterpret_cast(p); + } +#else + //************************************************************************* + /// Create a message from the pool. No parameters. + //************************************************************************* + template + TMessage* create() + { + ETL_STATIC_ASSERT((etl::is_base_of::value), "Not a message type"); + + void* p = ETL_NULLPTR; + + if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size()) + { + p = memory_block_pool.allocate_memory_block(sizeof(TMessage)); + + if (p != ETL_NULLPTR) + { + ::new(p) TMessage(); + } + } + + return reinterpret_cast(p); + } + + //************************************************************************* + /// Create a message from the pool. One parameter. + //************************************************************************* + template + TMessage* create(const T1& t1) + { + ETL_STATIC_ASSERT(etl::is_base_of::value, "Not a message type"); + + void* p = ETL_NULLPTR; + + if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size()) + { + p = memory_block_pool.allocate_memory_block(sizeof(TMessage)); + + if (p != ETL_NULLPTR) + { + ::new(p) TMessage(t1); + } + } + + return reinterpret_cast(p); + } + + //************************************************************************* + /// Create a message from the pool. Two parameters. + //************************************************************************* + template + TMessage* create(const T1& t1, const T2& t2) + { + ETL_STATIC_ASSERT(etl::is_base_of::value, "Not a message type"); + + void* p = ETL_NULLPTR; + + if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size()) + { + p = memory_block_pool.allocate_memory_block(sizeof(TMessage)); + + if (p != ETL_NULLPTR) + { + ::new(p) TMessage(t1, t2); + } + } + + return reinterpret_cast(p); + } + + //************************************************************************* + /// Create a message from the pool. Three parameters. + //************************************************************************* + template + TMessage* create(const T1& t1, const T2& t2, const T3& t3) + { + ETL_STATIC_ASSERT(etl::is_base_of::value, "Not a message type"); + + void* p = ETL_NULLPTR; + + if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size()) + { + p = memory_block_pool.allocate_memory_block(sizeof(TMessage)); + + if (p != ETL_NULLPTR) + { + ::new(p) TMessage(t1, t2, t3); + } + } + + return reinterpret_cast(p); + } + + //************************************************************************* + /// Create a message from the pool. Four parameters. + //************************************************************************* + template + TMessage* create(const T1& t1, const T2& t2, const T3& t3, const T4& t4) + { + ETL_STATIC_ASSERT(etl::is_base_of::value, "Not a message type"); + + void* p = ETL_NULLPTR; + + if (sizeof(TMessage) <= memory_block_pool.get_memory_block_size()) + { + p = memory_block_pool.allocate_memory_block(sizeof(TMessage)); + + if (p != ETL_NULLPTR) + { + ::new(p) TMessage(t1, t2, t3, t4); + } + } + + return reinterpret_cast(p) + } +#endif + + //************************************************************************* + /// Destruct a message and send it back to the pool. + //************************************************************************* + void destroy(const etl::imessage* const pmsg) + { + pmsg->~imessage(); + memory_block_pool.release_memory_block(pmsg); + } + + //************************************************************************* + /// Destruct a message and send it back to the pool. + //************************************************************************* + void destroy(const etl::imessage& msg) + { + destroy(&msg); + } + + private: + + /// The raw memory block pool. + imemory_block_pool& memory_block_pool; + + // Should not be copied. + message_pool(const message_pool&) ETL_DELETE; + message_pool& operator =(const message_pool&) ETL_DELETE; + }; +} + +#undef ETL_FILE + +#endif + diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 761494c3..edc3900a 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -114,7 +114,7 @@ namespace etl //******************************************** bool accepts(const etl::imessage& msg) const { - return accepts(msg.message_id); + return accepts(msg.get_message_id()); } //******************************************** @@ -351,7 +351,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const etl::message_id_t id = msg.message_id; + const etl::message_id_t id = msg.get_message_id(); switch (id) { @@ -467,7 +467,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -582,7 +582,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -696,7 +696,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -808,7 +808,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -919,7 +919,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1029,7 +1029,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1138,7 +1138,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1245,7 +1245,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1351,7 +1351,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1455,7 +1455,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1558,7 +1558,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1659,7 +1659,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1759,7 +1759,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1858,7 +1858,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { @@ -1956,7 +1956,7 @@ namespace etl //********************************************** void receive(etl::imessage_router& source, const etl::imessage& msg) ETL_OVERRIDE { - const size_t id = msg.message_id; + const size_t id = msg.get_message_id(); switch (id) { diff --git a/include/etl/pool.h b/include/etl/pool.h index defe802f..af4f617a 100644 --- a/include/etl/pool.h +++ b/include/etl/pool.h @@ -32,24 +32,8 @@ SOFTWARE. #define ETL_POOL_INCLUDED #include "platform.h" - -#include - -#include "algorithm.h" -#include "iterator.h" -#include "utility.h" -#include "error_handler.h" -#include "alignment.h" -#include "array.h" -#include "container.h" -#include "integral_limits.h" -#include "nullptr.h" -#include "alignment.h" +#include "generic_pool.h" #include "static_assert.h" -#include "algorithm.h" - -#undef ETL_FILE -#define ETL_FILE "11" #define ETL_POOL_CPP03_CODE 0 @@ -61,553 +45,6 @@ SOFTWARE. namespace etl { - //*************************************************************************** - /// The base class for pool exceptions. - ///\ingroup pool - //*************************************************************************** - class pool_exception : public exception - { - public: - - pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_) - : exception(reason_, file_name_, line_number_) - {} - }; - - //*************************************************************************** - /// The exception thrown when the pool has no more free items. - ///\ingroup pool - //*************************************************************************** - class pool_no_allocation : public pool_exception - { - public: - - explicit pool_no_allocation(string_type file_name_, numeric_type line_number_) - : pool_exception(ETL_ERROR_TEXT("pool:allocation", ETL_FILE"A"), file_name_, line_number_) - {} - }; - - //*************************************************************************** - /// 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(string_type file_name_, numeric_type line_number_) - : pool_exception(ETL_ERROR_TEXT("pool:not in pool", ETL_FILE"B"), file_name_, line_number_) - {} - }; - - //*************************************************************************** - /// The exception thrown when an the type requested is larger than the element size. - ///\ingroup pool - //*************************************************************************** - class pool_element_size : public pool_exception - { - public: - - pool_element_size(string_type file_name_, numeric_type line_number_) - : pool_exception(ETL_ERROR_TEXT("pool:element size", ETL_FILE"C"), file_name_, line_number_) - {} - }; - - //*************************************************************************** - ///\ingroup pool - //*************************************************************************** - class ipool - { - public: - - typedef size_t size_type; - - //************************************************************************* - /// Allocate storage for an object from the pool. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - T* allocate() - { - if (sizeof(T) > ITEM_SIZE) - { - ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size)); - } - - return reinterpret_cast(allocate_item()); - } - -#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_STLPORT) - //************************************************************************* - /// Allocate storage for an object from the pool and create default. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - T* create() - { - T* p = allocate(); - - if (p) - { - ::new (p) T(); - } - - return p; - } - - //************************************************************************* - /// Allocate storage for an object from the pool and create with 1 parameter. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - T* create(const T1& value1) - { - T* p = allocate(); - - if (p) - { - ::new (p) T(value1); - } - - return p; - } - - template - T* create(const T1& value1, const T2& value2) - { - T* p = allocate(); - - if (p) - { - ::new (p) T(value1, value2); - } - - return p; - } - - template - T* create(const T1& value1, const T2& value2, const T3& value3) - { - T* p = allocate(); - - if (p) - { - ::new (p) T(value1, value2, value3); - } - - return p; - } - - template - T* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) - { - T* p = allocate(); - - if (p) - { - ::new (p) T(value1, value2, value3, value4); - } - - return p; - } -#else - //************************************************************************* - /// Emplace with variadic constructor parameters. - //************************************************************************* - template - T* create(Args&&... args) - { - T* p = allocate(); - - if (p) - { - ::new (p) T(etl::forward(args)...); - } - - return p; - } -#endif - - //************************************************************************* - /// Destroys the object. - /// Undefined behaviour if the pool does not contain a 'T'. - /// \param p_object A pointer to the object to be destroyed. - //************************************************************************* - template - void destroy(const T* const p_object) - { - if (sizeof(T) > ITEM_SIZE) - { - ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size)); - } - - p_object->~T(); - release(p_object); - } - - //************************************************************************* - /// Release an object in the pool. - /// If asserts or exceptions are enabled 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 void* const p_object) - { - release_item((char*)p_object); - } - - //************************************************************************* - /// Release all objects in the pool. - //************************************************************************* - void release_all() - { - items_allocated = 0; - items_initialised = 0; - p_next = p_buffer; - } - - //************************************************************************* - /// Check to see if the object belongs to the pool. - /// \param p_object A pointer to the object to be checked. - /// \return true<\b> if it does, otherwise false - //************************************************************************* - //template - bool is_in_pool(const void* p_object) const - { - return is_item_in_pool((const char*)p_object); - } - - //************************************************************************* - /// Returns the maximum number of items in the pool. - //************************************************************************* - size_t max_size() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Returns the maximum number of items in the pool. - //************************************************************************* - size_t capacity() const - { - return MAX_SIZE; - } - - //************************************************************************* - /// Returns the number of free items in the pool. - //************************************************************************* - size_t available() const - { - return MAX_SIZE - items_allocated; - } - - //************************************************************************* - /// Returns the number of allocated items in the pool. - //************************************************************************* - size_t size() const - { - return items_allocated; - } - - //************************************************************************* - /// Checks to see if there are no allocated items in the pool. - /// \return true if there are none allocated. - //************************************************************************* - bool empty() const - { - return items_allocated == 0; - } - - //************************************************************************* - /// Checks to see if there are no free items in the pool. - /// \return true if there are none free. - //************************************************************************* - bool full() const - { - return items_allocated == MAX_SIZE; - } - - protected: - - //************************************************************************* - /// Constructor - //************************************************************************* - ipool(char* p_buffer_, uint32_t item_size_, uint32_t max_size_) - : p_buffer(p_buffer_), - p_next(p_buffer_), - items_allocated(0), - items_initialised(0), - ITEM_SIZE(item_size_), - MAX_SIZE(max_size_) - { - } - - private: - - //************************************************************************* - /// Allocate an item from the pool. - //************************************************************************* - char* allocate_item() - { - char* p_value = ETL_NULLPTR; - - // Any free space left? - if (items_allocated < MAX_SIZE) - { - // Initialise another one if necessary. - if (items_initialised < MAX_SIZE) - { - char* p = p_buffer + (items_initialised * ITEM_SIZE); - char* np = p + ITEM_SIZE; - *reinterpret_cast(p) = np; - ++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 = ETL_NULLPTR; - } - } - else - { - ETL_ASSERT(false, ETL_ERROR(pool_no_allocation)); - } - - return p_value; - } - - //************************************************************************* - /// Release an item back to the pool. - //************************************************************************* - void release_item(char* p_value) - { - // Does it belong to us? - ETL_ASSERT(is_item_in_pool(p_value), ETL_ERROR(pool_object_not_in_pool)); - - if (p_next != ETL_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; - } - - //************************************************************************* - /// Check if the item belongs to this pool. - //************************************************************************* - bool is_item_in_pool(const char* p) const - { - // Within the range of the buffer? - intptr_t distance = p - p_buffer; - 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; - } - - // Disable copy construction and assignment. - ipool(const ipool&); - ipool& operator =(const ipool&); - - char* p_buffer; - char* p_next; - - uint32_t items_allocated; ///< The number of items allocated. - uint32_t items_initialised; ///< The number of items initialised. - - const uint32_t ITEM_SIZE; ///< The size of allocated items. - const uint32_t MAX_SIZE; ///< The maximum number of objects that can be allocated. - - //************************************************************************* - /// Destructor. - //************************************************************************* -#if defined(ETL_POLYMORPHIC_POOL) || defined(ETL_POLYMORPHIC_CONTAINERS) - public: - virtual ~ipool() - { - } -#else - protected: - ~ipool() - { - } -#endif - }; - - //************************************************************************* - /// A templated abstract pool implementation that uses a fixed size pool. - ///\ingroup pool - //************************************************************************* - template - class generic_pool : public etl::ipool - { - public: - - static const size_t SIZE = SIZE_; - static const size_t ALIGNMENT = ALIGNMENT_; - static const size_t TYPE_SIZE = TYPE_SIZE_; - - //************************************************************************* - /// Constructor - //************************************************************************* - generic_pool() - : etl::ipool(reinterpret_cast(&buffer[0]), ELEMENT_SIZE, SIZE) - { - } - - //************************************************************************* - /// Allocate an object from the pool. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - /// Static asserts if the specified type is too large for the pool. - //************************************************************************* - template - U* allocate() - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::allocate(); - } - -#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE || defined(ETL_STLPORT) - //************************************************************************* - /// Allocate storage for an object from the pool and create with default. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - U* create() - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::create(); - } - - //************************************************************************* - /// Allocate storage for an object from the pool and create with 1 parameter. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - U* create(const T1& value1) - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::create(value1); - } - - //************************************************************************* - /// Allocate storage for an object from the pool and create with 2 parameters. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - U* create(const T1& value1, const T2& value2) - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::create(value1, value2); - } - - //************************************************************************* - /// Allocate storage for an object from the pool and create with 3 parameters. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - U* create(const T1& value1, const T2& value2, const T3& value3) - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::create(value1, value2, value3); - } - - //************************************************************************* - /// Allocate storage for an object from the pool and create with 4 parameters. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a null pointer is returned. - //************************************************************************* - template - U* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::create(value1, value2, value3, value4); - } -#else - //************************************************************************* - /// Emplace with variadic constructor parameters. - //************************************************************************* - template - U* create(Args&&... args) - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - return ipool::create(etl::forward(args)...); - } -#endif - - //************************************************************************* - /// Destroys the object. - /// Undefined behaviour if the pool does not contain a 'U'. - /// \param p_object A pointer to the object to be destroyed. - //************************************************************************* - template - void destroy(const U* const p_object) - { - ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - ETL_STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); - p_object->~U(); - ipool::release(p_object); - } - - private: - - // The pool element. - union Element - { - char* next; ///< Pointer to the next free element. - char value[TYPE_SIZE_]; ///< Storage for value type. - typename etl::type_with_alignment::type dummy; ///< Dummy item to get correct alignment. - }; - - ///< The memory for the pool of objects. - typename etl::aligned_storage::value>::type buffer[SIZE]; - - static const uint32_t ELEMENT_SIZE = sizeof(Element); - - // Should not be copied. - generic_pool(const generic_pool&); - generic_pool& operator =(const generic_pool&); - }; //************************************************************************* /// A templated pool implementation that uses a fixed size pool. @@ -712,17 +149,28 @@ namespace etl } #endif + //************************************************************************* + /// Releases the object. + /// Undefined behaviour if the pool does not contain a 'U' object derived from 'U'. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void release(const U* const p_object) + { + ETL_STATIC_ASSERT((etl::is_base_of::value), "Pool does not contain this type"); + base_t::template release(p_object); + } + //************************************************************************* /// Destroys the object. - /// Undefined behaviour if the pool does not contain a 'U'. + /// Undefined behaviour if the pool does not contain a 'U' object derived from 'U'. /// \param p_object A pointer to the object to be destroyed. //************************************************************************* template void destroy(const U* const p_object) { ETL_STATIC_ASSERT((etl::is_base_of::value), "Pool does not contain this type"); - p_object->~U(); - base_t::release(p_object); + base_t::template destroy(p_object); } private: @@ -733,7 +181,5 @@ namespace etl }; } -#undef ETL_FILE - #endif diff --git a/include/etl/reference_counted_object.h b/include/etl/reference_counted_object.h new file mode 100644 index 00000000..fd3687e7 --- /dev/null +++ b/include/etl/reference_counted_object.h @@ -0,0 +1,51 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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_REFERENCE_COUNTED_OBJECT_INCLUDED +#define ETL_REFERENCE_COUNTED_OBJECT_INCLUDED + +#include + +#include "platform.h" + +namespace etl +{ + //*************************************************************************** + class ireference_counted_object + { + public: + + virtual ~ireference_counted_object() {}; + virtual void set_reference_count(uint32_t value) = 0; + virtual void increment_reference_count() = 0; + ETL_NODISCARD virtual uint32_t decrement_reference_count() = 0; + ETL_NODISCARD virtual uint32_t get_reference_count() const = 0; + }; +} + +#endif diff --git a/include/etl/shared_message.h b/include/etl/shared_message.h new file mode 100644 index 00000000..030a666a --- /dev/null +++ b/include/etl/shared_message.h @@ -0,0 +1,137 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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_SHARED_MESSAGE_INCLUDED +#define ETL_SHARED_MESSAGE_INCLUDED + +#include "platform.h" +#include "message_pool.h" +#include "message.h" + +//***************************************************************************** +/// A wrapper for reference countable messages. +/// Contains pointers to a pool owner and a message defined with a ref count type. +/// See etl::message template. +//***************************************************************************** +namespace etl +{ + class shared_message + { + public: + + //************************************************************************* + /// Constructor + /// \param owner_ A reference to the owner pool. + /// \param pmessage A reference to the message allocated from the pool. + //************************************************************************* + shared_message(etl::message_pool& owner_, etl::ireference_counted_message& message_) + : p_message_owner(&owner_) + , p_message(&message_) + { + p_message->set_reference_count(1U); + } + + //************************************************************************* + /// Copy constructor + //************************************************************************* + shared_message(const shared_message& other) + : p_message_owner(other.p_message_owner) + , p_message(other.p_message) + { + p_message->increment_reference_count(); + } + + //************************************************************************* + /// Copy assignment operator + //************************************************************************* + shared_message& operator =(const shared_message& other) + { + if (&other != this) + { + // Deal with the current message. + if (p_message->decrement_reference_count() == 0U) + { + p_message_owner->destroy(p_message); + } + + // Copy over the new one. + p_message_owner = other.p_message_owner; + p_message = other.p_message; + p_message->increment_reference_count(); + } + + return *this; + } + + //************************************************************************* + /// Destructor + /// Returns the message back to the pool it it is the last copy. + //************************************************************************* + ~shared_message() + { + if (p_message->decrement_reference_count() == 0U) + { + p_message_owner->destroy(p_message); + } + } + + //************************************************************************* + /// Get a reference to the contained message. + //************************************************************************* + etl::imessage& get_message() + { + return *p_message; + } + + //************************************************************************* + /// Get a const reference to the contained message. + //************************************************************************* + const etl::imessage& get_message() const + { + return *p_message; + } + + //************************************************************************* + /// Get the current reference count for this pool message. + //************************************************************************* + uint32_t get_reference_count() const + { + return p_message->get_reference_count(); + } + + private: + + etl::message_pool* p_message_owner; + etl::ireference_counted_message* p_message; + }; +} + +#endif + diff --git a/include/etl/variant_pool.h b/include/etl/variant_pool.h index a0dac60a..a5dc59dd 100644 --- a/include/etl/variant_pool.h +++ b/include/etl/variant_pool.h @@ -54,55 +54,13 @@ SOFTWARE. #include #include "platform.h" -#include "error_handler.h" -#include "exception.h" -#include "largest.h" +#include "generic_pool.h" #include "type_traits.h" -#include "alignment.h" #include "static_assert.h" -#include "type_lookup.h" -#include "pool.h" - -#include "utility.h" - -#undef ETL_FILE -#define ETL_FILE "40" +#include "largest.h" namespace etl { - //*************************************************************************** - class variant_pool_exception : public etl::exception - { - public: - - variant_pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_) - : exception(reason_, file_name_, line_number_) - { - } - }; - - //*************************************************************************** - class variant_pool_cannot_create : public etl::variant_pool_exception - { - public: - - variant_pool_cannot_create(string_type file_name_, numeric_type line_number_) - : variant_pool_exception(ETL_ERROR_TEXT("variant_pool:cannot create", ETL_FILE"A"), file_name_, line_number_) - { - } - }; - - //*************************************************************************** - class variant_pool_did_not_create : public etl::variant_pool_exception - { - public: - - variant_pool_did_not_create(string_type file_name_, numeric_type line_number_) - : variant_pool_exception(ETL_ERROR_TEXT("variant_pool:did not create", ETL_FILE"B"), file_name_, line_number_) - { - } - }; - //*************************************************************************** template - class variant_pool + class variant_pool : public etl::generic_pool::size, + etl::largest::alignment, + MAX_SIZE_> { public: + typedef etl::generic_pool::size, + etl::largest::alignment, + MAX_SIZE_> base_t; + static const size_t MAX_SIZE = MAX_SIZE_; //************************************************************************* @@ -143,23 +107,7 @@ namespace etl { ETL_STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = ETL_NULLPTR; - - if (pool.full()) - { - ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); - } - else - { - p = pool.template allocate(); - - if (p != ETL_NULLPTR) - { - new (p) T(); - } - } - - return p; + return base_t::template create(); } //************************************************************************* @@ -170,23 +118,7 @@ namespace etl { ETL_STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = ETL_NULLPTR; - - if (pool.full()) - { - ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); - } - else - { - p = pool.template allocate(); - - if (p != ETL_NULLPTR) - { - new (p) T(p1); - } - } - - return p; + return base_t::template create(p1); } //************************************************************************* @@ -197,23 +129,7 @@ namespace etl { ETL_STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = ETL_NULLPTR; - - if (pool.full()) - { - ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); - } - else - { - p = pool.template allocate(); - - if (p != ETL_NULLPTR) - { - new (p) T(p1, p2); - } - } - - return p; + return base_t::template create(p1, p2); } //************************************************************************* @@ -224,23 +140,7 @@ namespace etl { ETL_STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = ETL_NULLPTR; - - if (pool.full()) - { - ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); - } - else - { - p = pool.template allocate(); - - if (p != ETL_NULLPTR) - { - new (p) T(p1, p2, p3); - } - } - - return p; + return base_t::template create(p1, p2, p3); } //************************************************************************* @@ -251,23 +151,7 @@ namespace etl { ETL_STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = ETL_NULLPTR; - - if (pool.full()) - { - ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); - } - else - { - p = pool.template allocate(); - - if (p != ETL_NULLPTR) - { - new (p) T(p1, p2, p3, p4); - } - } - - return p; + return base_t::template create(p1, p2, p3, p4); } #else //************************************************************************* @@ -278,23 +162,7 @@ namespace etl { ETL_STATIC_ASSERT((etl::is_one_of::value), "Unsupported type"); - T* p = ETL_NULLPTR; - - if (pool.full()) - { - ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); - } - else - { - p = pool.template allocate(); - - if (p != ETL_NULLPTR) - { - new (p) T(etl::forward(args)...); - } - } - - return p; + return base_t::template create(args...); } #endif @@ -302,40 +170,27 @@ namespace etl /// Destroys the object. //************************************************************************* template - bool destroy(const T* const p) + void destroy(const T* const p) { ETL_STATIC_ASSERT((etl::is_one_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value), "Invalid type"); + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value), "Invalid type"); - p->~T(); - - void* vp = reinterpret_cast(const_cast(p)); - - if (pool.is_in_pool(vp)) - { - pool.release(vp); - return true; - } - else - { - ETL_ASSERT(false, ETL_ERROR(variant_pool_did_not_create)); - return false; - } + base_t::destroy(p); } //************************************************************************* @@ -346,52 +201,11 @@ namespace etl return MAX_SIZE; } - //************************************************************************* - /// Returns the number of free items in the variant_pool. - //************************************************************************* - size_t available() const - { - return pool.available(); - } - - //************************************************************************* - /// Returns the number of allocated items in the variant_pool. - //************************************************************************* - size_t size() const - { - return pool.size(); - } - - //************************************************************************* - /// Checks to see if there are no allocated items in the variant_pool. - /// \return true if there are none allocated. - //************************************************************************* - bool empty() const - { - return pool.empty(); - } - - //************************************************************************* - /// Checks to see if there are no free items in the variant_pool. - /// \return true if there are none free. - //************************************************************************* - bool full() const - { - return pool.full(); - } - private: variant_pool(const variant_pool&); variant_pool& operator =(const variant_pool&); - - // The pool. - etl::generic_pool::size, - etl::largest::alignment, - MAX_SIZE> pool; }; } -#undef ETL_FILE - #endif diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index 54e90d5d..d5677937 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -199,9 +199,9 @@ namespace // The next line should result in a compile error. //Packet packet4(message4); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE2, packet2.get().message_id); - CHECK_EQUAL(MESSAGE3, packet3.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id()); + CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id()); CHECK(!static_cast(packet1.get()).moved); CHECK(!static_cast(packet2.get()).moved); @@ -225,8 +225,8 @@ namespace Packet packet1(message1); Packet packet2(std::move(message2)); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE2, packet2.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id()); CHECK(!static_cast(packet1.get()).moved); CHECK(static_cast(packet2.get()).moved); @@ -253,9 +253,9 @@ namespace // The next line should result in a compile error. //Packet packet4(message4); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE2, packet2.get().message_id); - CHECK_EQUAL(MESSAGE3, packet3.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id()); + CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id()); CHECK_EQUAL(1, static_cast(packet1.get()).x); CHECK_EQUAL(2.2, static_cast(packet2.get()).x); @@ -276,9 +276,9 @@ namespace CHECK_THROW(Packet packet4(static_cast(message4)), etl::unhandled_message_exception); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE2, packet2.get().message_id); - CHECK_EQUAL(MESSAGE3, packet3.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE2, packet2.get().get_message_id()); + CHECK_EQUAL(MESSAGE3, packet3.get().get_message_id()); CHECK_EQUAL(1, static_cast(packet1.get()).x); CHECK_EQUAL(2.2, static_cast(packet2.get()).x); @@ -294,8 +294,8 @@ namespace Packet packet1(message1); Packet packet2(packet1); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE1, packet2.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id()); CHECK(!static_cast(packet1.get()).moved); CHECK(!static_cast(packet2.get()).moved); @@ -316,8 +316,8 @@ namespace Packet packet1(message1); Packet packet2(std::move(Packet(message1))); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE1, packet2.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id()); CHECK(!static_cast(packet1.get()).moved); CHECK(static_cast(packet2.get()).moved); @@ -340,8 +340,8 @@ namespace packet2 = packet1; - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE1, packet2.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id()); CHECK(!static_cast(packet1.get()).moved); CHECK(!static_cast(packet2.get()).moved); @@ -364,8 +364,8 @@ namespace packet2 = std::move(packet1); - CHECK_EQUAL(MESSAGE1, packet1.get().message_id); - CHECK_EQUAL(MESSAGE1, packet2.get().message_id); + CHECK_EQUAL(MESSAGE1, packet1.get().get_message_id()); + CHECK_EQUAL(MESSAGE1, packet2.get().get_message_id()); CHECK(!static_cast(packet1.get()).moved); CHECK(static_cast(packet2.get()).moved); diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index 9a9e9013..8f2ae9f9 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -416,19 +416,19 @@ namespace Router2 r2; CHECK(r2.accepts(message1)); - CHECK(r2.accepts(message1.message_id)); + CHECK(r2.accepts(message1.get_message_id())); CHECK(r2.accepts(message2)); - CHECK(r2.accepts(message2.message_id)); + CHECK(r2.accepts(message2.get_message_id())); CHECK(!r2.accepts(message3)); - CHECK(!r2.accepts(message3.message_id)); + CHECK(!r2.accepts(message3.get_message_id())); CHECK(r2.accepts(message4)); - CHECK(r2.accepts(message4.message_id)); + CHECK(r2.accepts(message4.get_message_id())); CHECK(r2.accepts(message5)); - CHECK(r2.accepts(message5.message_id)); + CHECK(r2.accepts(message5.get_message_id())); } //************************************************************************* diff --git a/test/test_pool_message.cpp b/test/test_pool_message.cpp new file mode 100644 index 00000000..21fccbca --- /dev/null +++ b/test/test_pool_message.cpp @@ -0,0 +1,127 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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. +******************************************************************************/ + +#include "UnitTest++/UnitTest++.h" + +#include "etl/pool.h" +#include "etl/shared_message.h" +#include "etl/message_pool.h" +#include "etl/variant_pool.h" +#include "etl/message.h" +#include "etl/atomic.h" + +namespace +{ + struct Message1 : public etl::message<1, uint32_t> + { + }; + + SUITE(test_shared_message) + { + constexpr size_t POOL_SIZE = 2; + + etl::variant_pool vpool; + + etl::message_pool mp(vpool); + + //************************************************************************* + TEST(test_buffered) + { + etl::message_pool& mpool = mp; + + { + etl::shared_message* pbuffered_sm = nullptr; + + { + etl::shared_message sm(mpool, *mpool.create()); + uint32_t count1 = sm.get_reference_count(); + + pbuffered_sm = new etl::shared_message(sm); + //uint32_t count2 = sm.get_reference_count(); + //uint32_t count3 = pbuffered_sm->get_reference_count(); + + etl::shared_message sm2 = etl::shared_message(mpool, *mpool.create()); + uint32_t count4 = sm2.get_reference_count(); + + pbuffered_sm = pbuffered_sm; + } + + size_t ps1 = vpool.size(); + + //{ + // uint32_t count = pbuffered_sm->get_reference_count(); + // etl::message_id_t id = pbuffered_sm->get_message().get_message_id(); + //} + + size_t ps2 = vpool.size(); + + delete pbuffered_sm; + } + + size_t ps3 = vpool.size(); + + vpool.size(); + } + } + + ////************************************************************************* + //TEST(test_construct_and_destruct) + //{ + // etl::pool pool; + // etl::pool_chain<1> pool_chain; + + // pool_chain.add(pool); + + // etl::shared_message buffered_sm(pool_chain); + + // { + // etl::shared_message sm1(pool_chain, pool.create()); + // CHECK_EQUAL(1, sm1.get_reference_count()); + // CHECK_EQUAL(1, pool.size()); + // { + // etl::shared_message sm2(sm1); + // CHECK_EQUAL(1, sm1.get_reference_count()); + // CHECK_EQUAL(2, sm2.get_reference_count()); + // CHECK_EQUAL(1, pool.size()); + // { + // etl::shared_message sm3(pool_chain); + // sm3 = sm2; + // CHECK_EQUAL(1, sm1.get_reference_count()); + // CHECK_EQUAL(2, sm2.get_reference_count()); + // CHECK_EQUAL(3, sm3.get_reference_count()); + // CHECK_EQUAL(1, pool.size()); + + // } + // CHECK_EQUAL(1, pool.size()); + // } + // CHECK_EQUAL(1, pool.size()); + // } + // CHECK_EQUAL(0, pool.size()); + //} + +} diff --git a/test/test_variant_pool.cpp b/test/test_variant_pool.cpp index b3ce2a03..8634cca9 100644 --- a/test/test_variant_pool.cpp +++ b/test/test_variant_pool.cpp @@ -202,7 +202,7 @@ namespace CHECK(!variant_pool.empty()); CHECK(variant_pool.full()); - CHECK_THROW(variant_pool.create(), etl::variant_pool_cannot_create); + CHECK_THROW(variant_pool.create(), etl::pool_no_allocation); } //************************************************************************* @@ -309,7 +309,7 @@ namespace CHECK_NO_THROW(variant_pool1.destroy(p)); p = variant_pool2.create(); - CHECK_THROW(variant_pool1.destroy(p), etl::variant_pool_did_not_create); + CHECK_THROW(variant_pool1.destroy(p), etl::pool_object_not_in_pool); } }; } diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 31526554..2c83fe22 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1045,11 +1045,14 @@ + + + @@ -1079,6 +1082,7 @@ + @@ -1586,6 +1590,7 @@ + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 5200c57a..54827642 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -852,6 +852,18 @@ ETL\Containers\Generators + + ETL\Containers + + + ETL\Containers + + + ETL\Frameworks + + + ETL\Frameworks + @@ -1313,6 +1325,9 @@ Source Files + + Source Files +