diff --git a/.gitignore b/.gitignore index 4fb22bb0..e52f3484 100644 --- a/.gitignore +++ b/.gitignore @@ -282,3 +282,5 @@ test/vs2019/multi_loop.csv temp/create_arduino_library.py examples/FunctionInterruptSimulation-Delegates/vs2019/.vs +*.db-shm +test/vs2019/.vs/etl/v16/Browse.VC.db-wal diff --git a/include/etl/atomic.h b/include/etl/atomic.h index 8e030291..1af2a01b 100644 --- a/include/etl/atomic.h +++ b/include/etl/atomic.h @@ -48,6 +48,7 @@ SOFTWARE. #define ETL_HAS_ATOMIC 1 #else #define ETL_HAS_ATOMIC 0 + #pragma message ("ETL atomics not supported") #endif #endif diff --git a/include/etl/deque.h b/include/etl/deque.h index 72bf84ef..b74baa55 100644 --- a/include/etl/deque.h +++ b/include/etl/deque.h @@ -206,8 +206,8 @@ namespace etl //************************************************************************* deque_base(size_t max_size_, size_t buffer_size_) : current_size(0), - CAPACITY(max_size_), - BUFFER_SIZE(buffer_size_) + CAPACITY(max_size_), + BUFFER_SIZE(buffer_size_) { } @@ -236,12 +236,12 @@ namespace etl typedef T value_type; typedef size_t size_type; - typedef T& reference; + typedef T& reference; typedef const T& const_reference; #if ETL_CPP11_SUPPORTED - typedef T&& rvalue_reference; + typedef T&& rvalue_reference; #endif - typedef T* pointer; + typedef T* pointer; typedef const T* const_pointer; typedef typename etl::iterator_traits::difference_type difference_type; @@ -284,8 +284,8 @@ namespace etl //*************************************************** iterator& operator =(const iterator& other) { - index = other.index; - p_deque = other.p_deque; + index = other.index; + p_deque = other.p_deque; p_buffer = other.p_buffer; return *this; @@ -491,7 +491,7 @@ namespace etl } difference_type index; - ideque* p_deque; + ideque* p_deque; pointer p_buffer; }; @@ -529,8 +529,8 @@ namespace etl //*************************************************** const_iterator& operator =(const const_iterator& other) { - index = other.index; - p_deque = other.p_deque; + index = other.index; + p_deque = other.p_deque; p_buffer = other.p_buffer; return *this; @@ -538,8 +538,8 @@ namespace etl const_iterator& operator =(const typename ideque::iterator& other) { - index = other.index; - p_deque = other.p_deque; + index = other.index; + p_deque = other.p_deque; p_buffer = other.p_buffer; return *this; @@ -733,7 +733,7 @@ namespace etl } difference_type index; - ideque* p_deque; + ideque* p_deque; pointer p_buffer; }; @@ -1095,7 +1095,7 @@ namespace etl p = etl::addressof(*_begin); ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _begin; + position = _begin; } else if (insert_position == end()) { @@ -1103,7 +1103,7 @@ namespace etl ++_end; ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _end - 1; + position = _end - 1; } else { @@ -1162,7 +1162,7 @@ namespace etl p = etl::addressof(*_begin); ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _begin; + position = _begin; } else if (insert_position == end()) { @@ -1170,7 +1170,7 @@ namespace etl ++_end; ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _end - 1; + position = _end - 1; } else { @@ -1227,7 +1227,7 @@ namespace etl p = etl::addressof(*_begin); ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _begin; + position = _begin; } else if (insert_position == end()) { @@ -1235,7 +1235,7 @@ namespace etl ++_end; ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _end - 1; + position = _end - 1; } else { @@ -1292,7 +1292,7 @@ namespace etl p = etl::addressof(*_begin); ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _begin; + position = _begin; } else if (insert_position == end()) { @@ -1300,7 +1300,7 @@ namespace etl ++_end; ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _end - 1; + position = _end - 1; } else { @@ -1357,7 +1357,7 @@ namespace etl p = etl::addressof(*_begin); ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _begin; + position = _begin; } else if (insert_position == end()) { @@ -1365,7 +1365,7 @@ namespace etl ++_end; ++current_size; ETL_INCREMENT_DEBUG_COUNT - position = _end - 1; + position = _end - 1; } else { @@ -2090,7 +2090,7 @@ namespace etl //************************************************************************* ideque(pointer p_buffer_, size_t max_size_, size_t buffer_size_) : deque_base(max_size_, buffer_size_), - p_buffer(p_buffer_) + p_buffer(p_buffer_) { } @@ -2101,7 +2101,7 @@ namespace etl { if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) { - current_size = 0; + current_size = 0; ETL_RESET_DEBUG_COUNT } else @@ -2113,7 +2113,7 @@ namespace etl } _begin = iterator(0, *this, p_buffer); - _end = iterator(0, *this, p_buffer); + _end = iterator(0, *this, p_buffer); } //************************************************************************* @@ -2124,7 +2124,7 @@ namespace etl p_buffer = p_buffer_; _begin = iterator(_begin.index, *this, p_buffer); - _end = iterator(_end.index, *this, p_buffer); + _end = iterator(_end.index, *this, p_buffer); } iterator _begin; ///Iterator to the _begin item in the deque. @@ -2233,7 +2233,7 @@ namespace etl (*_begin).~T(); --current_size; ETL_DECREMENT_DEBUG_COUNT - ++_begin; + ++_begin; } //********************************************************************* @@ -2319,9 +2319,9 @@ namespace etl public: typedef T value_type; - typedef T* pointer; + typedef T* pointer; typedef const T* const_pointer; - typedef T& reference; + typedef T& reference; typedef const T& const_reference; typedef size_t size_type; typedef typename etl::iterator_traits::difference_type difference_type; @@ -2507,9 +2507,9 @@ namespace etl bool operator <(const etl::ideque& lhs, const etl::ideque& rhs) { return etl::lexicographical_compare(lhs.begin(), - lhs.end(), - rhs.begin(), - rhs.end()); + lhs.end(), + rhs.begin(), + rhs.end()); } //*************************************************************************** diff --git a/include/etl/file_error_numbers.txt b/include/etl/file_error_numbers.txt index c8306cec..31eb6ffd 100644 --- a/include/etl/file_error_numbers.txt +++ b/include/etl/file_error_numbers.txt @@ -53,5 +53,5 @@ 53 indirect_vector 54 queue_spsc_locked 55 message_packet -56 circular_buffer -57 multi_loop +56 multi_range +57 reference_counted_message_pool diff --git a/include/etl/fixed_sized_memory_block_pool.h b/include/etl/fixed_sized_memory_block_pool.h new file mode 100644 index 00000000..6e35e5f6 --- /dev/null +++ b/include/etl/fixed_sized_memory_block_pool.h @@ -0,0 +1,65 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 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_FIXED_MEMORY_BLOCK_POOL_INCLUDED +#define ETL_FIXED_MEMORY_BLOCK_POOL_INCLUDED + +#include "platform.h" +#include "memory.h" +#include "pool.h" +#include "alignment.h" + +namespace etl +{ + //************************************************************************* + /// The fixed sized memory block pool. + /// The allocated memory blocks are all the same size. + //************************************************************************* + template + struct fixed_sized_memory_block_pool : public etl::ipool + { + public: + + fixed_sized_memory_block_pool() + : ipool(buffer.get_address(), BLOCK_SIZE, SIZE) + { + } + + private: + + // No copying allowed. + fixed_sized_memory_block_pool(const etl::fixed_sized_memory_block_pool&) ETL_DELETE; + fixed_sized_memory_block_pool& operator =(const etl::fixed_sized_memory_block_pool&) ETL_DELETE; + + typename etl::aligned_storage::type buffer; + }; +} + +#endif diff --git a/include/etl/fsm.h b/include/etl/fsm.h index 15bb636e..e079ee8a 100644 --- a/include/etl/fsm.h +++ b/include/etl/fsm.h @@ -224,8 +224,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) { } @@ -278,26 +280,6 @@ namespace etl } } - //******************************************* - /// Top level message handler for the FSM. - //******************************************* - void receive(const etl::imessage& message) ETL_OVERRIDE - { - static etl::null_message_router nmr; - receive(nmr, message); - } - - //******************************************* - /// Top level message handler for the FSM. - //******************************************* - void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, message); - } - } - //******************************************* /// Top level message handler for the FSM. //******************************************* @@ -448,7 +430,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) { @@ -513,7 +495,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) { @@ -577,7 +559,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) { @@ -640,7 +622,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) { @@ -701,7 +683,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) { @@ -761,7 +743,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) { @@ -820,7 +802,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) { @@ -878,7 +860,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) { @@ -934,7 +916,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) { @@ -989,7 +971,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) { @@ -1043,7 +1025,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) { @@ -1096,7 +1078,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) { @@ -1147,7 +1129,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) { @@ -1197,7 +1179,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) { @@ -1246,7 +1228,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) { @@ -1294,7 +1276,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 7aa987b9..47450831 100644 --- a/include/etl/generators/fsm_generator.h +++ b/include/etl/generators/fsm_generator.h @@ -236,8 +236,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) { } @@ -290,26 +292,6 @@ namespace etl } } - //******************************************* - /// Top level message handler for the FSM. - //******************************************* - void receive(const etl::imessage& message) ETL_OVERRIDE - { - static etl::null_message_router nmr; - receive(nmr, message); - } - - //******************************************* - /// Top level message handler for the FSM. - //******************************************* - void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, message); - } - } - //******************************************* /// Top level message handler for the FSM. //******************************************* @@ -468,7 +450,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(" {") @@ -545,7 +527,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 aa4b208b..f08f4292 100644 --- a/include/etl/generators/message_router_generator.h +++ b/include/etl/generators/message_router_generator.h @@ -67,6 +67,7 @@ cog.outl("//******************************************************************** #include "platform.h" #include "message.h" +#include "shared_message.h" #include "message_packet.h" #include "message_types.h" #include "alignment.h" @@ -107,6 +108,13 @@ namespace etl } }; + //*************************************************************************** + /// Forward declare null message router functionality. + //*************************************************************************** + class imessage_router; + + etl::imessage_router& get_null_message_router(); + //*************************************************************************** /// This is the base of all message routers. //*************************************************************************** @@ -115,18 +123,51 @@ namespace etl public: virtual ~imessage_router() {} - virtual void receive(const etl::imessage& message) = 0; virtual void receive(imessage_router& source, const etl::imessage& message) = 0; - virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) = 0; virtual bool accepts(etl::message_id_t id) const = 0; virtual bool is_null_router() const = 0; virtual bool is_producer() const = 0; virtual bool is_consumer() const = 0; + virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) + { + if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) + { + receive(source, message); + } + } + + //******************************************** + void receive(const etl::imessage& message) + { + receive(etl::get_null_message_router(), message); + } + + //******************************************** + virtual void receive(imessage_router& source, etl::shared_message shared_msg) + { + receive(source, shared_msg.get_message()); + } + + //******************************************** + void receive(etl::shared_message shared_msg) + { + receive(etl::get_null_message_router(), shared_msg); + } + + //******************************************** + void receive(imessage_router& source, etl::message_router_id_t destination_router_id, etl::shared_message shared_msg) + { + if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) + { + receive(source, shared_msg); + } + } + //******************************************** bool accepts(const etl::imessage& msg) const { - return accepts(msg.message_id); + return accepts(msg.get_message_id()); } //******************************************** @@ -164,15 +205,15 @@ namespace etl protected: imessage_router(etl::message_router_id_t id_) - : successor(ETL_NULLPTR), - message_router_id(id_) + : successor(ETL_NULLPTR) + , message_router_id(id_) { } imessage_router(etl::message_router_id_t id_, - imessage_router& successor_) - : successor(&successor_), - message_router_id(id_) + imessage_router& successor_) + : successor(&successor_) + , message_router_id(id_) { } @@ -200,21 +241,15 @@ namespace etl } //******************************************** - void receive(const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::receive; - //******************************************** void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE { } //******************************************** - void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::accepts; - //******************************************** bool accepts(etl::message_id_t) const ETL_OVERRIDE { return false; @@ -246,6 +281,13 @@ namespace etl } }; + //*********************************************** + /// null message router functionality. + inline etl::imessage_router& get_null_message_router() + { + return etl::null_message_router::instance(); + } + //*************************************************************************** /// This router can be used as a producer-only of messages, such an interrupt routine. //*************************************************************************** @@ -259,21 +301,15 @@ namespace etl } //******************************************** - void receive(const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::receive; - //******************************************** void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE { } //******************************************** - void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::accepts; - //******************************************** bool accepts(etl::message_id_t) const ETL_OVERRIDE { return false; @@ -359,24 +395,11 @@ namespace etl cog.outl(" }") cog.outl("") cog.outl(" //**********************************************") - cog.outl(" void receive(const etl::imessage& msg) ETL_OVERRIDE") - cog.outl(" {") - cog.outl(" receive(etl::null_message_router::instance(), msg);") - cog.outl(" }") + cog.outl(" using etl::imessage_router::receive;") cog.outl("") - cog.outl(" //**********************************************") - cog.outl(" void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE") - cog.outl(" {") - cog.outl(" if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))") - cog.outl(" {") - cog.outl(" receive(source, msg);") - cog.outl(" }") - cog.outl(" }") - cog.outl("") - 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(" {") @@ -399,9 +422,9 @@ namespace etl cog.outl(" }") cog.outl(" }") cog.outl("") + cog.outl(" //**********************************************") cog.outl(" using imessage_router::accepts;") cog.outl("") - cog.outl(" //**********************************************") cog.outl(" bool accepts(etl::message_id_t id) const ETL_OVERRIDE") cog.outl(" {") cog.outl(" switch (id)") @@ -492,24 +515,11 @@ namespace etl cog.outl(" }") cog.outl("") cog.outl(" //**********************************************") - cog.outl(" void receive(const etl::imessage& msg) ETL_OVERRIDE") - cog.outl(" {") - cog.outl(" receive(etl::null_message_router::instance(), msg);") - cog.outl(" }") + cog.outl(" using etl::imessage_router::receive;") cog.outl("") - cog.outl(" //**********************************************") - cog.outl(" void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE") - cog.outl(" {") - cog.outl(" if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))") - cog.outl(" {") - cog.outl(" receive(source, msg);") - cog.outl(" }") - cog.outl(" }") - cog.outl("") - 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(" {") @@ -532,9 +542,9 @@ namespace etl cog.outl(" }") cog.outl(" }") cog.outl("") + cog.outl(" //**********************************************") cog.outl(" using imessage_router::accepts;") cog.outl("") - cog.outl(" //**********************************************") cog.outl(" bool accepts(etl::message_id_t id) const ETL_OVERRIDE") cog.outl(" {") cog.outl(" switch (id)") diff --git a/include/etl/generators/variant_pool_generator.h b/include/etl/generators/variant_pool_generator.h index 236c94ef..cd93e5e3 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..91659e1a --- /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_CONSTANT uint32_t ELEMENT_SIZE = sizeof(Element); + + // Should not be copied. + generic_pool(const generic_pool&) ETL_DELETE; + generic_pool& operator =(const generic_pool&) ETL_DELETE; + }; +} + +#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/ireference_counted_message_pool.h b/include/etl/ireference_counted_message_pool.h new file mode 100644 index 00000000..ddacf969 --- /dev/null +++ b/include/etl/ireference_counted_message_pool.h @@ -0,0 +1,53 @@ +///\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_IREFERENCE_COUNTED_MESSAGE_POOL_INCLUDED +#define ETL_IREFERENCE_COUNTED_MESSAGE_POOL_INCLUDED + +#include "platform.h" + +namespace etl +{ + class ireference_counted_message; + + //*************************************************************************** + /// Interface for a reference counted message pool. + //*************************************************************************** + class ireference_counted_message_pool + { + public: + + virtual void release(const etl::ireference_counted_message* const pmsg) = 0; + virtual void release(const etl::ireference_counted_message& msg) = 0; + }; +} + +#endif + diff --git a/include/etl/memory.h b/include/etl/memory.h index 474cd449..abb3767b 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -1508,36 +1508,36 @@ namespace etl //***************************************************************************** // Global functions for unique_ptr //***************************************************************************** -template -bool operator ==(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) +template +bool operator ==(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) { return lhs.get() == rhs.get(); } //********************************* -template -bool operator <(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) +template +bool operator <(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) { return reinterpret_cast(lhs.get()) < reinterpret_cast(rhs.get()); } //********************************* -template -bool operator <=(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) +template +bool operator <=(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) { return !(rhs < lhs); } //********************************* -template -bool operator >(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) +template +bool operator >(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) { return (rhs < lhs); } //********************************* -template -bool operator >=(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) +template +bool operator >=(const etl::unique_ptr&lhs, const etl::unique_ptr& rhs) { return !(lhs < rhs); } @@ -1593,7 +1593,7 @@ namespace etl ///\ingroup memory //***************************************************************************** template - void create_value_at(T* p) + void create_value_at(T* p) { ::new (p) T(); } @@ -1603,7 +1603,7 @@ namespace etl ///\ingroup memory //***************************************************************************** template - void create_value_at(T* p, TCounter& count) + void create_value_at(T* p, TCounter& count) { ::new (p) T(); ++count; @@ -1614,7 +1614,7 @@ namespace etl ///\ingroup memory //***************************************************************************** template - void create_copy_at(T* p, const T& value) + void create_copy_at(T* p, const T& value) { ::new (p) T(value); } @@ -1900,6 +1900,16 @@ namespace etl } }; + //************************************************************************* + /// 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; + }; + //*************************************************************************** /// Declares an aligned buffer of N_OBJECTS x of size OBJECT_SIZE at alignment ALIGNMENT. ///\ingroup alignment diff --git a/include/etl/message.h b/include/etl/message.h index 02baf2d5..d718be16 100644 --- a/include/etl/message.h +++ b/include/etl/message.h @@ -63,44 +63,37 @@ namespace etl } }; + //*************************************************************************** + // Message interface. //*************************************************************************** class imessage { 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 + // Message type. + //*************************************************************************** + template class message : public imessage { public: - message() - : imessage(ID_) - { - } - enum { ID = ID_ }; + + ETL_NODISCARD etl::message_id_t get_message_id() const ETL_NOEXCEPT ETL_OVERRIDE + { + return ID; + } }; } diff --git a/include/etl/message_bus.h b/include/etl/message_bus.h index e981fe48..6254b702 100644 --- a/include/etl/message_bus.h +++ b/include/etl/message_bus.h @@ -147,13 +147,6 @@ namespace etl } } - //******************************************* - void receive(const etl::imessage& message) ETL_OVERRIDE - { - etl::null_message_router nmr; - receive(nmr, etl::imessage_router::ALL_MESSAGE_ROUTERS, message); - } - //******************************************* void receive(etl::message_router_id_t destination_router_id, const etl::imessage& message) @@ -187,7 +180,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 +206,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_router.h b/include/etl/message_router.h index c5b7ec1e..955ee8ea 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -55,6 +55,7 @@ SOFTWARE. #include "platform.h" #include "message.h" +#include "shared_message.h" #include "message_packet.h" #include "message_types.h" #include "alignment.h" @@ -95,6 +96,13 @@ namespace etl } }; + //*************************************************************************** + /// Forward declare null message router functionality. + //*************************************************************************** + class imessage_router; + + etl::imessage_router& get_null_message_router(); + //*************************************************************************** /// This is the base of all message routers. //*************************************************************************** @@ -103,18 +111,51 @@ namespace etl public: virtual ~imessage_router() {} - virtual void receive(const etl::imessage& message) = 0; virtual void receive(imessage_router& source, const etl::imessage& message) = 0; - virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) = 0; virtual bool accepts(etl::message_id_t id) const = 0; virtual bool is_null_router() const = 0; virtual bool is_producer() const = 0; virtual bool is_consumer() const = 0; + virtual void receive(imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) + { + if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) + { + receive(source, message); + } + } + + //******************************************** + void receive(const etl::imessage& message) + { + receive(etl::get_null_message_router(), message); + } + + //******************************************** + virtual void receive(imessage_router& source, etl::shared_message shared_msg) + { + receive(source, shared_msg.get_message()); + } + + //******************************************** + void receive(etl::shared_message shared_msg) + { + receive(etl::get_null_message_router(), shared_msg); + } + + //******************************************** + void receive(imessage_router& source, etl::message_router_id_t destination_router_id, etl::shared_message shared_msg) + { + if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) + { + receive(source, shared_msg); + } + } + //******************************************** bool accepts(const etl::imessage& msg) const { - return accepts(msg.message_id); + return accepts(msg.get_message_id()); } //******************************************** @@ -152,15 +193,15 @@ namespace etl protected: imessage_router(etl::message_router_id_t id_) - : successor(ETL_NULLPTR), - message_router_id(id_) + : successor(ETL_NULLPTR) + , message_router_id(id_) { } imessage_router(etl::message_router_id_t id_, - imessage_router& successor_) - : successor(&successor_), - message_router_id(id_) + imessage_router& successor_) + : successor(&successor_) + , message_router_id(id_) { } @@ -188,21 +229,15 @@ namespace etl } //******************************************** - void receive(const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::receive; - //******************************************** void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE { } //******************************************** - void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::accepts; - //******************************************** bool accepts(etl::message_id_t) const ETL_OVERRIDE { return false; @@ -234,6 +269,13 @@ namespace etl } }; + //*********************************************** + /// null message router functionality. + inline etl::imessage_router& get_null_message_router() + { + return etl::null_message_router::instance(); + } + //*************************************************************************** /// This router can be used as a producer-only of messages, such an interrupt routine. //*************************************************************************** @@ -247,21 +289,15 @@ namespace etl } //******************************************** - void receive(const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::receive; - //******************************************** void receive(etl::imessage_router&, const etl::imessage&) ETL_OVERRIDE { } //******************************************** - void receive(imessage_router&, etl::message_router_id_t, const etl::imessage&) ETL_OVERRIDE - { - } + using etl::imessage_router::accepts; - //******************************************** bool accepts(etl::message_id_t) const ETL_OVERRIDE { return false; @@ -334,24 +370,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -386,9 +409,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -450,24 +473,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -501,9 +511,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -565,24 +575,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -615,9 +612,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -679,24 +676,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -728,9 +712,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -791,24 +775,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -839,9 +810,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -902,24 +873,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -949,9 +907,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1012,24 +970,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1058,9 +1003,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1121,24 +1066,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1166,9 +1098,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1228,24 +1160,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1272,9 +1191,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1334,24 +1253,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1377,9 +1283,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1438,24 +1344,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1480,9 +1373,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1541,24 +1434,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1582,9 +1462,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1642,24 +1522,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1682,9 +1549,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1742,24 +1609,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1781,9 +1635,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1841,24 +1695,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1879,9 +1720,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) @@ -1939,24 +1780,11 @@ namespace etl } //********************************************** - void receive(const etl::imessage& msg) ETL_OVERRIDE - { - receive(etl::null_message_router::instance(), msg); - } + using etl::imessage_router::receive; - //********************************************** - void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& msg) ETL_OVERRIDE - { - if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS)) - { - receive(source, msg); - } - } - - //********************************************** 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) { @@ -1976,9 +1804,9 @@ namespace etl } } + //********************************************** using imessage_router::accepts; - //********************************************** bool accepts(etl::message_id_t id) const ETL_OVERRIDE { switch (id) diff --git a/include/etl/multi_array.h b/include/etl/multi_array.h index 0c1f9f06..cc0d84be 100644 --- a/include/etl/multi_array.h +++ b/include/etl/multi_array.h @@ -44,23 +44,23 @@ namespace etl namespace private_multi_array { - template + template struct multi_array_t { - using type = etl::array::type, D1>; - static constexpr size_t SIZE = D1; + using type = etl::array::type, TD1>; + static constexpr size_t SIZE = TD1; }; - template - struct multi_array_t + template + struct multi_array_t { - using type = etl::array; - static constexpr size_t SIZE = D1; + using type = etl::array; + static constexpr size_t SIZE = TD1; }; } - template - using multi_array = typename private_multi_array::multi_array_t::type; + template + using multi_array = typename private_multi_array::multi_array_t::type; #endif } diff --git a/include/etl/pool.h b/include/etl/pool.h index 5c7b83c1..547937c5 100644 --- a/include/etl/pool.h +++ b/include/etl/pool.h @@ -711,28 +711,37 @@ 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: // Should not be copied. - pool(const pool&); - pool& operator =(const pool&); + pool(const pool&) ETL_DELETE; + pool& operator =(const pool&) ETL_DELETE; }; } -#undef ETL_FILE - #endif diff --git a/include/etl/reference_counted_message.h b/include/etl/reference_counted_message.h new file mode 100644 index 00000000..94d15cd1 --- /dev/null +++ b/include/etl/reference_counted_message.h @@ -0,0 +1,195 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 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_MESSAGE_INCLUDED +#define ETL_REFERENCE_COUNTED_MESSAGE_INCLUDED + +#include + +#include "platform.h" +#include "message.h" +#include "atomic.h" +#include "reference_counted_object.h" +#include "ireference_counted_message_pool.h" + +namespace etl +{ + //*************************************************************************** + // Base class for all reference counted messages. + //*************************************************************************** + class ireference_counted_message + { + public: + + virtual ETL_NODISCARD const etl::imessage& get_message() const = 0; ///< Get a const reference to the message. + virtual ETL_NODISCARD etl::ireference_counter& get_reference_counter() = 0; ///< Get a reference to the reference counter. + virtual ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const = 0; ///< Get a const reference to the reference counter. + virtual void release() = 0; ///< Release back to the owner. + }; + + //*************************************************************************** + // Reference counted message type. + //*************************************************************************** + template + class reference_counted_message : public etl::ireference_counted_message + { + public: + + typedef TMessage message_type; + typedef TCounter counter_type; + + //*************************************************************************** + /// Constructor + /// \param msg The message to count. + //*************************************************************************** + reference_counted_message(const TMessage& msg_, etl::ireference_counted_message_pool& owner_) + : rc_object(msg_) + , owner(owner_) + { + } + + //*************************************************************************** + /// Get a const reference to the message. + /// \return A const reference to the message. + //*************************************************************************** + virtual ETL_NODISCARD const TMessage& get_message() const ETL_OVERRIDE + { + return rc_object.get_object(); + } + + //*************************************************************************** + /// Get a reference to the reference counter. + /// \return A reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD etl::ireference_counter& get_reference_counter() ETL_OVERRIDE + { + return rc_object.get_reference_counter(); + } + + //*************************************************************************** + /// Get a const reference to the reference counter. + /// \return A const reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const ETL_OVERRIDE + { + return rc_object.get_reference_counter(); + } + + //*************************************************************************** + /// Release back to the owner pool. + /// \return A reference to the owner pool. + //*************************************************************************** + virtual void release() ETL_OVERRIDE + { + owner.release(*this); + } + + private: + + etl::reference_counted_object rc_object; ///< The reference counted object. + etl::ireference_counted_message_pool& owner; ///< The pool that owns this object. + }; + + //*************************************************************************** + /// Persistent message type. + /// The message type will always have a reference count of 1. + /// \tparam TMessage The message type stored. + //*************************************************************************** + template + class persistent_message : virtual public etl::ireference_counted_message + { + public: + + typedef TMessage message_type; + + //*************************************************************************** + /// Constructor + /// \param msg The message to count. + //*************************************************************************** + persistent_message(const TMessage& msg_) + : rc_object(msg_) + { + } + + //*************************************************************************** + /// Get a const reference to the message. + /// \return A const reference to the message. + //*************************************************************************** + virtual ETL_NODISCARD const TMessage& get_message() const ETL_OVERRIDE + { + return rc_object.get_object(); + } + + //*************************************************************************** + /// Get a reference to the reference counter. + /// \return A reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD etl::ireference_counter& get_reference_counter() ETL_OVERRIDE + { + return rc_object.get_reference_counter(); + } + + //*************************************************************************** + /// Get a const reference to the reference counter. + /// \return A const reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD const etl::ireference_counter& get_reference_counter() const ETL_OVERRIDE + { + return rc_object.get_reference_counter(); + } + + //*************************************************************************** + /// Release back to the owner pool. + /// \return A reference to the owner pool. + //*************************************************************************** + virtual void release() ETL_OVERRIDE + { + // Do nothing. + } + + private: + + // This class must not be default contructed, copy constructed or assigned. + persistent_message() ETL_DELETE; + persistent_message(const persistent_message&) ETL_DELETE; + persistent_message& operator =(const persistent_message&) ETL_DELETE; + + etl::persistent_object rc_object; ///< The reference counted object. + }; + +#if ETL_CPP11_SUPPORTED && ETL_HAS_ATOMIC + //*************************************************************************** + /// Class for creating reference counted objects using an atomic counter. + /// \tparam TObject The type to be reference counted. + //*************************************************************************** + template + using atomic_counted_message = etl::reference_counted_message; +#endif +} + +#endif diff --git a/include/etl/reference_counted_message_pool.h b/include/etl/reference_counted_message_pool.h new file mode 100644 index 00000000..c5b2acc8 --- /dev/null +++ b/include/etl/reference_counted_message_pool.h @@ -0,0 +1,150 @@ +///\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_REFERENCE_COUNTED_MESSAGE_POOL_INCLUDED +#define ETL_REFERENCE_COUNTED_MESSAGE_POOL_INCLUDED + +#include "platform.h" +#include "message.h" +#include "ireference_counted_message_pool.h" +#include "reference_counted_message.h" +#include "static_assert.h" +#include "error_handler.h" +#include "utility.h" +#include "memory.h" + +#define ETL_FILE "57" + +namespace etl +{ + //*************************************************************************** + /// + //*************************************************************************** + class reference_counted_message_pool_allocation_exception : public etl::exception + { + public: + + reference_counted_message_pool_allocation_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// + //*************************************************************************** + class reference_counted_message_pool_allocation_failure : etl::reference_counted_message_pool_allocation_exception + { + public: + + reference_counted_message_pool_allocation_failure(string_type file_name_, numeric_type line_number_) + : reference_counted_message_pool_allocation_exception(ETL_ERROR_TEXT("reference_counted_message_pool:allocation failure", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// A pool for allocating reference counted messages. + //*************************************************************************** + template + class reference_counted_message_pool : public ireference_counted_message_pool + { + public: + + //************************************************************************* + /// Constructor + //************************************************************************* + reference_counted_message_pool(imemory_block_pool& memory_block_pool_) + : memory_block_pool(memory_block_pool_) + { + } + + //************************************************************************* + /// Allocate a reference counted message from the pool. + //************************************************************************* + template + etl::ireference_counted_message* allocate(const TMessage& message) + { + ETL_STATIC_ASSERT((etl::is_base_of::value), "Not a message type"); + + typedef etl::reference_counted_message rcm_t; + typedef rcm_t* prcm_t; + + prcm_t p = ETL_NULLPTR; + + if (sizeof(rcm_t) <= memory_block_pool.get_memory_block_size()) + { + p = static_cast(memory_block_pool.allocate_memory_block(sizeof(rcm_t))); + + if (p != ETL_NULLPTR) + { + ::new(p) rcm_t(message, *this); + } + } + + ETL_ASSERT((p != ETL_NULLPTR), ETL_ERROR(etl::message_pool_allocation_failure)); + + return p; + } + + //************************************************************************* + /// Destruct a message and send it back to the pool. + //************************************************************************* + void release(const etl::ireference_counted_message* const p_rcmessage) + { + if (p_rcmessage != ETL_NULLPTR) + { + p_rcmessage->~ireference_counted_message(); + memory_block_pool.release_memory_block(p_rcmessage); + } + } + + //************************************************************************* + /// Destruct a message and send it back to the pool. + //************************************************************************* + void release(const etl::ireference_counted_message& msg) + { + release(&msg); + } + + private: + + /// The raw memory block pool. + imemory_block_pool& memory_block_pool; + + // Should not be copied. + reference_counted_message_pool(const reference_counted_message_pool&) ETL_DELETE; + reference_counted_message_pool& operator =(const reference_counted_message_pool&) ETL_DELETE; + }; +} + +#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..36792082 --- /dev/null +++ b/include/etl/reference_counted_object.h @@ -0,0 +1,279 @@ +///****************************************************************************** +//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" +#include "atomic.h" + +namespace etl +{ + //*************************************************************************** + /// The base of all reference counters. + //*************************************************************************** + class ireference_counter + { + public: + + virtual ~ireference_counter() {}; + virtual void set_reference_count(int32_t value) = 0; + virtual void increment_reference_count() = 0; + ETL_NODISCARD virtual int32_t decrement_reference_count() = 0; + ETL_NODISCARD virtual int32_t get_reference_count() const = 0; + }; + + //*************************************************************************** + /// A specific type of reference counter. + //*************************************************************************** + template + class reference_counter : public ireference_counter + { + public: + + //*************************************************************************** + /// Constructor. + //*************************************************************************** + reference_counter() + : reference_count(0) + { + } + + //*************************************************************************** + /// Set the reference count. + //*************************************************************************** + virtual void set_reference_count(int32_t value) ETL_OVERRIDE + { + reference_count = value; + } + + //*************************************************************************** + /// Increment the reference count. + //*************************************************************************** + virtual void increment_reference_count() ETL_OVERRIDE + { + ++reference_count; + } + + //*************************************************************************** + /// Decrement the reference count. + //*************************************************************************** + ETL_NODISCARD virtual int32_t decrement_reference_count() ETL_OVERRIDE + { + assert(reference_count > 0); + + return int32_t(--reference_count); + } + + //*************************************************************************** + /// Get the current reference count. + //*************************************************************************** + ETL_NODISCARD virtual int32_t get_reference_count() const ETL_OVERRIDE + { + return int32_t(reference_count); + } + + private: + + TCounter reference_count; // The reference count object. + }; + + //*************************************************************************** + /// A null reference counter. + /// Always returns the reference count as 1, for persistent objects. + //*************************************************************************** + class null_reference_counter : public ireference_counter + { + public: + + //*************************************************************************** + /// Set the reference count. + //*************************************************************************** + virtual void set_reference_count(int32_t value) ETL_OVERRIDE + { + } + + //*************************************************************************** + /// Increment the reference count. + //*************************************************************************** + virtual void increment_reference_count() ETL_OVERRIDE + { + } + + //*************************************************************************** + /// Decrement the reference count. + //*************************************************************************** + ETL_NODISCARD virtual int32_t decrement_reference_count() ETL_OVERRIDE + { + return int32_t(1); + } + + //*************************************************************************** + /// Get the current reference count. + //*************************************************************************** + ETL_NODISCARD virtual int32_t get_reference_count() const ETL_OVERRIDE + { + return int32_t(1); + } + }; + + //*************************************************************************** + /// Base for all reference counted objects. + //*************************************************************************** + class ireference_counted_object + { + public: + + ETL_NODISCARD virtual ireference_counter& get_reference_counter() = 0; + ETL_NODISCARD virtual const ireference_counter& get_reference_counter() const = 0; + }; + + //*************************************************************************** + /// Class for creating reference counted objects. + /// \tparam TObject The type to be reference counted. + /// \tparam TCounter The type to use as the counter. + //*************************************************************************** + template + class reference_counted_object : public etl::ireference_counted_object + { + public: + + typedef TObject value_type; + typedef TCounter counter_type; + + //*************************************************************************** + /// Constructor. + //*************************************************************************** + reference_counted_object(const TObject& object_) + : object(object_) + { + } + + //*************************************************************************** + /// Get a const reference to the counted object. + //*************************************************************************** + ETL_NODISCARD const value_type& get_object() const + { + return object; + } + + //*************************************************************************** + /// Get a reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD ireference_counter& get_reference_counter() ETL_OVERRIDE + { + return reference_counter; + } + + //*************************************************************************** + /// Get a const reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD const ireference_counter& get_reference_counter() const ETL_OVERRIDE + { + return reference_counter; + } + + private: + + // This class must not be default contructed, copy constructed or assigned. + reference_counted_object() ETL_DELETE; + reference_counted_object(const reference_counted_object&) ETL_DELETE; + reference_counted_object& operator =(const reference_counted_object&) ETL_DELETE; + + const TObject object; ///< The object being reference counted. + etl::reference_counter reference_counter; ///< The reference counter. + }; + + //*************************************************************************** + /// Persistent message type. + /// The message type will always have a reference count of 1. + /// \tparam TObject The type stored in the object. + //*************************************************************************** + template + class persistent_object : public etl::ireference_counted_object + { + public: + + typedef TObject value_type; + + //*************************************************************************** + /// Constructor. + //*************************************************************************** + persistent_object(const TObject& object_) + : object(object_) + { + } + + //*************************************************************************** + /// Get a const reference to the counted object. + //*************************************************************************** + ETL_NODISCARD const value_type& get_object() const + { + return object; + } + + //*************************************************************************** + /// Get a reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD ireference_counter& get_reference_counter() ETL_OVERRIDE + { + return reference_counter; + } + + //*************************************************************************** + /// Get a const reference to the reference counter. + //*************************************************************************** + virtual ETL_NODISCARD const ireference_counter& get_reference_counter() const ETL_OVERRIDE + { + return reference_counter; + } + + private: + + // This class must not be default contructed, copy constructed or assigned. + persistent_object() ETL_DELETE; + persistent_object(const persistent_object&) ETL_DELETE; + persistent_object& operator =(const persistent_object&) ETL_DELETE; + + TObject object; ///< The object being reference counted. + etl::null_reference_counter reference_counter; ///< The reference counter. + }; + +#if ETL_CPP11_SUPPORTED && ETL_HAS_ATOMIC + //*************************************************************************** + /// Class for creating reference counted objects using an atomic counter. + /// \tparam TObject The type to be reference counted. + //*************************************************************************** + template + using atomic_counted_object = etl::reference_counted_object; +#endif +} + +#endif diff --git a/include/etl/shared_message.h b/include/etl/shared_message.h new file mode 100644 index 00000000..82b29b87 --- /dev/null +++ b/include/etl/shared_message.h @@ -0,0 +1,151 @@ +///\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 "utility.h" +#include "reference_counted_message.h" + +//***************************************************************************** +/// A wrapper for reference counted messages. +/// Contains pointers to a pool owner and a message defined with a ref count type. +//***************************************************************************** +namespace etl +{ + class shared_message + { + public: + + //************************************************************************* + /// Constructor + /// \param message A reference to the message allocated from the pool. + //************************************************************************* + shared_message(etl::ireference_counted_message& rcmessage_) + : p_rcmessage(&rcmessage_) + { + p_rcmessage->get_reference_counter().set_reference_count(1U); + } + + //************************************************************************* + /// Copy constructor + //************************************************************************* + shared_message(const shared_message& other) + : p_rcmessage(other.p_rcmessage) + { + p_rcmessage->get_reference_counter().increment_reference_count(); + } + + //************************************************************************* + /// Copy assignment operator + //************************************************************************* + shared_message& operator =(const shared_message& other) + { + if (&other != this) + { + // Deal with the current message. + if (p_rcmessage->get_reference_counter().decrement_reference_count() == 0U) + { + p_rcmessage->release(); + } + + // Copy over the new one. + p_rcmessage = other.p_rcmessage; + p_rcmessage->get_reference_counter().increment_reference_count(); + } + + return *this; + } + + //************************************************************************* + /// Destructor + /// Returns the message back to the pool it it is the last copy. + //************************************************************************* + ~shared_message() + { + if (p_rcmessage->get_reference_counter().decrement_reference_count() == 0U) + { + p_rcmessage->release(); + } + } + + //************************************************************************* + /// Get a const reference to the contained message. + //************************************************************************* + const etl::imessage& get_message() const + { + return p_rcmessage->get_message(); + } + + //************************************************************************* + /// Get the current reference count for this shared message. + //************************************************************************* + uint32_t get_reference_count() const + { + return p_rcmessage->get_reference_counter().get_reference_count(); + } + + private: + + shared_message() ETL_DELETE; + + etl::ireference_counted_message* p_rcmessage; + }; + + //***************************************************************************** + /// Make a shared_message from a pool. + /// \param owner The pool to allocate the reference counted message from. + /// \param message The message to reference count. + //***************************************************************************** + template + etl::shared_message make_shared_message(TPool& owner, const TMessage& message) + { + etl::ireference_counted_message* p_rcmessage = owner.allocate(message); + return etl::shared_message(*p_rcmessage); + } + +#if ETL_CPP11_SUPPORTED + //***************************************************************************** + /// Make a shared_message from a pool. + /// \param owner The pool to allocate the reference counted message from. + /// \param args The arguments to pass to the message constructor. + //***************************************************************************** + template + etl::shared_message make_shared_message(TPool& owner, TArgs&&... args) + { + etl::ireference_counted_message* p_rcmessage = owner.allocate(TMessage(etl::forward(args)...)); + return etl::shared_message(*p_rcmessage); + } +#endif +} + +#endif + diff --git a/include/etl/variant_pool.h b/include/etl/variant_pool.h index 6b0de79a..c572580c 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; + variant_pool(const variant_pool&) ETL_DELETE; + variant_pool& operator =(const variant_pool&) ETL_DELETE; }; } -#undef ETL_FILE - #endif diff --git a/test/test_message_packet.cpp b/test/test_message_packet.cpp index 6ed82775..5a49f69e 100644 --- a/test/test_message_packet.cpp +++ b/test/test_message_packet.cpp @@ -201,9 +201,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); @@ -227,8 +227,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); @@ -255,9 +255,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); @@ -278,9 +278,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); @@ -296,8 +296,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); @@ -318,8 +318,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); @@ -342,8 +342,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); @@ -366,8 +366,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..bfdb635d --- /dev/null +++ b/test/test_pool_message.cpp @@ -0,0 +1,221 @@ +/****************************************************************************** +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.h" +#include "etl/message_router.h" +#include "etl/atomic.h" +#include "etl/queue.h" +#include "etl/reference_counted_message_pool.h" + +namespace +{ + constexpr etl::message_id_t MESSAGE1 = 1U; + constexpr etl::message_id_t MESSAGE2 = 2U; + + constexpr etl::message_router_id_t ROUTER1 = 1U; + constexpr etl::message_router_id_t ROUTER2 = 2U; + + //************************************************************************* + struct Message1 : public etl::message + { + }; + + //************************************************************************* + struct Message2 : public etl::message + { + }; + + //************************************************************************* + struct Router1 : public etl::message_router + { + Router1() + : message_router(1) + { + + } + + void on_receive(etl::imessage_router& source, const Message1& message) + { + + } + + void on_receive_unknown(etl::imessage_router& source, const etl::imessage& message) + { + + } + }; + + //************************************************************************* + struct Router2 : public etl::message_router + { + Router2() + : message_router(2) + { + + } + + void on_receive(etl::imessage_router& source, const Message1& message) + { + + } + + void on_receive_unknown(etl::imessage_router& source, const etl::imessage& message) + { + + } + }; + + //************************************************************************* + struct Processor : public etl::shared_message_processor + { + Processor(Router& router_) + : shared_message_processor(router_) + { + } + + void receive(etl::shared_message message) + { + uint32_t count1 = message.get_reference_count(); + + smqueue.push(message); + + uint32_t count2 = message.get_reference_count(); + } + + void receive(etl::imessage_router& source, etl::shared_message message) + { + } + + void Process() + { + get_router().receive(smqueue.front().get_message()); + smqueue.pop(); + } + + etl::queue smqueue; + }; + + Router router; + Processor processor(router); + + 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(); + + processor.receive(sm); + + uint32_t count1b = sm.get_reference_count(); + + processor.Process(); + + uint32_t count1c = 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 7defeade..d57ad7b4 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1286,11 +1286,16 @@ + + + + + @@ -1323,7 +1328,12 @@ + + + + + @@ -1905,6 +1915,7 @@ + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 1a73bbcd..b47d81ae 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -909,6 +909,36 @@ ETL\Utilities + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + ETL\Frameworks + + + ETL\Frameworks + + + ETL\Frameworks + + + ETL\Frameworks + + + ETL\Containers + + + ETL\Containers + @@ -1445,6 +1475,9 @@ Source Files + + Source Files +