Containers (STL-compatible) StateMachines MessageBus and more for Embedded Systems. See www.etlcpp.com
Diff: message_router.h
- Revision:
- 0:b47c2a7920c2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/message_router.h Fri Mar 16 16:34:18 2018 +0000 @@ -0,0 +1,2531 @@ +/****************************************************************************** +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. +******************************************************************************/ + +#if 0 +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +#endif + +//*************************************************************************** +// This file has been auto generated. Do not edit this file. +//*************************************************************************** + +//*************************************************************************** +// 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=<n> message_router_generator.h +// Where <n> 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 +// +// See generate.bat +//*************************************************************************** + +#ifndef __ETL_MESSAGE_ROUTER__ +#define __ETL_MESSAGE_ROUTER__ + +#include <stdint.h> + +#include "platform.h" +#include "message.h" +#include "message_types.h" +#include "alignment.h" +#include "error_handler.h" +#include "exception.h" +#include "largest.h" +#include "nullptr.h" + +#undef ETL_FILE +#define ETL_FILE "35" + +namespace etl +{ + //*************************************************************************** + /// Base exception class for message router + //*************************************************************************** + class message_router_exception : public etl::exception + { + public: + + message_router_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : etl::exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// Router id is out of the legal range. + //*************************************************************************** + class message_router_illegal_id : public etl::message_router_exception + { + public: + + message_router_illegal_id(string_type file_name_, numeric_type line_number_) + : message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + 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; + + //******************************************** + bool accepts(const etl::imessage& msg) const + { + return accepts(msg.message_id); + } + + //******************************************** + etl::message_router_id_t get_message_router_id() const + { + return message_router_id; + } + + //******************************************** + bool is_null_router() const + { + return (message_router_id == NULL_MESSAGE_ROUTER); + } + + //******************************************** + bool is_bus() const + { + return (message_router_id == MESSAGE_BUS); + } + + //******************************************** + void set_successor(imessage_router& successor_) + { + successor = &successor_; + } + + //******************************************** + imessage_router& get_successor() const + { + return *successor; + } + + //******************************************** + bool has_successor() const + { + return (successor != nullptr); + } + + enum + { + NULL_MESSAGE_ROUTER = 255, + MESSAGE_BUS = 254, + ALL_MESSAGE_ROUTERS = 253, + MAX_MESSAGE_ROUTER = 249 + }; + + protected: + + 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_) + { + } + + private: + + // Disabled. + imessage_router(const imessage_router&); + imessage_router& operator =(const imessage_router&); + + etl::imessage_router* successor; + + etl::message_router_id_t message_router_id; + }; + + //*************************************************************************** + /// This router can be used either as a sink for messages + /// or as a producer-only of messages such an interrupt routine. + //*************************************************************************** + class null_message_router : public imessage_router + { + public: + + null_message_router() + : imessage_router(imessage_router::NULL_MESSAGE_ROUTER) + { + } + + //******************************************** + void receive(const etl::imessage&) + { + } + + //******************************************** + void receive(etl::imessage_router&, const etl::imessage&) + { + } + + //******************************************** + bool accepts(etl::message_id_t) const + { + return false; + } + + //******************************************** + static null_message_router& instance() + { + static null_message_router nmr; + return nmr; + } + }; + + //*************************************************************************** + /// Send a message to a router. + /// Sets the 'sender' to etl::null_message_router type. + //*************************************************************************** + inline static void send_message(etl::imessage_router& destination, + const etl::imessage& message) + { + destination.receive(message); + } + + //*************************************************************************** + /// Send a message to a router. + //*************************************************************************** + 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 <typename TDerived, + typename T1, typename T2 = void, typename T3 = void, typename T4 = void, + typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, + typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void, + typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void> + class message_router : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break; + case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break; + case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break; + case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break; + case T15::ID: ::new (p) T15(static_cast<const T15&>(msg)); break; + case T16::ID: ::new (p) T16(static_cast<const T16&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const etl::message_id_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break; + case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break; + case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break; + case T14::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T14&>(msg)); break; + case T15::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T15&>(msg)); break; + case T16::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T16&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 15 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9, typename T10, typename T11, typename T12, + typename T13, typename T14, typename T15> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break; + case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break; + case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break; + case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break; + case T15::ID: ::new (p) T15(static_cast<const T15&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break; + case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break; + case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break; + case T14::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T14&>(msg)); break; + case T15::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T15&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 14 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9, typename T10, typename T11, typename T12, + typename T13, typename T14> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break; + case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break; + case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break; + case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break; + case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break; + case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break; + case T14::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T14&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 13 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9, typename T10, typename T11, typename T12, + typename T13> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break; + case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break; + case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break; + case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break; + case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 12 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9, typename T10, typename T11, typename T12> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break; + case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break; + case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 11 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9, typename T10, typename T11> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 10 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9, typename T10> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 9 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, + typename T9> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 8 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + 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: + + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 7 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6, T7>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (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; + } + } + }; + + //*************************************************************************** + // Specialisation for 6 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6> + class message_router<TDerived, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5, T6>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (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; + } + } + }; + + //*************************************************************************** + // Specialisation for 5 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4, + typename T5> + class message_router<TDerived, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4, T5>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4, T5>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (id) + { + case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 4 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3, typename T4> + class message_router<TDerived, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3, T4>::size, + ALIGNMENT = etl::largest<T1, T2, T3, T4>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (id) + { + case T1::ID: case T2::ID: case T3::ID: case T4::ID: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 3 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2, typename T3> + class message_router<TDerived, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2, T3>::size, + ALIGNMENT = etl::largest<T1, T2, T3>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (id) + { + case T1::ID: case T2::ID: case T3::ID: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 2 message types. + //*************************************************************************** + template <typename TDerived, + typename T1, typename T2> + class message_router<TDerived, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1, T2>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1, T2>::size, + ALIGNMENT = etl::largest<T1, T2>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (id) + { + case T1::ID: case T2::ID: + return true; break; + default: + return false; break; + } + } + }; + + //*************************************************************************** + // Specialisation for 1 message type. + //*************************************************************************** + template <typename TDerived, + typename T1> + class message_router<TDerived, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> + : public imessage_router + { + public: + + //********************************************** + class message_packet + { + public: + + //******************************************** + explicit message_packet(const etl::imessage& msg) + { + const size_t id = msg.message_id; + + void* p = data; + + switch (id) + { + case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break; + default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break; + } + } + + //******************************************** + template <typename T> + explicit message_packet(const T& msg) + { + STATIC_ASSERT((etl::is_one_of<T, T1>::value), "Unsupported type for this message packet"); + + void* p = data; + ::new (p) T(static_cast<const T&>(msg)); + } + + //******************************************** + ~message_packet() + { + static_cast<etl::imessage*>(data)->~imessage(); + } + + //******************************************** + etl::imessage& get() + { + return *static_cast<etl::imessage*>(data); + } + + //******************************************** + const etl::imessage& get() const + { + return *static_cast<const etl::imessage*>(data); + } + + enum + { + SIZE = etl::largest<T1>::size, + ALIGNMENT = etl::largest<T1>::alignment + }; + + private: + + typename etl::aligned_storage<SIZE, ALIGNMENT>::type data; + }; + + //********************************************** + 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)); + } + + //********************************************** + 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)); + } + + //********************************************** + void receive(const etl::imessage& msg) + { + receive(etl::null_message_router::instance(), msg); + } + + //********************************************** + void receive(etl::imessage_router& source, const etl::imessage& msg) + { + const size_t id = msg.message_id; + + switch (id) + { + case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break; + default: + { + if (has_successor()) + { + get_successor().receive(source, msg); + } + else + { + static_cast<TDerived*>(this)->on_receive_unknown(source, msg); + } + break; + } + } + } + + using imessage_router::accepts; + + //********************************************** + bool accepts(etl::message_id_t id) const + { + switch (id) + { + case T1::ID: + return true; break; + default: + return false; break; + } + } + }; +} + +#undef ETL_FILE + +#endif +