From 9f4fe86df9627e1e4313aeb58d639ddcc7b34c19 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 30 Nov 2017 16:56:22 +0000 Subject: [PATCH] Added 'successor' member to allow implementation 'Chain Of Responsibility' pattern. --- src/message_router.h | 577 +++++++++++++++++++++++++-------- src/message_router_generator.h | 77 ++++- test/test_message_router.cpp | 57 ++++ 3 files changed, 561 insertions(+), 150 deletions(-) diff --git a/src/message_router.h b/src/message_router.h index 397086cd..4c8744c2 100644 --- a/src/message_router.h +++ b/src/message_router.h @@ -38,12 +38,12 @@ SOFTWARE. // To generate to header file, run this at the command line. // Note: You will need Python and COG installed. // -// python -m cogapp -d -e -omessage_router.h -DHandlers= message_router_generator.h +// python -m cogapp -d -e -omessage_router.h -DHandlers= message_router_generator.h // Where is the number of messages to support. // // e.g. // To generate handlers for up to 16 messages... -// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h +// python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h // // See generate.bat //*************************************************************************** @@ -60,6 +60,7 @@ SOFTWARE. #include "error_handler.h" #include "exception.h" #include "largest.h" +#include "nullptr.h" #undef ETL_FILE #define ETL_FILE "35" @@ -126,6 +127,12 @@ namespace etl return (message_router_id == MESSAGE_BUS); } + //******************************************** + void set_successor(imessage_router& successor_) + { + successor = &successor_; + } + enum { NULL_MESSAGE_ROUTER = 255, @@ -136,11 +143,21 @@ namespace etl protected: - imessage_router(etl::message_router_id_t id) - : message_router_id(id) + imessage_router(etl::message_router_id_t id_) + : successor(nullptr), + message_router_id(id_) { } + imessage_router(etl::message_router_id_t id_, + imessage_router& successor_) + : successor(&successor_), + message_router_id(id_) + { + } + + etl::imessage_router* successor; + private: // Disabled. @@ -191,7 +208,7 @@ namespace etl /// Send a message to a router. /// Sets the 'sender' to etl::null_message_router type. //*************************************************************************** - inline static void send_message(etl::imessage_router& destination, + inline static void send_message(etl::imessage_router& destination, const etl::imessage& message) { destination.receive(message); @@ -200,20 +217,20 @@ namespace etl //*************************************************************************** /// Send a message to a router. //*************************************************************************** - inline static void send_message(etl::imessage_router& source, - etl::imessage_router& destination, + inline static void send_message(etl::imessage_router& source, + etl::imessage_router& destination, const etl::imessage& message) { destination.receive(source, message); } - + //*************************************************************************** // The definition for all 16 message types. //*************************************************************************** template class message_router : public imessage_router { @@ -293,10 +310,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -328,7 +352,18 @@ namespace etl case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T15::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T16::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -339,8 +374,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID: return true; break; default: return false; break; @@ -351,10 +386,10 @@ namespace etl //*************************************************************************** // Specialisation for 15 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -434,10 +469,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -468,7 +510,18 @@ namespace etl case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T15::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -479,8 +532,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: return true; break; default: return false; break; @@ -491,10 +544,10 @@ namespace etl //*************************************************************************** // Specialisation for 14 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -573,10 +626,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -606,7 +666,18 @@ namespace etl case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T14::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -617,8 +688,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: return true; break; default: return false; break; @@ -629,10 +700,10 @@ namespace etl //*************************************************************************** // Specialisation for 13 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -710,10 +781,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -742,7 +820,18 @@ namespace etl case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T13::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -753,8 +842,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: return true; break; default: return false; break; @@ -765,9 +854,9 @@ namespace etl //*************************************************************************** // Specialisation for 12 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -844,10 +933,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -875,7 +971,18 @@ namespace etl case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T12::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -886,8 +993,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: case T12::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: case T12::ID: return true; break; default: return false; break; @@ -898,9 +1005,9 @@ namespace etl //*************************************************************************** // Specialisation for 11 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -976,10 +1083,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1006,7 +1120,18 @@ namespace etl case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T11::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1017,8 +1142,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: case T11::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: case T11::ID: return true; break; default: return false; break; @@ -1029,9 +1154,9 @@ namespace etl //*************************************************************************** // Specialisation for 10 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1106,10 +1231,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1135,7 +1267,18 @@ namespace etl case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T10::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1146,8 +1289,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: case T10::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: case T10::ID: return true; break; default: return false; break; @@ -1158,9 +1301,9 @@ namespace etl //*************************************************************************** // Specialisation for 9 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1234,10 +1377,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1262,7 +1412,18 @@ namespace etl case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T9::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1273,8 +1434,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - case T9::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + case T9::ID: return true; break; default: return false; break; @@ -1285,8 +1446,8 @@ namespace etl //*************************************************************************** // Specialisation for 8 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1359,10 +1520,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1386,7 +1554,18 @@ namespace etl case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T8::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1397,8 +1576,8 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: - + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: + return true; break; default: return false; break; @@ -1409,8 +1588,8 @@ namespace etl //*************************************************************************** // Specialisation for 7 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1482,10 +1661,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1508,7 +1694,18 @@ namespace etl case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T7::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1519,7 +1716,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: return true; break; default: return false; break; @@ -1530,8 +1727,8 @@ namespace etl //*************************************************************************** // Specialisation for 6 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1602,10 +1799,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1627,7 +1831,18 @@ namespace etl case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T6::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1638,7 +1853,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: return true; break; default: return false; break; @@ -1649,8 +1864,8 @@ namespace etl //*************************************************************************** // Specialisation for 5 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1720,10 +1935,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1744,7 +1966,18 @@ namespace etl case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T5::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1755,7 +1988,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: return true; break; default: return false; break; @@ -1766,7 +1999,7 @@ namespace etl //*************************************************************************** // Specialisation for 4 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1835,10 +2068,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1858,7 +2098,18 @@ namespace etl case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T4::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1869,7 +2120,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: case T4::ID: + case T1::ID: case T2::ID: case T3::ID: case T4::ID: return true; break; default: return false; break; @@ -1880,7 +2131,7 @@ namespace etl //*************************************************************************** // Specialisation for 3 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -1948,10 +2199,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -1970,7 +2228,18 @@ namespace etl case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T3::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -1981,7 +2250,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: case T3::ID: + case T1::ID: case T2::ID: case T3::ID: return true; break; default: return false; break; @@ -1992,7 +2261,7 @@ namespace etl //*************************************************************************** // Specialisation for 2 message types. //*************************************************************************** - template class message_router : public imessage_router @@ -2059,10 +2328,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -2080,7 +2356,18 @@ namespace etl { case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; case T2::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -2091,7 +2378,7 @@ namespace etl { switch (id) { - case T1::ID: case T2::ID: + case T1::ID: case T2::ID: return true; break; default: return false; break; @@ -2102,7 +2389,7 @@ namespace etl //*************************************************************************** // Specialisation for 1 message type. //*************************************************************************** - template class message_router : public imessage_router @@ -2168,10 +2455,17 @@ namespace etl }; //********************************************** - message_router(etl::message_router_id_t id) - : imessage_router(id) + message_router(etl::message_router_id_t id_) + : imessage_router(id_) { - ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) + : imessage_router(id_, successor_) + { + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } //********************************************** @@ -2188,7 +2482,18 @@ namespace etl switch (id) { case T1::ID: static_cast(this)->on_receive(source, static_cast(msg)); break; - default: static_cast(this)->on_receive_unknown(source, msg); break; + default: + { + if (successor != nullptr) + { + successor->receive(source, msg); + } + else + { + static_cast(this)->on_receive_unknown(source, msg); + } + break; + } } } @@ -2199,7 +2504,7 @@ namespace etl { switch (id) { - case T1::ID: + case T1::ID: return true; break; default: return false; break; diff --git a/src/message_router_generator.h b/src/message_router_generator.h index 054cd5fb..8353ee48 100644 --- a/src/message_router_generator.h +++ b/src/message_router_generator.h @@ -72,6 +72,7 @@ cog.outl("//******************************************************************** #include "error_handler.h" #include "exception.h" #include "largest.h" +#include "nullptr.h" #undef ETL_FILE #define ETL_FILE "35" @@ -138,6 +139,12 @@ namespace etl return (message_router_id == MESSAGE_BUS); } + //******************************************** + void set_successor(imessage_router& successor_) + { + successor = &successor_; + } + enum { NULL_MESSAGE_ROUTER = 255, @@ -148,11 +155,21 @@ namespace etl protected: - imessage_router(etl::message_router_id_t id) - : message_router_id(id) + imessage_router(etl::message_router_id_t id_) + : successor(nullptr), + message_router_id(id_) { } + imessage_router(etl::message_router_id_t id_, + imessage_router& successor_) + : successor(&successor_), + message_router_id(id_) + { + } + + etl::imessage_router* successor; + private: // Disabled. @@ -313,10 +330,17 @@ 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(" message_router(etl::message_router_id_t id_)") + cog.outl(" : imessage_router(id_)") cog.outl(" {") - cog.outl(" ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));") + cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));") + cog.outl(" }") + cog.outl("") + cog.outl(" //**********************************************") + cog.outl(" message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)") + cog.outl(" : imessage_router(id_, successor_)") + cog.outl(" {") + cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));") cog.outl(" }") cog.outl("") cog.outl(" //**********************************************") @@ -336,9 +360,18 @@ namespace etl cog.out(" case T%d::ID:" % n) cog.out(" static_cast(this)->on_receive(source, static_cast(msg));" % n) cog.outl(" break;") - cog.out(" default:") - cog.out(" static_cast(this)->on_receive_unknown(source, msg);") - cog.outl(" break;") + cog.outl(" default:") + cog.outl(" {") + cog.outl(" if (successor != nullptr)") + cog.outl(" {") + cog.outl(" successor->receive(source, msg);") + cog.outl(" }") + cog.outl(" else") + cog.outl(" {") + cog.outl(" static_cast(this)->on_receive_unknown(source, msg);") + cog.outl(" }") + cog.outl(" break;") + cog.outl(" }") cog.outl(" }") cog.outl(" }") cog.outl("") @@ -469,10 +502,17 @@ 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(" message_router(etl::message_router_id_t id_)") + cog.outl(" : imessage_router(id_)") cog.outl(" {") - cog.outl(" ETL_ASSERT(id <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));") + cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));") + cog.outl(" }") + cog.outl("") + cog.outl(" //**********************************************") + cog.outl(" message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)") + cog.outl(" : imessage_router(id_, successor_)") + cog.outl(" {") + cog.outl(" ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));") cog.outl(" }") cog.outl("") cog.outl(" //**********************************************") @@ -492,9 +532,18 @@ namespace etl cog.out(" case T%d::ID:" % t) cog.out(" static_cast(this)->on_receive(source, static_cast(msg));" % t) cog.outl(" break;") - cog.out(" default:") - cog.out(" static_cast(this)->on_receive_unknown(source, msg);") - cog.outl(" break;") + cog.outl(" default:") + cog.outl(" {") + cog.outl(" if (successor != nullptr)") + cog.outl(" {") + cog.outl(" successor->receive(source, msg);") + cog.outl(" }") + cog.outl(" else") + cog.outl(" {") + cog.outl(" static_cast(this)->on_receive_unknown(source, msg);") + cog.outl(" }") + cog.outl(" break;") + cog.outl(" }") cog.outl(" }") cog.outl(" }") cog.outl("") diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index c15408fb..45598673 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -417,5 +417,62 @@ namespace CHECK_EQUAL(4, r1.callback_count); queue.pop(); } + + //========================================================================= + TEST(message_router_successor) + { + Router1 r1; + Router2 r2; + + r2.set_successor(r1); + + etl::send_message(r2, message1); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(0, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message2); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message3); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(0, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + + etl::send_message(r2, message4); + CHECK_EQUAL(1, r2.message1_count); + CHECK_EQUAL(1, r2.message2_count); + CHECK_EQUAL(1, r2.message4_count); + CHECK_EQUAL(0, r2.message_unknown_count); + + CHECK_EQUAL(0, r1.message1_count); + CHECK_EQUAL(0, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + } }; }