diff --git a/src/file_error_numbers.txt b/src/file_error_numbers.txt index 5cea1e44..b7d48536 100644 --- a/src/file_error_numbers.txt +++ b/src/file_error_numbers.txt @@ -34,4 +34,6 @@ 34 fsm 35 message_router 36 scheduler -37 task \ No newline at end of file +37 task +38 message +39 message_bus \ No newline at end of file diff --git a/src/fsm.h b/src/fsm.h index 54b84fff..b4dc0613 100644 --- a/src/fsm.h +++ b/src/fsm.h @@ -26,6 +26,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ +#if 0 +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +#endif + //*************************************************************************** // This file has been auto generated. Do not edit this file. //*************************************************************************** @@ -224,8 +228,9 @@ namespace etl //******************************************* /// Constructor. //******************************************* - fsm() - : p_state(nullptr) + fsm(etl::message_router_id_t id) + : imessage_router(id), + p_state(nullptr) { } diff --git a/src/fsm_generator.h b/src/fsm_generator.h index bec171a6..06e379d4 100644 --- a/src/fsm_generator.h +++ b/src/fsm_generator.h @@ -3,7 +3,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2017 jwellbelove @@ -234,8 +234,9 @@ namespace etl //******************************************* /// Constructor. //******************************************* - fsm() - : p_state(nullptr) + fsm(etl::message_router_id_t id) + : imessage_router(id), + p_state(nullptr) { } diff --git a/src/generate_fsm.bat b/src/generate_fsm.bat new file mode 100644 index 00000000..07c25ece --- /dev/null +++ b/src/generate_fsm.bat @@ -0,0 +1 @@ +python -m cogapp -d -e -ofsm.h -DHandlers=16 fsm_generator.h diff --git a/src/generate_message_router.bat b/src/generate_message_router.bat new file mode 100644 index 00000000..b30597fb --- /dev/null +++ b/src/generate_message_router.bat @@ -0,0 +1 @@ +python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h diff --git a/src/largest.h b/src/largest.h index 502eee3e..649d6eec 100644 --- a/src/largest.h +++ b/src/largest.h @@ -28,6 +28,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ +#if 0 +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +#endif + //*************************************************************************** // This file has been auto generated. Do not edit this file. //*************************************************************************** diff --git a/src/largest_generator.h b/src/largest_generator.h index c785bf5e..27464662 100644 --- a/src/largest_generator.h +++ b/src/largest_generator.h @@ -5,7 +5,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2014 jwellbelove diff --git a/src/message.h b/src/message.h new file mode 100644 index 00000000..ae260796 --- /dev/null +++ b/src/message.h @@ -0,0 +1,105 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://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_MESSAGE__ +#define __ETL_MESSAGE__ + +#include + +#include "error_handler.h" +#include "exception.h" +#include "message_types.h" + +#undef ETL_FILE +#define ETL_FILE "38" + +namespace etl +{ + //*************************************************************************** + class message_exception : public etl::exception + { + public: + + message_exception(string_type what, string_type file_name, numeric_type line_number) + : exception(what, file_name, line_number) + { + } + }; + + //*************************************************************************** + class unhandled_message_exception : public etl::message_exception + { + public: + + unhandled_message_exception(string_type file_name, numeric_type line_number) + : message_exception(ETL_ERROR_TEXT("message:unknown", ETL_FILE"A"), file_name, line_number) + { + } + }; + + //*************************************************************************** + class imessage + { + public: + + //******************************************** + virtual ~imessage() {} + + const etl::message_id_t message_id; + + protected: + + //******************************************** + imessage(etl::message_id_t id) + : message_id(id) + { + } + }; + + //*************************************************************************** + template + class message : public imessage + { + public: + + enum + { + ID = ID_ + }; + + //******************************************** + message() + : imessage(ID_) + { + } + }; +} + +#undef ETL_FILE + +#endif diff --git a/src/message_bus.h b/src/message_bus.h new file mode 100644 index 00000000..34623cbf --- /dev/null +++ b/src/message_bus.h @@ -0,0 +1,322 @@ +/****************************************************************************** +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_MESSAGE_BUS_ +#define __ETL_MESSAGE_BUS_ + +#include +#include + +#include "algorithm.h" +#include "vector.h" +#include "nullptr.h" +#include "error_handler.h" +#include "exception.h" +#include "message_types.h" +#include "message.h" +#include "message_router.h" + +#undef ETL_FILE +#define ETL_FILE "39" + +namespace etl +{ + //*************************************************************************** + /// Base exception class for message bus + //*************************************************************************** + class message_bus_exception : public etl::exception + { + public: + + message_bus_exception(string_type what, string_type file_name, numeric_type line_number) + : etl::exception(what, file_name, line_number) + { + } + }; + + //*************************************************************************** + /// Too many subscribers. + //*************************************************************************** + class message_bus_too_many_subscribers : public etl::message_bus_exception + { + public: + + message_bus_too_many_subscribers(string_type file_name, numeric_type line_number) + : message_bus_exception(ETL_ERROR_TEXT("message bus:too many subscribers", ETL_FILE"A"), file_name, line_number) + { + } + }; + + //*************************************************************************** + /// Duplicate router id. + //*************************************************************************** + class message_bus_duplicate_router_id : public etl::message_bus_exception + { + public: + + message_bus_duplicate_router_id(string_type file_name, numeric_type line_number) + : message_bus_exception(ETL_ERROR_TEXT("message bus:duplicate router id", ETL_FILE"B"), file_name, line_number) + { + } + }; + + //*************************************************************************** + /// Base for message bus + //*************************************************************************** + class imessage_bus : public etl::imessage_router + { + public: + + imessage_bus() + : imessage_router(etl::imessage_router::MESSAGE_BUS) + { + } + + using etl::imessage_router::receive; + + virtual void receive(etl::message_router_id_t destination_router_id, const etl::imessage& message) = 0; + virtual void receive(etl::imessage_router& source, etl::message_router_id_t destination_router_id, const etl::imessage& message) = 0; + virtual bool subscribe(etl::imessage_router& router) = 0; + virtual void unsubscribe(etl::message_router_id_t id) = 0; + + //******************************************* + void unsubscribe(etl::imessage_router& router) + { + unsubscribe(router.get_message_router_id()); + } + }; + + //*************************************************************************** + /// The message bus + //*************************************************************************** + template + class message_bus : public etl::imessage_bus + { + private: + + //******************************************* + // How to compare router ids. + //******************************************* + struct compare_router_id + { + bool operator()(etl::imessage_router* prouter, etl::message_router_id_t id) const + { + return prouter->get_message_router_id() > id; + } + + bool operator()(etl::message_router_id_t id, etl::imessage_router* prouter) const + { + return id > prouter->get_message_router_id(); + } + }; + + public: + + //******************************************* + /// Subscribe to the bus. + //******************************************* + bool subscribe(etl::imessage_router& router) + { + bool ok = true; + + // There's no point actually adding null routers. + if (router.get_message_router_id() != etl::imessage_router::NULL_MESSAGE_ROUTER) + { + ok = !router_list.full(); + + ETL_ASSERT(ok, ETL_ERROR(etl::message_bus_too_many_subscribers)); + + if (ok) + { + // Insert in order. + router_list_t::iterator irouter = std::lower_bound(router_list.begin(), + router_list.end(), + router.get_message_router_id(), + compare_router_id()); + + router_list.insert(irouter, &router); + } + } + + return ok; + } + + //******************************************* + /// Unsubscribe from the bus. + //******************************************* + using etl::imessage_bus::unsubscribe; + + void unsubscribe(etl::message_router_id_t id) + { + std::pair range = std::equal_range(router_list.begin(), + router_list.end(), + id, + compare_router_id()); + + while (range.first != range.second) + { + router_list.erase(range.first); + ++range.first; + } + } + + //******************************************* + void receive(const etl::imessage& message) + { + 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) + { + etl::null_message_router nmr; + receive(nmr, destination_router_id, message); + } + + //******************************************* + void receive(etl::imessage_router& source, + const etl::imessage& message) + { + receive(source, etl::imessage_router::ALL_MESSAGE_ROUTERS, message); + } + + //******************************************* + void receive(etl::imessage_router& source, + etl::message_router_id_t destination_router_id, + const etl::imessage& message) + { + switch (destination_router_id) + { + //***************************** + // Null message router. Should never get here as these routers can never be subscribed. + case etl::imessage_router::NULL_MESSAGE_ROUTER: + { + + break; + } + + //***************************** + // Broadcast to all routers. + case etl::imessage_router::ALL_MESSAGE_ROUTERS: + { + router_list_t::iterator irouter = router_list.begin(); + + // Broadcast to everyone. + while (irouter != router_list.end()) + { + etl::imessage_router& router = **irouter; + + if (router.get_message_router_id() == etl::imessage_router::MESSAGE_BUS) + { + // The router is actually a bus. + etl::imessage_bus& bus = static_cast(router); + + // So pass it on. + bus.receive(source, destination_router_id, message); + } + else if (router.accepts(message.message_id)) + { + router.receive(source, message); + } + + ++irouter; + } + + break; + } + + //***************************** + // Must be an addressed message. + default: + { + router_list_t::iterator irouter = router_list.begin(); + + // Do any message busses first. + // These are always at the start of the list. + while ((*irouter)->get_message_router_id() == etl::imessage_router::MESSAGE_BUS) + { + // The router is actually a bus. + etl::imessage_bus& bus = static_cast(**irouter); + + // So pass it on. + bus.receive(source, destination_router_id, message); + + ++irouter; + } + + // See if routers with the id exist. + std::pair range = std::equal_range(irouter, + router_list.end(), + destination_router_id, + compare_router_id()); + + // Call all of them. + while (range.first != range.second) + { + if ((*(range.first))->accepts(message.message_id)) + { + (*(range.first))->receive(source, message); + } + + ++range.first; + } + + break; + } + } + } + + using imessage_router::accepts; + + //******************************************* + /// Does this message bus accept the message id? + /// Yes!, it accepts everything! + //******************************************* + bool accepts(etl::message_id_t id) const + { + return true; + } + + //******************************************* + size_t size() const + { + return router_list.size(); + } + + private: + + typedef etl::vector router_list_t; + router_list_t router_list; + }; +} + +#undef ETL_FILE + +#endif diff --git a/src/message_router.h b/src/message_router.h index 2367a247..362a467c 100644 --- a/src/message_router.h +++ b/src/message_router.h @@ -3,7 +3,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2017 jwellbelove @@ -26,6 +26,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ +#if 0 +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +#endif + //*************************************************************************** // This file has been auto generated. Do not edit this file. //*************************************************************************** @@ -49,6 +53,8 @@ SOFTWARE. #include +#include "message.h" +#include "message_types.h" #include "alignment.h" #include "error_handler.h" #include "exception.h" @@ -59,80 +65,14 @@ SOFTWARE. namespace etl { - /// Allow alternative type for message id. -#if !defined(ETL_MESSAGE_ID_TYPE) - typedef uint_least8_t message_id_t; -#else - typedef ETL_MESSAGE_ID_TYPE message_id_t; -#endif - - //*************************************************************************** - class message_exception : public etl::exception - { - public: - - message_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - class unhandled_message_exception : public etl::message_exception - { - public: - - unhandled_message_exception(string_type file_name, numeric_type line_number) - : message_exception(ETL_ERROR_TEXT("message:unknown", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - class imessage - { - public: - - //******************************************** - virtual ~imessage() {} - - const etl::message_id_t message_id; - - protected: - - //******************************************** - imessage(etl::message_id_t id) - : message_id(id) - { - } - }; - - //*************************************************************************** - template - class message : public imessage - { - public: - - enum - { - ID = ID_ - }; - - //******************************************** - message() - : imessage(ID_) - { - } - }; - //*************************************************************************** class imessage_router { public: + virtual ~imessage_router() {} virtual void receive(const etl::imessage& message) = 0; virtual void receive(imessage_router& source, const etl::imessage& message) = 0; - virtual bool accepts(etl::message_id_t id) const = 0; //******************************************** @@ -142,11 +82,29 @@ namespace etl } //******************************************** - void send_message(imessage_router& destination, - const etl::imessage& message) + etl::message_router_id_t get_message_router_id() const { - destination.receive(*this, message); + return message_router_id; } + + static const message_router_id_t NULL_MESSAGE_ROUTER = 255; + static const message_router_id_t MESSAGE_BUS = 254; + static const message_router_id_t ALL_MESSAGE_ROUTERS = 253; + + protected: + + imessage_router(etl::message_router_id_t id) + : message_router_id(id) + { + } + + private: + + // Disabled. + imessage_router(const imessage_router&); + imessage_router& operator =(const imessage_router&); + + etl::message_router_id_t message_router_id; }; //*************************************************************************** @@ -157,6 +115,11 @@ namespace etl { public: + null_message_router() + : imessage_router(imessage_router::NULL_MESSAGE_ROUTER) + { + } + //******************************************** void receive(const etl::imessage& message) { @@ -172,6 +135,13 @@ namespace etl { return false; } + + //******************************************** + static null_message_router& instance() + { + static null_message_router nmr; + return nmr; + } }; //*************************************************************************** @@ -280,11 +250,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -415,11 +390,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -548,11 +528,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -679,11 +664,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -807,11 +797,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -933,11 +928,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1057,11 +1057,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1179,11 +1184,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1298,11 +1308,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1415,11 +1430,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1529,11 +1549,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1641,11 +1666,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1750,11 +1780,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1857,11 +1892,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -1962,11 +2002,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** @@ -2065,11 +2110,16 @@ namespace etl typename etl::aligned_storage::type data; }; + //********************************************** + message_router(etl::message_router_id_t id) + : imessage_router(id) + { + } + //********************************************** void receive(const etl::imessage& msg) { - etl::null_message_router nmr; - receive(nmr, msg); + receive(etl::null_message_router::instance(), msg); } //********************************************** diff --git a/src/message_router_generator.h b/src/message_router_generator.h index 0ac54884..c22143e3 100644 --- a/src/message_router_generator.h +++ b/src/message_router_generator.h @@ -3,7 +3,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2017 jwellbelove @@ -65,6 +65,8 @@ cog.outl("//******************************************************************** #include +#include "message.h" +#include "message_types.h" #include "alignment.h" #include "error_handler.h" #include "exception.h" @@ -75,80 +77,14 @@ cog.outl("//******************************************************************** namespace etl { - /// Allow alternative type for message id. -#if !defined(ETL_MESSAGE_ID_TYPE) - typedef uint_least8_t message_id_t; -#else - typedef ETL_MESSAGE_ID_TYPE message_id_t; -#endif - - //*************************************************************************** - class message_exception : public etl::exception - { - public: - - message_exception(string_type what, string_type file_name, numeric_type line_number) - : exception(what, file_name, line_number) - { - } - }; - - //*************************************************************************** - class unhandled_message_exception : public etl::message_exception - { - public: - - unhandled_message_exception(string_type file_name, numeric_type line_number) - : message_exception(ETL_ERROR_TEXT("message:unknown", ETL_FILE"A"), file_name, line_number) - { - } - }; - - //*************************************************************************** - class imessage - { - public: - - //******************************************** - virtual ~imessage() {} - - const etl::message_id_t message_id; - - protected: - - //******************************************** - imessage(etl::message_id_t id) - : message_id(id) - { - } - }; - - //*************************************************************************** - template - class message : public imessage - { - public: - - enum - { - ID = ID_ - }; - - //******************************************** - message() - : imessage(ID_) - { - } - }; - //*************************************************************************** class imessage_router { public: + virtual ~imessage_router() {} virtual void receive(const etl::imessage& message) = 0; virtual void receive(imessage_router& source, const etl::imessage& message) = 0; - virtual bool accepts(etl::message_id_t id) const = 0; //******************************************** @@ -158,11 +94,29 @@ namespace etl } //******************************************** - void send_message(imessage_router& destination, - const etl::imessage& message) + etl::message_router_id_t get_message_router_id() const { - destination.receive(*this, message); + return message_router_id; } + + static const message_router_id_t NULL_MESSAGE_ROUTER = 255; + static const message_router_id_t MESSAGE_BUS = 254; + static const message_router_id_t ALL_MESSAGE_ROUTERS = 253; + + protected: + + imessage_router(etl::message_router_id_t id) + : message_router_id(id) + { + } + + private: + + // Disabled. + imessage_router(const imessage_router&); + imessage_router& operator =(const imessage_router&); + + etl::message_router_id_t message_router_id; }; //*************************************************************************** @@ -173,6 +127,11 @@ namespace etl { public: + null_message_router() + : imessage_router(imessage_router::NULL_MESSAGE_ROUTER) + { + } + //******************************************** void receive(const etl::imessage& message) { @@ -188,6 +147,13 @@ namespace etl { return false; } + + //******************************************** + static null_message_router& instance() + { + static null_message_router nmr; + return nmr; + } }; //*************************************************************************** @@ -305,10 +271,15 @@ namespace etl cog.outl(" };") cog.outl("") cog.outl(" //**********************************************") + cog.outl(" message_router(etl::message_router_id_t id)") + cog.outl(" : imessage_router(id)") + cog.outl(" {") + cog.outl(" }") + cog.outl("") + cog.outl(" //**********************************************") cog.outl(" void receive(const etl::imessage& msg)") cog.outl(" {") - cog.outl(" etl::null_message_router nmr;") - cog.outl(" receive(nmr, msg);") + cog.outl(" receive(etl::null_message_router::instance(), msg);") cog.outl(" }") cog.outl("") cog.outl(" //**********************************************") @@ -455,10 +426,15 @@ namespace etl cog.outl(" };") cog.outl("") cog.outl(" //**********************************************") + cog.outl(" message_router(etl::message_router_id_t id)") + cog.outl(" : imessage_router(id)") + cog.outl(" {") + cog.outl(" }") + cog.outl("") + cog.outl(" //**********************************************") cog.outl(" void receive(const etl::imessage& msg)") cog.outl(" {") - cog.outl(" etl::null_message_router nmr;") - cog.outl(" receive(nmr, msg);") + cog.outl(" receive(etl::null_message_router::instance(), msg);") cog.outl(" }") cog.outl("") cog.outl(" //**********************************************") diff --git a/src/message_types.h b/src/message_types.h new file mode 100644 index 00000000..a049dae9 --- /dev/null +++ b/src/message_types.h @@ -0,0 +1,46 @@ +/****************************************************************************** +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_MESSAGE_DEFS__ +#define __ETL_MESSAGE_DEFS__ + +#include + +namespace etl +{ + /// Allow alternative type for message id. +#if !defined(ETL_MESSAGE_ID_TYPE) + typedef uint_least8_t message_id_t; +#else + typedef ETL_MESSAGE_ID_TYPE message_id_t; +#endif + + typedef uint_least8_t message_router_id_t; +} + +#endif diff --git a/src/smallest.h b/src/smallest.h index d90ac740..41025c2e 100644 --- a/src/smallest.h +++ b/src/smallest.h @@ -29,7 +29,7 @@ SOFTWARE. ******************************************************************************/ #if 0 -#error This header is a generator. Do not include. +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. #endif //*************************************************************************** diff --git a/src/smallest_generator.h b/src/smallest_generator.h index 6b74bf1c..1c99c09c 100644 --- a/src/smallest_generator.h +++ b/src/smallest_generator.h @@ -5,7 +5,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2014 jwellbelove diff --git a/src/type_traits.h b/src/type_traits.h index 4cce9267..c3a339e3 100644 --- a/src/type_traits.h +++ b/src/type_traits.h @@ -28,6 +28,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ +#if 0 +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +#endif + //*************************************************************************** // This file has been auto generated. Do not edit this file. //*************************************************************************** diff --git a/src/type_traits_generator.h b/src/type_traits_generator.h index 56cd91cd..68a2202d 100644 --- a/src/type_traits_generator.h +++ b/src/type_traits_generator.h @@ -5,7 +5,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2014 jwellbelove diff --git a/test/codeblocks/.gitignore b/test/codeblocks/.gitignore new file mode 100644 index 00000000..19c16877 --- /dev/null +++ b/test/codeblocks/.gitignore @@ -0,0 +1 @@ +random_*.csv diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index e8031a1d..bf9309b8 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,144 +2,19 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -147,134 +22,14 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -282,4 +37,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test_fsm.cpp b/test/test_fsm.cpp index 4a2d16f0..54b49d9a 100644 --- a/test/test_fsm.cpp +++ b/test/test_fsm.cpp @@ -36,6 +36,9 @@ SOFTWARE. namespace { + const etl::message_router_id_t MOTOR_CONTROL = 0; + + //*************************************************************************** // Events struct EventId @@ -322,7 +325,8 @@ namespace public: MotorControl() - : idle(common), + : fsm(MOTOR_CONTROL), + idle(common), running(common), windingDown(common), locked(common) diff --git a/test/test_message_bus.cpp b/test/test_message_bus.cpp new file mode 100644 index 00000000..1116caa3 --- /dev/null +++ b/test/test_message_bus.cpp @@ -0,0 +1,657 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://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. +******************************************************************************/ + +#include "UnitTest++.h" +#include "ExtraCheckMacros.h" + +#include "message_router.h" +#include "message_bus.h" +#include "queue.h" +#include "largest.h" +#include "packet.h" + +//*************************************************************************** +// The set of messages. +//*************************************************************************** +namespace +{ + enum + { + MESSAGE1, + MESSAGE2, + MESSAGE3, + MESSAGE4, + MESSAGE5 + }; + + enum + { + ROUTER1 = 1, + ROUTER2 = 2, + ROUTER3 = 3, + ROUTER4 = 4, + ROUTER5 = 5 + }; + + struct Message1 : public etl::message + { + }; + + struct Message2 : public etl::message + { + }; + + struct Message3 : public etl::message + { + int value[10]; + }; + + struct Message4 : public etl::message + { + }; + + struct Message5 : public etl::message + { + }; + + Message1 message1; + Message2 message2; + Message3 message3; + Message4 message4; + Message5 message5; + + //*************************************************************************** + // Router that handles messages 1, 2, 3, 4, 5. + //*************************************************************************** + class RouterA : public etl::message_router + { + public: + + RouterA(etl::message_router_id_t id) + : message_router(id), + message1_count(0), + message2_count(0), + message3_count(0), + message4_count(0), + message5_count(0), + message_unknown_count(0) + { + + } + + void on_receive(etl::imessage_router& sender, const Message1& msg) + { + ++message1_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message2& msg) + { + ++message2_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message3& msg) + { + ++message3_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message4& msg) + { + ++message4_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message5& msg) + { + ++message5_count; + } + + void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg) + { + ++message_unknown_count; + } + + int message1_count; + int message2_count; + int message3_count; + int message4_count; + int message5_count; + int message_unknown_count; + }; + + //*************************************************************************** + // Router that handles messages 1, 2, 4 and 5 and returns nothing. + //*************************************************************************** + class RouterB : public etl::message_router + { + public: + + RouterB(etl::message_router_id_t id) + : message_router(id), + message1_count(0), + message2_count(0), + message4_count(0), + message5_count(0), + message_unknown_count(0) + { + + } + + void on_receive(etl::imessage_router& sender, const Message1& msg) + { + ++message1_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message2& msg) + { + ++message2_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message4& msg) + { + ++message4_count; + etl::send_message(sender, message5); + } + + void on_receive(etl::imessage_router& sender, const Message5& msg) + { + ++message5_count; + } + + void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg) + { + ++message_unknown_count; + etl::send_message(sender, message5); + } + + int message1_count; + int message2_count; + int message4_count; + int message5_count; + int message_unknown_count; + }; + + etl::imessage_router* p_router; + etl::imessage_bus* p_bus; + + SUITE(test_message_router) + { + //========================================================================= + TEST(message_bus_subscribe_unsubscribe) + { + etl::message_bus<2> bus1; + + RouterA router1(0); + RouterB router2(1); + RouterA router3(2); + + CHECK_EQUAL(0, bus1.size()); + + CHECK_NO_THROW(bus1.subscribe(router1)); + CHECK_EQUAL(1, bus1.size()); + + CHECK_NO_THROW(bus1.subscribe(router2)); + CHECK_EQUAL(2, bus1.size()); + + CHECK_THROW(bus1.subscribe(router3), etl::message_bus_too_many_subscribers); + CHECK_EQUAL(2, bus1.size()); + + bus1.unsubscribe(router1); + CHECK_EQUAL(1, bus1.size()); + + // Erase router not in list. + bus1.unsubscribe(router3); + CHECK_EQUAL(1, bus1.size()); + + // Erase using id. + bus1.unsubscribe(router2.get_message_router_id()); + CHECK_EQUAL(0, bus1.size()); + + // Erase router from empty list. + bus1.unsubscribe(router2); + CHECK_EQUAL(0, bus1.size()); + } + + //========================================================================= + TEST(message_bus_broadcast) + { + etl::message_bus<2> bus1; + + RouterA router1(ROUTER1); + RouterB router2(ROUTER2); + RouterA sender(ROUTER3); + + bus1.subscribe(router1); + bus1.subscribe(router2); + + bus1.receive(sender, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(2, sender.message5_count); + + bus1.receive(sender, message2); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(1, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(4, sender.message5_count); + + bus1.receive(sender, message3); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(1, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(5, sender.message5_count); + + bus1.receive(sender, message4); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(1, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(1, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(1, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(7, sender.message5_count); + } + + //========================================================================= + TEST(message_bus_broadcast_as_router) + { + etl::message_bus<2> bus1; + + RouterA router1(ROUTER1); + RouterB router2(ROUTER2); + RouterA sender(ROUTER3); + + bus1.subscribe(router1); + bus1.subscribe(router2); + + // Reference to router sub-type + etl::imessage_router& irouter = bus1; + + irouter.receive(sender, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(2, sender.message5_count); + + irouter.receive(sender, message2); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(1, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(4, sender.message5_count); + + irouter.receive(sender, message3); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(1, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(5, sender.message5_count); + + irouter.receive(sender, message4); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(1, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(1, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(1, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(7, sender.message5_count); + } + + //========================================================================= + TEST(message_bus_addressed) + { + etl::message_bus<2> bus1; + + RouterA router1(ROUTER1); + RouterB router2(ROUTER2); + RouterA sender(ROUTER3); + + bus1.subscribe(router1); + bus1.subscribe(router2); + + bus1.receive(sender, ROUTER1, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(0, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(1, sender.message5_count); + + bus1.receive(sender, ROUTER2, message2); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(0, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(2, sender.message5_count); + + bus1.receive(sender, ROUTER1, message3); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(0, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(3, sender.message5_count); + + bus1.receive(sender, ROUTER2, message4); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(0, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(1, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(4, sender.message5_count); + + // Send to a router not subscribed to the bus. + bus1.receive(sender, ROUTER5, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(1, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(0, router2.message1_count); + CHECK_EQUAL(1, router2.message2_count); + CHECK_EQUAL(1, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(4, sender.message5_count); + } + + //========================================================================= + TEST(message_bus_addressed_duplicate_router_id) + { + etl::message_bus<3> bus1; + + RouterA router1(ROUTER1); + RouterB router2(ROUTER1); + RouterB router3(ROUTER2); + RouterA sender(ROUTER3); + + bus1.subscribe(router1); + bus1.subscribe(router2); + bus1.subscribe(router3); + + bus1.receive(sender, ROUTER1, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(0, router3.message1_count); + CHECK_EQUAL(0, router3.message2_count); + CHECK_EQUAL(0, router3.message4_count); + CHECK_EQUAL(0, router3.message5_count); + CHECK_EQUAL(0, router3.message_unknown_count); + + CHECK_EQUAL(2, sender.message5_count); + } + + //========================================================================= + TEST(message_bus_broad_cast_addressed_sub_bus) + { + etl::message_bus<3> bus1; + etl::message_bus<2> bus2; + + RouterA router1(ROUTER1); + RouterA router2(ROUTER2); + RouterA router3(ROUTER3); + RouterA router4(ROUTER4); + + RouterA sender(ROUTER5); + + bus1.subscribe(router1); + bus1.subscribe(router2); + bus1.subscribe(bus2); + + bus2.subscribe(router3); + bus2.subscribe(router4); + + // Broadcast to bus1 + bus1.receive(sender, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(1, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(1, router3.message1_count); + CHECK_EQUAL(0, router3.message2_count); + CHECK_EQUAL(0, router3.message4_count); + CHECK_EQUAL(0, router3.message5_count); + CHECK_EQUAL(0, router3.message_unknown_count); + + CHECK_EQUAL(1, router4.message1_count); + CHECK_EQUAL(0, router4.message2_count); + CHECK_EQUAL(0, router4.message4_count); + CHECK_EQUAL(0, router4.message5_count); + CHECK_EQUAL(0, router4.message_unknown_count); + + CHECK_EQUAL(4, sender.message5_count); + + // Addressed to ROUTER2 + bus1.receive(sender, ROUTER2, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(2, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(1, router3.message1_count); + CHECK_EQUAL(0, router3.message2_count); + CHECK_EQUAL(0, router3.message4_count); + CHECK_EQUAL(0, router3.message5_count); + CHECK_EQUAL(0, router3.message_unknown_count); + + CHECK_EQUAL(1, router4.message1_count); + CHECK_EQUAL(0, router4.message2_count); + CHECK_EQUAL(0, router4.message4_count); + CHECK_EQUAL(0, router4.message5_count); + CHECK_EQUAL(0, router4.message_unknown_count); + + CHECK_EQUAL(5, sender.message5_count); + + // Addressed to ROUTER3 via bus2 + bus1.receive(sender, ROUTER3, message1); + + CHECK_EQUAL(1, router1.message1_count); + CHECK_EQUAL(0, router1.message2_count); + CHECK_EQUAL(0, router1.message3_count); + CHECK_EQUAL(0, router1.message4_count); + CHECK_EQUAL(0, router1.message5_count); + CHECK_EQUAL(0, router1.message_unknown_count); + + CHECK_EQUAL(2, router2.message1_count); + CHECK_EQUAL(0, router2.message2_count); + CHECK_EQUAL(0, router2.message4_count); + CHECK_EQUAL(0, router2.message5_count); + CHECK_EQUAL(0, router2.message_unknown_count); + + CHECK_EQUAL(2, router3.message1_count); + CHECK_EQUAL(0, router3.message2_count); + CHECK_EQUAL(0, router3.message4_count); + CHECK_EQUAL(0, router3.message5_count); + CHECK_EQUAL(0, router3.message_unknown_count); + + CHECK_EQUAL(1, router4.message1_count); + CHECK_EQUAL(0, router4.message2_count); + CHECK_EQUAL(0, router4.message4_count); + CHECK_EQUAL(0, router4.message5_count); + CHECK_EQUAL(0, router4.message_unknown_count); + + CHECK_EQUAL(6, sender.message5_count); + } + }; +} diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index efe912fa..4af52cb3 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -48,6 +48,12 @@ namespace MESSAGE5 }; + enum + { + ROUTER1, + ROUTER2 + }; + struct Message1 : public etl::message { }; @@ -83,7 +89,8 @@ namespace public: Router1() - : message1_count(0), + : message_router(ROUTER1), + message1_count(0), message2_count(0), message3_count(0), message4_count(0), @@ -143,7 +150,8 @@ namespace public: Router2() - : message1_count(0), + : message_router(ROUTER2), + message1_count(0), message2_count(0), message4_count(0), message_unknown_count(0), diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 18257869..a6dd0367 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -131,6 +131,9 @@ + + + @@ -371,6 +374,7 @@ + @@ -421,6 +425,8 @@ + + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 641d1707..18e39962 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -462,6 +462,15 @@ ETL\Utilities\Generators + + ETL\Frameworks + + + ETL\Frameworks + + + ETL\Frameworks + @@ -797,6 +806,9 @@ Source Files + + Source Files + @@ -808,6 +820,12 @@ Resource Files + + Resource Files + + + Resource Files +