diff --git a/include/etl/message_router.h b/include/etl/message_router.h index 7073f38c..70a1607a 100644 --- a/include/etl/message_router.h +++ b/include/etl/message_router.h @@ -418,18 +418,28 @@ namespace etl message_router() : imessage_router(etl::imessage_router::MESSAGE_ROUTER) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::imessage_router& successor_) : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); } //********************************************** message_router(etl::message_router_id_t id_) : imessage_router(id_) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -437,6 +447,10 @@ namespace etl message_router(etl::message_router_id_t id_, etl::imessage_router& successor_) : imessage_router(id_, successor_) { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); } @@ -551,6 +565,106 @@ namespace etl } }; + //*************************************************************************** + // The definition for all message types. + //*************************************************************************** + template + class message_router : public imessage_router + { + public: + + using message_packet = etl::message_packet<>; + using message_types = etl::type_list<>; + + //********************************************** + message_router() + : imessage_router(etl::imessage_router::MESSAGE_ROUTER) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + } + + //********************************************** + message_router(etl::imessage_router& successor_) + : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + } + + //********************************************** + message_router(etl::message_router_id_t id_) + : imessage_router(id_) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + + 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_) + { + // CRTP validation: Derived must inherit from this exact specialization. + ETL_STATIC_ASSERT((etl::is_base_of, TDerived>::value), + "Mismatch in derived type: TDerived does not inherit from etl::message_router"); + + ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id)); + } + + //********************************************** + using etl::imessage_router::receive; + + void receive(const etl::imessage& msg) ETL_OVERRIDE + { + if (has_successor()) + { + get_successor().receive(msg); + } + } + + template ::value, int>::type = 0> + void receive(const TMessage& msg) + { +#include "etl/private/diagnostic_array_bounds_push.h" + if (has_successor()) + { + get_successor().receive(msg); + } +#include "etl/private/diagnostic_pop.h" + } + + //********************************************** + using imessage_router::accepts; + + bool accepts(etl::message_id_t id) const ETL_OVERRIDE + { + return false; + } + + //******************************************** + ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE + { + return false; + } + + //******************************************** + bool is_producer() const ETL_OVERRIDE + { + return true; + } + + //******************************************** + bool is_consumer() const ETL_OVERRIDE + { + return true; + } + }; + //*************************************************************************** /// Helper to turn etl::type_list into etl::tuple template diff --git a/test/test_message_router.cpp b/test/test_message_router.cpp index 53da2b6b..2413d067 100644 --- a/test/test_message_router.cpp +++ b/test/test_message_router.cpp @@ -49,6 +49,7 @@ namespace enum { + ROUTER0, ROUTER1, ROUTER2, ROUTER3 @@ -119,17 +120,26 @@ namespace Message5 message5; + //*************************************************************************** + // Router that handles no messages. + //*************************************************************************** + class Router0 : public etl::message_router + { + public: + + Router0() + : message_router(ROUTER0) + { + } + }; + //*************************************************************************** // Router that handles messages 1, 2, 3, 4 and 5 and returns nothing. // Created from a type list. //*************************************************************************** -#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION) using Router1Messages = etl::type_list; class Router1 : public etl::message_router_from_type_list_t -#else - class Router1 : public etl::message_router -#endif { public: @@ -384,6 +394,84 @@ namespace CHECK_EQUAL(4, r2.callback_count); } + //************************************************************************* + TEST(message_router_with_no_message_types) + { + Router0 r0; + Router1 r1; + Router2 r2; + + Message1 message1(r2); + Message2 message2(r2); + Message3 message3(r2); + Message4 message4(r2); + + r0.append_successor(r1); // All messages are passed to r1. + + CHECK_TRUE((etl::is_same>::value)); + + CHECK(!r0.is_null_router()); + CHECK(r0.is_producer()); + CHECK(r0.is_consumer()); + + r1.receive(message1); + CHECK_EQUAL(1, 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); + CHECK_EQUAL(1, r2.callback_count); + + r1.receive(message2); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(0, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(2, r2.callback_count); + + r1.receive(message3); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(0, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(3, r2.callback_count); + + r1.receive(message4); + CHECK_EQUAL(1, r1.message1_count); + CHECK_EQUAL(1, r1.message2_count); + CHECK_EQUAL(1, r1.message3_count); + CHECK_EQUAL(1, r1.message4_count); + CHECK_EQUAL(0, r1.message_unknown_count); + CHECK_EQUAL(4, r2.callback_count); + + //// Send from the null router. + //etl::send_message(r0, 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); + + //etl::send_message(r0, 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); + + //etl::send_message(r0, message3); + //CHECK_EQUAL(1, r2.message1_count); + //CHECK_EQUAL(1, r2.message2_count); + //CHECK_EQUAL(0, r2.message4_count); + //CHECK_EQUAL(1, r2.message_unknown_count); + + //etl::send_message(r0, message4); + //CHECK_EQUAL(1, r2.message1_count); + //CHECK_EQUAL(1, r2.message2_count); + //CHECK_EQUAL(1, r2.message4_count); + //CHECK_EQUAL(1, r2.message_unknown_count); + } + //************************************************************************* TEST(message_null_router) {