Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers message_router.h Source File

message_router.h

00001 /******************************************************************************
00002 The MIT License(MIT)
00003 
00004 Embedded Template Library.
00005 https://github.com/ETLCPP/etl
00006 https://www.etlcpp.com
00007 
00008 Copyright(c) 2017 jwellbelove
00009 
00010 Permission is hereby granted, free of charge, to any person obtaining a copy
00011 of this software and associated documentation files(the "Software"), to deal
00012 in the Software without restriction, including without limitation the rights
00013 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
00014 copies of the Software, and to permit persons to whom the Software is
00015 furnished to do so, subject to the following conditions :
00016 
00017 The above copyright notice and this permission notice shall be included in all
00018 copies or substantial portions of the Software.
00019 
00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00026 SOFTWARE.
00027 ******************************************************************************/
00028 
00029 #if 0
00030 #error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
00031 #endif
00032 
00033 //***************************************************************************
00034 // This file has been auto generated. Do not edit this file.
00035 //***************************************************************************
00036 
00037 //***************************************************************************
00038 // To generate to header file, run this at the command line.
00039 // Note: You will need Python and COG installed.
00040 //
00041 // python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h 
00042 // Where <n> is the number of messages to support.
00043 //
00044 // e.g.
00045 // To generate handlers for up to 16 messages...
00046 // python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h 
00047 //
00048 // See generate.bat
00049 //***************************************************************************
00050 
00051 #ifndef __ETL_MESSAGE_ROUTER__
00052 #define __ETL_MESSAGE_ROUTER__
00053 
00054 #include <stdint.h>
00055 
00056 #include "platform.h "
00057 #include "message.h"
00058 #include "message_types.h"
00059 #include "alignment.h "
00060 #include "error_handler.h "
00061 #include "exception.h "
00062 #include "largest.h "
00063 #include "nullptr.h "
00064 
00065 #undef ETL_FILE
00066 #define ETL_FILE "35"
00067 
00068 namespace etl
00069 {
00070   //***************************************************************************
00071   /// Base exception class for message router
00072   //***************************************************************************
00073   class message_router_exception : public etl::exception
00074   {
00075   public:
00076 
00077     message_router_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00078       : etl::exception(reason_, file_name_, line_number_)
00079     {
00080     }
00081   };
00082 
00083   //***************************************************************************
00084   /// Router id is out of the legal range.
00085   //***************************************************************************
00086   class message_router_illegal_id : public etl::message_router_exception
00087   {
00088   public:
00089 
00090     message_router_illegal_id(string_type file_name_, numeric_type line_number_)
00091       : message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_FILE"A"), file_name_, line_number_)
00092     {
00093     }
00094   };
00095 
00096   //***************************************************************************
00097   class imessage_router
00098   {
00099   public:
00100 
00101     virtual ~imessage_router() {}
00102     virtual void receive(const etl::imessage& message) = 0;
00103     virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
00104     virtual bool accepts(etl::message_id_t id) const = 0;
00105 
00106     //********************************************
00107     bool accepts(const etl::imessage& msg) const
00108     {
00109       return accepts(msg.message_id);
00110     }
00111 
00112     //********************************************
00113     etl::message_router_id_t get_message_router_id() const
00114     {
00115       return message_router_id;
00116     }
00117 
00118     //********************************************
00119     bool is_null_router() const
00120     {
00121       return (message_router_id == NULL_MESSAGE_ROUTER);
00122     }
00123 
00124     //********************************************
00125     bool is_bus() const
00126     {
00127       return (message_router_id == MESSAGE_BUS);
00128     }
00129 
00130     //********************************************
00131     void set_successor(imessage_router& successor_)
00132     {
00133       successor = &successor_;
00134     }
00135 
00136     //********************************************
00137     imessage_router& get_successor() const
00138     {
00139       return *successor;
00140     }
00141 
00142     //********************************************
00143     bool has_successor() const
00144     {
00145       return (successor != nullptr);
00146     }
00147 
00148     enum
00149     {
00150       NULL_MESSAGE_ROUTER = 255,
00151       MESSAGE_BUS         = 254,
00152       ALL_MESSAGE_ROUTERS = 253,
00153       MAX_MESSAGE_ROUTER  = 249
00154     };
00155 
00156   protected:
00157 
00158     imessage_router(etl::message_router_id_t id_)
00159       : successor(nullptr),
00160         message_router_id(id_)
00161     {
00162     }
00163 
00164     imessage_router(etl::message_router_id_t id_, 
00165                     imessage_router&         successor_)
00166       : successor(&successor_),
00167         message_router_id(id_)        
00168     {
00169     }
00170 
00171   private:
00172 
00173     // Disabled.
00174     imessage_router(const imessage_router&);
00175     imessage_router& operator =(const imessage_router&);
00176 
00177     etl::imessage_router* successor;
00178 
00179     etl::message_router_id_t  message_router_id;
00180   };
00181 
00182   //***************************************************************************
00183   /// This router can be used either as a sink for messages
00184   /// or as a producer-only of messages such an interrupt routine.
00185   //***************************************************************************
00186   class null_message_router : public imessage_router
00187   {
00188   public:
00189 
00190     null_message_router()
00191       : imessage_router(imessage_router::NULL_MESSAGE_ROUTER)
00192     {
00193     }
00194 
00195     //********************************************
00196     void receive(const etl::imessage&)
00197     {
00198     }
00199 
00200     //********************************************
00201     void receive(etl::imessage_router&, const etl::imessage&)
00202     {
00203     }
00204 
00205     //********************************************
00206     bool accepts(etl::message_id_t) const
00207     {
00208       return false;
00209     }
00210 
00211     //********************************************
00212     static null_message_router& instance()
00213     {
00214       static null_message_router nmr;
00215       return nmr;
00216     }
00217   };
00218 
00219   //***************************************************************************
00220   /// Send a message to a router.
00221   /// Sets the 'sender' to etl::null_message_router type.
00222   //***************************************************************************
00223   inline static void send_message(etl::imessage_router& destination, 
00224                                   const etl::imessage&  message)
00225   {
00226     destination.receive(message);
00227   }
00228 
00229   //***************************************************************************
00230   /// Send a message to a router.
00231   //***************************************************************************
00232   inline static void send_message(etl::imessage_router& source, 
00233                                   etl::imessage_router& destination, 
00234                                   const etl::imessage&  message)
00235   {
00236     destination.receive(source, message);
00237   }
00238   
00239   //***************************************************************************
00240   // The definition for all 16 message types.
00241   //***************************************************************************
00242   template <typename TDerived,
00243             typename T1, typename T2 = void, typename T3 = void, typename T4 = void, 
00244             typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void, 
00245             typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void, 
00246             typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
00247   class message_router  : public imessage_router
00248   {
00249   public:
00250 
00251     //**********************************************
00252     class message_packet
00253     {
00254     public:
00255 
00256       //********************************************
00257       explicit message_packet(const etl::imessage& msg)
00258       {
00259         const size_t id = msg.message_id;
00260 
00261         void* p = data;
00262 
00263         switch (id)
00264         {
00265           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
00266           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
00267           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
00268           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
00269           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
00270           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
00271           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
00272           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
00273           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
00274           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
00275           case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
00276           case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
00277           case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
00278           case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break;
00279           case T15::ID: ::new (p) T15(static_cast<const T15&>(msg)); break;
00280           case T16::ID: ::new (p) T16(static_cast<const T16&>(msg)); break;
00281           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
00282         }
00283       }
00284 
00285       //********************************************
00286       template <typename T>
00287       explicit message_packet(const T& msg)
00288       {
00289         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");
00290 
00291         void* p = data;
00292         ::new (p) T(static_cast<const T&>(msg));
00293       }
00294 
00295       //********************************************
00296       ~message_packet()
00297       {
00298         static_cast<etl::imessage*>(data)->~imessage();
00299       }
00300 
00301       //********************************************
00302       etl::imessage& get()
00303       {
00304         return *static_cast<etl::imessage*>(data);
00305       }
00306 
00307       //********************************************
00308       const etl::imessage& get() const
00309       {
00310         return *static_cast<const etl::imessage*>(data);
00311       }
00312 
00313       enum
00314       {
00315         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::size,
00316         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::alignment
00317       };
00318 
00319     private:
00320 
00321       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
00322     };
00323 
00324     //**********************************************
00325     message_router(etl::message_router_id_t id_)
00326       : imessage_router(id_)
00327     {
00328       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00329     }
00330 
00331     //**********************************************
00332     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
00333       : imessage_router(id_, successor_)
00334     {
00335       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00336     }
00337 
00338     //**********************************************
00339     void receive(const etl::imessage& msg)
00340     {
00341       receive(etl::null_message_router::instance(), msg);
00342     }
00343 
00344     //**********************************************
00345     void receive(etl::imessage_router& source, const etl::imessage& msg)
00346     {
00347       const etl::message_id_t id = msg.message_id;
00348 
00349       switch (id)
00350       {
00351         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
00352         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
00353         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
00354         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
00355         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
00356         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
00357         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
00358         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
00359         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
00360         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
00361         case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
00362         case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
00363         case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
00364         case T14::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
00365         case T15::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T15&>(msg)); break;
00366         case T16::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T16&>(msg)); break;
00367         default:
00368         {
00369            if (has_successor())
00370            {
00371              get_successor().receive(source, msg);
00372            }
00373            else
00374            {
00375              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
00376            }
00377            break;
00378         }
00379       }
00380     }
00381 
00382     using imessage_router::accepts;
00383 
00384     //**********************************************
00385     bool accepts(etl::message_id_t id) const
00386     {
00387       switch (id)
00388       {
00389         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
00390         case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: case T16::ID: 
00391           return true; break;
00392         default:
00393           return false; break;
00394       }
00395     }
00396   };
00397 
00398   //***************************************************************************
00399   // Specialisation for 15 message types.
00400   //***************************************************************************
00401   template <typename TDerived, 
00402             typename T1, typename T2, typename T3, typename T4, 
00403             typename T5, typename T6, typename T7, typename T8, 
00404             typename T9, typename T10, typename T11, typename T12, 
00405             typename T13, typename T14, typename T15>
00406   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void>
00407    : public imessage_router
00408   {
00409   public:
00410 
00411     //**********************************************
00412     class message_packet
00413     {
00414     public:
00415 
00416       //********************************************
00417       explicit message_packet(const etl::imessage& msg)
00418       {
00419         const size_t id = msg.message_id;
00420 
00421         void* p = data;
00422 
00423         switch (id)
00424         {
00425           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
00426           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
00427           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
00428           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
00429           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
00430           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
00431           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
00432           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
00433           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
00434           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
00435           case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
00436           case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
00437           case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
00438           case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break;
00439           case T15::ID: ::new (p) T15(static_cast<const T15&>(msg)); break;
00440           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
00441         }
00442       }
00443 
00444       //********************************************
00445       template <typename T>
00446       explicit message_packet(const T& msg)
00447       {
00448         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");
00449 
00450         void* p = data;
00451         ::new (p) T(static_cast<const T&>(msg));
00452       }
00453 
00454       //********************************************
00455       ~message_packet()
00456       {
00457         static_cast<etl::imessage*>(data)->~imessage();
00458       }
00459 
00460       //********************************************
00461       etl::imessage& get()
00462       {
00463         return *static_cast<etl::imessage*>(data);
00464       }
00465 
00466       //********************************************
00467       const etl::imessage& get() const
00468       {
00469         return *static_cast<const etl::imessage*>(data);
00470       }
00471 
00472       enum
00473       {
00474         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>::size,
00475         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>::alignment
00476       };
00477 
00478     private:
00479 
00480       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
00481     };
00482 
00483     //**********************************************
00484     message_router(etl::message_router_id_t id_)
00485       : imessage_router(id_)
00486     {
00487       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00488     }
00489 
00490     //**********************************************
00491     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
00492       : imessage_router(id_, successor_)
00493     {
00494       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00495     }
00496 
00497     //**********************************************
00498     void receive(const etl::imessage& msg)
00499     {
00500       receive(etl::null_message_router::instance(), msg);
00501     }
00502 
00503     //**********************************************
00504     void receive(etl::imessage_router& source, const etl::imessage& msg)
00505     {
00506       const size_t id = msg.message_id;
00507 
00508       switch (id)
00509       {
00510         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
00511         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
00512         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
00513         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
00514         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
00515         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
00516         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
00517         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
00518         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
00519         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
00520         case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
00521         case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
00522         case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
00523         case T14::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
00524         case T15::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T15&>(msg)); break;
00525         default:
00526         {
00527            if (has_successor())
00528            {
00529              get_successor().receive(source, msg);
00530            }
00531            else
00532            {
00533              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
00534            }
00535            break;
00536         }
00537       }
00538     }
00539 
00540     using imessage_router::accepts;
00541 
00542     //**********************************************
00543     bool accepts(etl::message_id_t id) const
00544     {
00545       switch (id)
00546       {
00547         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
00548         case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: case T15::ID: 
00549           return true; break;
00550         default:
00551           return false; break;
00552       }
00553     }
00554   };
00555 
00556   //***************************************************************************
00557   // Specialisation for 14 message types.
00558   //***************************************************************************
00559   template <typename TDerived, 
00560             typename T1, typename T2, typename T3, typename T4, 
00561             typename T5, typename T6, typename T7, typename T8, 
00562             typename T9, typename T10, typename T11, typename T12, 
00563             typename T13, typename T14>
00564   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void>
00565    : public imessage_router
00566   {
00567   public:
00568 
00569     //**********************************************
00570     class message_packet
00571     {
00572     public:
00573 
00574       //********************************************
00575       explicit message_packet(const etl::imessage& msg)
00576       {
00577         const size_t id = msg.message_id;
00578 
00579         void* p = data;
00580 
00581         switch (id)
00582         {
00583           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
00584           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
00585           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
00586           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
00587           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
00588           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
00589           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
00590           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
00591           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
00592           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
00593           case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
00594           case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
00595           case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
00596           case T14::ID: ::new (p) T14(static_cast<const T14&>(msg)); break;
00597           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
00598         }
00599       }
00600 
00601       //********************************************
00602       template <typename T>
00603       explicit message_packet(const T& msg)
00604       {
00605         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");
00606 
00607         void* p = data;
00608         ::new (p) T(static_cast<const T&>(msg));
00609       }
00610 
00611       //********************************************
00612       ~message_packet()
00613       {
00614         static_cast<etl::imessage*>(data)->~imessage();
00615       }
00616 
00617       //********************************************
00618       etl::imessage& get()
00619       {
00620         return *static_cast<etl::imessage*>(data);
00621       }
00622 
00623       //********************************************
00624       const etl::imessage& get() const
00625       {
00626         return *static_cast<const etl::imessage*>(data);
00627       }
00628 
00629       enum
00630       {
00631         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>::size,
00632         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>::alignment
00633       };
00634 
00635     private:
00636 
00637       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
00638     };
00639 
00640     //**********************************************
00641     message_router(etl::message_router_id_t id_)
00642       : imessage_router(id_)
00643     {
00644       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00645     }
00646 
00647     //**********************************************
00648     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
00649       : imessage_router(id_, successor_)
00650     {
00651       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00652     }
00653 
00654     //**********************************************
00655     void receive(const etl::imessage& msg)
00656     {
00657       receive(etl::null_message_router::instance(), msg);
00658     }
00659 
00660     //**********************************************
00661     void receive(etl::imessage_router& source, const etl::imessage& msg)
00662     {
00663       const size_t id = msg.message_id;
00664 
00665       switch (id)
00666       {
00667         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
00668         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
00669         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
00670         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
00671         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
00672         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
00673         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
00674         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
00675         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
00676         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
00677         case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
00678         case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
00679         case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
00680         case T14::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T14&>(msg)); break;
00681         default:
00682         {
00683            if (has_successor())
00684            {
00685              get_successor().receive(source, msg);
00686            }
00687            else
00688            {
00689              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
00690            }
00691            break;
00692         }
00693       }
00694     }
00695 
00696     using imessage_router::accepts;
00697 
00698     //**********************************************
00699     bool accepts(etl::message_id_t id) const
00700     {
00701       switch (id)
00702       {
00703         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
00704         case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: case T14::ID: 
00705           return true; break;
00706         default:
00707           return false; break;
00708       }
00709     }
00710   };
00711 
00712   //***************************************************************************
00713   // Specialisation for 13 message types.
00714   //***************************************************************************
00715   template <typename TDerived, 
00716             typename T1, typename T2, typename T3, typename T4, 
00717             typename T5, typename T6, typename T7, typename T8, 
00718             typename T9, typename T10, typename T11, typename T12, 
00719             typename T13>
00720   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void>
00721    : public imessage_router
00722   {
00723   public:
00724 
00725     //**********************************************
00726     class message_packet
00727     {
00728     public:
00729 
00730       //********************************************
00731       explicit message_packet(const etl::imessage& msg)
00732       {
00733         const size_t id = msg.message_id;
00734 
00735         void* p = data;
00736 
00737         switch (id)
00738         {
00739           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
00740           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
00741           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
00742           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
00743           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
00744           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
00745           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
00746           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
00747           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
00748           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
00749           case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
00750           case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
00751           case T13::ID: ::new (p) T13(static_cast<const T13&>(msg)); break;
00752           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
00753         }
00754       }
00755 
00756       //********************************************
00757       template <typename T>
00758       explicit message_packet(const T& msg)
00759       {
00760         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");
00761 
00762         void* p = data;
00763         ::new (p) T(static_cast<const T&>(msg));
00764       }
00765 
00766       //********************************************
00767       ~message_packet()
00768       {
00769         static_cast<etl::imessage*>(data)->~imessage();
00770       }
00771 
00772       //********************************************
00773       etl::imessage& get()
00774       {
00775         return *static_cast<etl::imessage*>(data);
00776       }
00777 
00778       //********************************************
00779       const etl::imessage& get() const
00780       {
00781         return *static_cast<const etl::imessage*>(data);
00782       }
00783 
00784       enum
00785       {
00786         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>::size,
00787         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>::alignment
00788       };
00789 
00790     private:
00791 
00792       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
00793     };
00794 
00795     //**********************************************
00796     message_router(etl::message_router_id_t id_)
00797       : imessage_router(id_)
00798     {
00799       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00800     }
00801 
00802     //**********************************************
00803     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
00804       : imessage_router(id_, successor_)
00805     {
00806       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00807     }
00808 
00809     //**********************************************
00810     void receive(const etl::imessage& msg)
00811     {
00812       receive(etl::null_message_router::instance(), msg);
00813     }
00814 
00815     //**********************************************
00816     void receive(etl::imessage_router& source, const etl::imessage& msg)
00817     {
00818       const size_t id = msg.message_id;
00819 
00820       switch (id)
00821       {
00822         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
00823         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
00824         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
00825         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
00826         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
00827         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
00828         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
00829         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
00830         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
00831         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
00832         case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
00833         case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
00834         case T13::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T13&>(msg)); break;
00835         default:
00836         {
00837            if (has_successor())
00838            {
00839              get_successor().receive(source, msg);
00840            }
00841            else
00842            {
00843              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
00844            }
00845            break;
00846         }
00847       }
00848     }
00849 
00850     using imessage_router::accepts;
00851 
00852     //**********************************************
00853     bool accepts(etl::message_id_t id) const
00854     {
00855       switch (id)
00856       {
00857         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
00858         case T9::ID: case T10::ID: case T11::ID: case T12::ID: case T13::ID: 
00859           return true; break;
00860         default:
00861           return false; break;
00862       }
00863     }
00864   };
00865 
00866   //***************************************************************************
00867   // Specialisation for 12 message types.
00868   //***************************************************************************
00869   template <typename TDerived, 
00870             typename T1, typename T2, typename T3, typename T4, 
00871             typename T5, typename T6, typename T7, typename T8, 
00872             typename T9, typename T10, typename T11, typename T12>
00873   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void>
00874    : public imessage_router
00875   {
00876   public:
00877 
00878     //**********************************************
00879     class message_packet
00880     {
00881     public:
00882 
00883       //********************************************
00884       explicit message_packet(const etl::imessage& msg)
00885       {
00886         const size_t id = msg.message_id;
00887 
00888         void* p = data;
00889 
00890         switch (id)
00891         {
00892           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
00893           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
00894           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
00895           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
00896           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
00897           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
00898           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
00899           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
00900           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
00901           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
00902           case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
00903           case T12::ID: ::new (p) T12(static_cast<const T12&>(msg)); break;
00904           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
00905         }
00906       }
00907 
00908       //********************************************
00909       template <typename T>
00910       explicit message_packet(const T& msg)
00911       {
00912         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");
00913 
00914         void* p = data;
00915         ::new (p) T(static_cast<const T&>(msg));
00916       }
00917 
00918       //********************************************
00919       ~message_packet()
00920       {
00921         static_cast<etl::imessage*>(data)->~imessage();
00922       }
00923 
00924       //********************************************
00925       etl::imessage& get()
00926       {
00927         return *static_cast<etl::imessage*>(data);
00928       }
00929 
00930       //********************************************
00931       const etl::imessage& get() const
00932       {
00933         return *static_cast<const etl::imessage*>(data);
00934       }
00935 
00936       enum
00937       {
00938         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>::size,
00939         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>::alignment
00940       };
00941 
00942     private:
00943 
00944       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
00945     };
00946 
00947     //**********************************************
00948     message_router(etl::message_router_id_t id_)
00949       : imessage_router(id_)
00950     {
00951       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00952     }
00953 
00954     //**********************************************
00955     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
00956       : imessage_router(id_, successor_)
00957     {
00958       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
00959     }
00960 
00961     //**********************************************
00962     void receive(const etl::imessage& msg)
00963     {
00964       receive(etl::null_message_router::instance(), msg);
00965     }
00966 
00967     //**********************************************
00968     void receive(etl::imessage_router& source, const etl::imessage& msg)
00969     {
00970       const size_t id = msg.message_id;
00971 
00972       switch (id)
00973       {
00974         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
00975         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
00976         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
00977         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
00978         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
00979         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
00980         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
00981         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
00982         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
00983         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
00984         case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
00985         case T12::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T12&>(msg)); break;
00986         default:
00987         {
00988            if (has_successor())
00989            {
00990              get_successor().receive(source, msg);
00991            }
00992            else
00993            {
00994              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
00995            }
00996            break;
00997         }
00998       }
00999     }
01000 
01001     using imessage_router::accepts;
01002 
01003     //**********************************************
01004     bool accepts(etl::message_id_t id) const
01005     {
01006       switch (id)
01007       {
01008         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
01009         case T9::ID: case T10::ID: case T11::ID: case T12::ID: 
01010           return true; break;
01011         default:
01012           return false; break;
01013       }
01014     }
01015   };
01016 
01017   //***************************************************************************
01018   // Specialisation for 11 message types.
01019   //***************************************************************************
01020   template <typename TDerived, 
01021             typename T1, typename T2, typename T3, typename T4, 
01022             typename T5, typename T6, typename T7, typename T8, 
01023             typename T9, typename T10, typename T11>
01024   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void>
01025    : public imessage_router
01026   {
01027   public:
01028 
01029     //**********************************************
01030     class message_packet
01031     {
01032     public:
01033 
01034       //********************************************
01035       explicit message_packet(const etl::imessage& msg)
01036       {
01037         const size_t id = msg.message_id;
01038 
01039         void* p = data;
01040 
01041         switch (id)
01042         {
01043           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01044           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01045           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01046           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01047           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01048           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
01049           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
01050           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
01051           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
01052           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
01053           case T11::ID: ::new (p) T11(static_cast<const T11&>(msg)); break;
01054           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01055         }
01056       }
01057 
01058       //********************************************
01059       template <typename T>
01060       explicit message_packet(const T& msg)
01061       {
01062         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");
01063 
01064         void* p = data;
01065         ::new (p) T(static_cast<const T&>(msg));
01066       }
01067 
01068       //********************************************
01069       ~message_packet()
01070       {
01071         static_cast<etl::imessage*>(data)->~imessage();
01072       }
01073 
01074       //********************************************
01075       etl::imessage& get()
01076       {
01077         return *static_cast<etl::imessage*>(data);
01078       }
01079 
01080       //********************************************
01081       const etl::imessage& get() const
01082       {
01083         return *static_cast<const etl::imessage*>(data);
01084       }
01085 
01086       enum
01087       {
01088         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::size,
01089         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>::alignment
01090       };
01091 
01092     private:
01093 
01094       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01095     };
01096 
01097     //**********************************************
01098     message_router(etl::message_router_id_t id_)
01099       : imessage_router(id_)
01100     {
01101       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01102     }
01103 
01104     //**********************************************
01105     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01106       : imessage_router(id_, successor_)
01107     {
01108       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01109     }
01110 
01111     //**********************************************
01112     void receive(const etl::imessage& msg)
01113     {
01114       receive(etl::null_message_router::instance(), msg);
01115     }
01116 
01117     //**********************************************
01118     void receive(etl::imessage_router& source, const etl::imessage& msg)
01119     {
01120       const size_t id = msg.message_id;
01121 
01122       switch (id)
01123       {
01124         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01125         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01126         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01127         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01128         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01129         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
01130         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
01131         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
01132         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
01133         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
01134         case T11::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T11&>(msg)); break;
01135         default:
01136         {
01137            if (has_successor())
01138            {
01139              get_successor().receive(source, msg);
01140            }
01141            else
01142            {
01143              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01144            }
01145            break;
01146         }
01147       }
01148     }
01149 
01150     using imessage_router::accepts;
01151 
01152     //**********************************************
01153     bool accepts(etl::message_id_t id) const
01154     {
01155       switch (id)
01156       {
01157         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
01158         case T9::ID: case T10::ID: case T11::ID: 
01159           return true; break;
01160         default:
01161           return false; break;
01162       }
01163     }
01164   };
01165 
01166   //***************************************************************************
01167   // Specialisation for 10 message types.
01168   //***************************************************************************
01169   template <typename TDerived, 
01170             typename T1, typename T2, typename T3, typename T4, 
01171             typename T5, typename T6, typename T7, typename T8, 
01172             typename T9, typename T10>
01173   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void>
01174    : public imessage_router
01175   {
01176   public:
01177 
01178     //**********************************************
01179     class message_packet
01180     {
01181     public:
01182 
01183       //********************************************
01184       explicit message_packet(const etl::imessage& msg)
01185       {
01186         const size_t id = msg.message_id;
01187 
01188         void* p = data;
01189 
01190         switch (id)
01191         {
01192           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01193           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01194           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01195           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01196           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01197           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
01198           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
01199           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
01200           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
01201           case T10::ID: ::new (p) T10(static_cast<const T10&>(msg)); break;
01202           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01203         }
01204       }
01205 
01206       //********************************************
01207       template <typename T>
01208       explicit message_packet(const T& msg)
01209       {
01210         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::value), "Unsupported type for this message packet");
01211 
01212         void* p = data;
01213         ::new (p) T(static_cast<const T&>(msg));
01214       }
01215 
01216       //********************************************
01217       ~message_packet()
01218       {
01219         static_cast<etl::imessage*>(data)->~imessage();
01220       }
01221 
01222       //********************************************
01223       etl::imessage& get()
01224       {
01225         return *static_cast<etl::imessage*>(data);
01226       }
01227 
01228       //********************************************
01229       const etl::imessage& get() const
01230       {
01231         return *static_cast<const etl::imessage*>(data);
01232       }
01233 
01234       enum
01235       {
01236         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::size,
01237         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::alignment
01238       };
01239 
01240     private:
01241 
01242       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01243     };
01244 
01245     //**********************************************
01246     message_router(etl::message_router_id_t id_)
01247       : imessage_router(id_)
01248     {
01249       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01250     }
01251 
01252     //**********************************************
01253     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01254       : imessage_router(id_, successor_)
01255     {
01256       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01257     }
01258 
01259     //**********************************************
01260     void receive(const etl::imessage& msg)
01261     {
01262       receive(etl::null_message_router::instance(), msg);
01263     }
01264 
01265     //**********************************************
01266     void receive(etl::imessage_router& source, const etl::imessage& msg)
01267     {
01268       const size_t id = msg.message_id;
01269 
01270       switch (id)
01271       {
01272         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01273         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01274         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01275         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01276         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01277         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
01278         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
01279         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
01280         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
01281         case T10::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T10&>(msg)); break;
01282         default:
01283         {
01284            if (has_successor())
01285            {
01286              get_successor().receive(source, msg);
01287            }
01288            else
01289            {
01290              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01291            }
01292            break;
01293         }
01294       }
01295     }
01296 
01297     using imessage_router::accepts;
01298 
01299     //**********************************************
01300     bool accepts(etl::message_id_t id) const
01301     {
01302       switch (id)
01303       {
01304         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
01305         case T9::ID: case T10::ID: 
01306           return true; break;
01307         default:
01308           return false; break;
01309       }
01310     }
01311   };
01312 
01313   //***************************************************************************
01314   // Specialisation for 9 message types.
01315   //***************************************************************************
01316   template <typename TDerived, 
01317             typename T1, typename T2, typename T3, typename T4, 
01318             typename T5, typename T6, typename T7, typename T8, 
01319             typename T9>
01320   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void>
01321    : public imessage_router
01322   {
01323   public:
01324 
01325     //**********************************************
01326     class message_packet
01327     {
01328     public:
01329 
01330       //********************************************
01331       explicit message_packet(const etl::imessage& msg)
01332       {
01333         const size_t id = msg.message_id;
01334 
01335         void* p = data;
01336 
01337         switch (id)
01338         {
01339           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01340           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01341           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01342           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01343           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01344           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
01345           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
01346           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
01347           case T9::ID: ::new (p) T9(static_cast<const T9&>(msg)); break;
01348           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01349         }
01350       }
01351 
01352       //********************************************
01353       template <typename T>
01354       explicit message_packet(const T& msg)
01355       {
01356         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8, T9>::value), "Unsupported type for this message packet");
01357 
01358         void* p = data;
01359         ::new (p) T(static_cast<const T&>(msg));
01360       }
01361 
01362       //********************************************
01363       ~message_packet()
01364       {
01365         static_cast<etl::imessage*>(data)->~imessage();
01366       }
01367 
01368       //********************************************
01369       etl::imessage& get()
01370       {
01371         return *static_cast<etl::imessage*>(data);
01372       }
01373 
01374       //********************************************
01375       const etl::imessage& get() const
01376       {
01377         return *static_cast<const etl::imessage*>(data);
01378       }
01379 
01380       enum
01381       {
01382         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9>::size,
01383         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8, T9>::alignment
01384       };
01385 
01386     private:
01387 
01388       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01389     };
01390 
01391     //**********************************************
01392     message_router(etl::message_router_id_t id_)
01393       : imessage_router(id_)
01394     {
01395       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01396     }
01397 
01398     //**********************************************
01399     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01400       : imessage_router(id_, successor_)
01401     {
01402       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01403     }
01404 
01405     //**********************************************
01406     void receive(const etl::imessage& msg)
01407     {
01408       receive(etl::null_message_router::instance(), msg);
01409     }
01410 
01411     //**********************************************
01412     void receive(etl::imessage_router& source, const etl::imessage& msg)
01413     {
01414       const size_t id = msg.message_id;
01415 
01416       switch (id)
01417       {
01418         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01419         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01420         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01421         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01422         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01423         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
01424         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
01425         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
01426         case T9::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T9&>(msg)); break;
01427         default:
01428         {
01429            if (has_successor())
01430            {
01431              get_successor().receive(source, msg);
01432            }
01433            else
01434            {
01435              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01436            }
01437            break;
01438         }
01439       }
01440     }
01441 
01442     using imessage_router::accepts;
01443 
01444     //**********************************************
01445     bool accepts(etl::message_id_t id) const
01446     {
01447       switch (id)
01448       {
01449         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
01450         case T9::ID: 
01451           return true; break;
01452         default:
01453           return false; break;
01454       }
01455     }
01456   };
01457 
01458   //***************************************************************************
01459   // Specialisation for 8 message types.
01460   //***************************************************************************
01461   template <typename TDerived, 
01462             typename T1, typename T2, typename T3, typename T4, 
01463             typename T5, typename T6, typename T7, typename T8>
01464   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void>
01465    : public imessage_router
01466   {
01467   public:
01468 
01469     //**********************************************
01470     class message_packet
01471     {
01472     public:
01473 
01474       //********************************************
01475       explicit message_packet(const etl::imessage& msg)
01476       {
01477         const size_t id = msg.message_id;
01478 
01479         void* p = data;
01480 
01481         switch (id)
01482         {
01483           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01484           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01485           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01486           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01487           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01488           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
01489           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
01490           case T8::ID: ::new (p) T8(static_cast<const T8&>(msg)); break;
01491           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01492         }
01493       }
01494 
01495       //********************************************
01496       template <typename T>
01497       explicit message_packet(const T& msg)
01498       {
01499         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7, T8>::value), "Unsupported type for this message packet");
01500 
01501         void* p = data;
01502         ::new (p) T(static_cast<const T&>(msg));
01503       }
01504 
01505       //********************************************
01506       ~message_packet()
01507       {
01508         static_cast<etl::imessage*>(data)->~imessage();
01509       }
01510 
01511       //********************************************
01512       etl::imessage& get()
01513       {
01514         return *static_cast<etl::imessage*>(data);
01515       }
01516 
01517       //********************************************
01518       const etl::imessage& get() const
01519       {
01520         return *static_cast<const etl::imessage*>(data);
01521       }
01522 
01523       enum
01524       {
01525         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8>::size,
01526         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7, T8>::alignment
01527       };
01528 
01529     private:
01530 
01531       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01532     };
01533 
01534     //**********************************************
01535     message_router(etl::message_router_id_t id_)
01536       : imessage_router(id_)
01537     {
01538       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01539     }
01540 
01541     //**********************************************
01542     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01543       : imessage_router(id_, successor_)
01544     {
01545       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01546     }
01547 
01548     //**********************************************
01549     void receive(const etl::imessage& msg)
01550     {
01551       receive(etl::null_message_router::instance(), msg);
01552     }
01553 
01554     //**********************************************
01555     void receive(etl::imessage_router& source, const etl::imessage& msg)
01556     {
01557       const size_t id = msg.message_id;
01558 
01559       switch (id)
01560       {
01561         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01562         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01563         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01564         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01565         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01566         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
01567         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
01568         case T8::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T8&>(msg)); break;
01569         default:
01570         {
01571            if (has_successor())
01572            {
01573              get_successor().receive(source, msg);
01574            }
01575            else
01576            {
01577              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01578            }
01579            break;
01580         }
01581       }
01582     }
01583 
01584     using imessage_router::accepts;
01585 
01586     //**********************************************
01587     bool accepts(etl::message_id_t id) const
01588     {
01589       switch (id)
01590       {
01591         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: case T8::ID: 
01592         
01593           return true; break;
01594         default:
01595           return false; break;
01596       }
01597     }
01598   };
01599 
01600   //***************************************************************************
01601   // Specialisation for 7 message types.
01602   //***************************************************************************
01603   template <typename TDerived, 
01604             typename T1, typename T2, typename T3, typename T4, 
01605             typename T5, typename T6, typename T7>
01606   class message_router<TDerived, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void>
01607    : public imessage_router
01608   {
01609   public:
01610 
01611     //**********************************************
01612     class message_packet
01613     {
01614     public:
01615 
01616       //********************************************
01617       explicit message_packet(const etl::imessage& msg)
01618       {
01619         const size_t id = msg.message_id;
01620 
01621         void* p = data;
01622 
01623         switch (id)
01624         {
01625           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01626           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01627           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01628           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01629           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01630           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
01631           case T7::ID: ::new (p) T7(static_cast<const T7&>(msg)); break;
01632           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01633         }
01634       }
01635 
01636       //********************************************
01637       template <typename T>
01638       explicit message_packet(const T& msg)
01639       {
01640         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6, T7>::value), "Unsupported type for this message packet");
01641 
01642         void* p = data;
01643         ::new (p) T(static_cast<const T&>(msg));
01644       }
01645 
01646       //********************************************
01647       ~message_packet()
01648       {
01649         static_cast<etl::imessage*>(data)->~imessage();
01650       }
01651 
01652       //********************************************
01653       etl::imessage& get()
01654       {
01655         return *static_cast<etl::imessage*>(data);
01656       }
01657 
01658       //********************************************
01659       const etl::imessage& get() const
01660       {
01661         return *static_cast<const etl::imessage*>(data);
01662       }
01663 
01664       enum
01665       {
01666         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6, T7>::size,
01667         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6, T7>::alignment
01668       };
01669 
01670     private:
01671 
01672       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01673     };
01674 
01675     //**********************************************
01676     message_router(etl::message_router_id_t id_)
01677       : imessage_router(id_)
01678     {
01679       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01680     }
01681 
01682     //**********************************************
01683     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01684       : imessage_router(id_, successor_)
01685     {
01686       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01687     }
01688 
01689     //**********************************************
01690     void receive(const etl::imessage& msg)
01691     {
01692       receive(etl::null_message_router::instance(), msg);
01693     }
01694 
01695     //**********************************************
01696     void receive(etl::imessage_router& source, const etl::imessage& msg)
01697     {
01698       const size_t id = msg.message_id;
01699 
01700       switch (id)
01701       {
01702         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01703         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01704         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01705         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01706         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01707         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
01708         case T7::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T7&>(msg)); break;
01709         default:
01710         {
01711            if (has_successor())
01712            {
01713              get_successor().receive(source, msg);
01714            }
01715            else
01716            {
01717              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01718            }
01719            break;
01720         }
01721       }
01722     }
01723 
01724     using imessage_router::accepts;
01725 
01726     //**********************************************
01727     bool accepts(etl::message_id_t id) const
01728     {
01729       switch (id)
01730       {
01731         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: case T7::ID: 
01732           return true; break;
01733         default:
01734           return false; break;
01735       }
01736     }
01737   };
01738 
01739   //***************************************************************************
01740   // Specialisation for 6 message types.
01741   //***************************************************************************
01742   template <typename TDerived, 
01743             typename T1, typename T2, typename T3, typename T4, 
01744             typename T5, typename T6>
01745   class message_router<TDerived, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void>
01746    : public imessage_router
01747   {
01748   public:
01749 
01750     //**********************************************
01751     class message_packet
01752     {
01753     public:
01754 
01755       //********************************************
01756       explicit message_packet(const etl::imessage& msg)
01757       {
01758         const size_t id = msg.message_id;
01759 
01760         void* p = data;
01761 
01762         switch (id)
01763         {
01764           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01765           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01766           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01767           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01768           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01769           case T6::ID: ::new (p) T6(static_cast<const T6&>(msg)); break;
01770           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01771         }
01772       }
01773 
01774       //********************************************
01775       template <typename T>
01776       explicit message_packet(const T& msg)
01777       {
01778         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5, T6>::value), "Unsupported type for this message packet");
01779 
01780         void* p = data;
01781         ::new (p) T(static_cast<const T&>(msg));
01782       }
01783 
01784       //********************************************
01785       ~message_packet()
01786       {
01787         static_cast<etl::imessage*>(data)->~imessage();
01788       }
01789 
01790       //********************************************
01791       etl::imessage& get()
01792       {
01793         return *static_cast<etl::imessage*>(data);
01794       }
01795 
01796       //********************************************
01797       const etl::imessage& get() const
01798       {
01799         return *static_cast<const etl::imessage*>(data);
01800       }
01801 
01802       enum
01803       {
01804         SIZE      = etl::largest<T1, T2, T3, T4, T5, T6>::size,
01805         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5, T6>::alignment
01806       };
01807 
01808     private:
01809 
01810       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01811     };
01812 
01813     //**********************************************
01814     message_router(etl::message_router_id_t id_)
01815       : imessage_router(id_)
01816     {
01817       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01818     }
01819 
01820     //**********************************************
01821     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01822       : imessage_router(id_, successor_)
01823     {
01824       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01825     }
01826 
01827     //**********************************************
01828     void receive(const etl::imessage& msg)
01829     {
01830       receive(etl::null_message_router::instance(), msg);
01831     }
01832 
01833     //**********************************************
01834     void receive(etl::imessage_router& source, const etl::imessage& msg)
01835     {
01836       const size_t id = msg.message_id;
01837 
01838       switch (id)
01839       {
01840         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01841         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01842         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01843         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01844         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01845         case T6::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T6&>(msg)); break;
01846         default:
01847         {
01848            if (has_successor())
01849            {
01850              get_successor().receive(source, msg);
01851            }
01852            else
01853            {
01854              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01855            }
01856            break;
01857         }
01858       }
01859     }
01860 
01861     using imessage_router::accepts;
01862 
01863     //**********************************************
01864     bool accepts(etl::message_id_t id) const
01865     {
01866       switch (id)
01867       {
01868         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: case T6::ID: 
01869           return true; break;
01870         default:
01871           return false; break;
01872       }
01873     }
01874   };
01875 
01876   //***************************************************************************
01877   // Specialisation for 5 message types.
01878   //***************************************************************************
01879   template <typename TDerived, 
01880             typename T1, typename T2, typename T3, typename T4, 
01881             typename T5>
01882   class message_router<TDerived, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void>
01883    : public imessage_router
01884   {
01885   public:
01886 
01887     //**********************************************
01888     class message_packet
01889     {
01890     public:
01891 
01892       //********************************************
01893       explicit message_packet(const etl::imessage& msg)
01894       {
01895         const size_t id = msg.message_id;
01896 
01897         void* p = data;
01898 
01899         switch (id)
01900         {
01901           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
01902           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
01903           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
01904           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
01905           case T5::ID: ::new (p) T5(static_cast<const T5&>(msg)); break;
01906           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
01907         }
01908       }
01909 
01910       //********************************************
01911       template <typename T>
01912       explicit message_packet(const T& msg)
01913       {
01914         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4, T5>::value), "Unsupported type for this message packet");
01915 
01916         void* p = data;
01917         ::new (p) T(static_cast<const T&>(msg));
01918       }
01919 
01920       //********************************************
01921       ~message_packet()
01922       {
01923         static_cast<etl::imessage*>(data)->~imessage();
01924       }
01925 
01926       //********************************************
01927       etl::imessage& get()
01928       {
01929         return *static_cast<etl::imessage*>(data);
01930       }
01931 
01932       //********************************************
01933       const etl::imessage& get() const
01934       {
01935         return *static_cast<const etl::imessage*>(data);
01936       }
01937 
01938       enum
01939       {
01940         SIZE      = etl::largest<T1, T2, T3, T4, T5>::size,
01941         ALIGNMENT = etl::largest<T1, T2, T3, T4, T5>::alignment
01942       };
01943 
01944     private:
01945 
01946       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
01947     };
01948 
01949     //**********************************************
01950     message_router(etl::message_router_id_t id_)
01951       : imessage_router(id_)
01952     {
01953       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01954     }
01955 
01956     //**********************************************
01957     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
01958       : imessage_router(id_, successor_)
01959     {
01960       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
01961     }
01962 
01963     //**********************************************
01964     void receive(const etl::imessage& msg)
01965     {
01966       receive(etl::null_message_router::instance(), msg);
01967     }
01968 
01969     //**********************************************
01970     void receive(etl::imessage_router& source, const etl::imessage& msg)
01971     {
01972       const size_t id = msg.message_id;
01973 
01974       switch (id)
01975       {
01976         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
01977         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
01978         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
01979         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
01980         case T5::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T5&>(msg)); break;
01981         default:
01982         {
01983            if (has_successor())
01984            {
01985              get_successor().receive(source, msg);
01986            }
01987            else
01988            {
01989              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
01990            }
01991            break;
01992         }
01993       }
01994     }
01995 
01996     using imessage_router::accepts;
01997 
01998     //**********************************************
01999     bool accepts(etl::message_id_t id) const
02000     {
02001       switch (id)
02002       {
02003         case T1::ID: case T2::ID: case T3::ID: case T4::ID: case T5::ID: 
02004           return true; break;
02005         default:
02006           return false; break;
02007       }
02008     }
02009   };
02010 
02011   //***************************************************************************
02012   // Specialisation for 4 message types.
02013   //***************************************************************************
02014   template <typename TDerived, 
02015             typename T1, typename T2, typename T3, typename T4>
02016   class message_router<TDerived, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void>
02017    : public imessage_router
02018   {
02019   public:
02020 
02021     //**********************************************
02022     class message_packet
02023     {
02024     public:
02025 
02026       //********************************************
02027       explicit message_packet(const etl::imessage& msg)
02028       {
02029         const size_t id = msg.message_id;
02030 
02031         void* p = data;
02032 
02033         switch (id)
02034         {
02035           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
02036           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
02037           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
02038           case T4::ID: ::new (p) T4(static_cast<const T4&>(msg)); break;
02039           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
02040         }
02041       }
02042 
02043       //********************************************
02044       template <typename T>
02045       explicit message_packet(const T& msg)
02046       {
02047         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3, T4>::value), "Unsupported type for this message packet");
02048 
02049         void* p = data;
02050         ::new (p) T(static_cast<const T&>(msg));
02051       }
02052 
02053       //********************************************
02054       ~message_packet()
02055       {
02056         static_cast<etl::imessage*>(data)->~imessage();
02057       }
02058 
02059       //********************************************
02060       etl::imessage& get()
02061       {
02062         return *static_cast<etl::imessage*>(data);
02063       }
02064 
02065       //********************************************
02066       const etl::imessage& get() const
02067       {
02068         return *static_cast<const etl::imessage*>(data);
02069       }
02070 
02071       enum
02072       {
02073         SIZE      = etl::largest<T1, T2, T3, T4>::size,
02074         ALIGNMENT = etl::largest<T1, T2, T3, T4>::alignment
02075       };
02076 
02077     private:
02078 
02079       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
02080     };
02081 
02082     //**********************************************
02083     message_router(etl::message_router_id_t id_)
02084       : imessage_router(id_)
02085     {
02086       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02087     }
02088 
02089     //**********************************************
02090     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
02091       : imessage_router(id_, successor_)
02092     {
02093       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02094     }
02095 
02096     //**********************************************
02097     void receive(const etl::imessage& msg)
02098     {
02099       receive(etl::null_message_router::instance(), msg);
02100     }
02101 
02102     //**********************************************
02103     void receive(etl::imessage_router& source, const etl::imessage& msg)
02104     {
02105       const size_t id = msg.message_id;
02106 
02107       switch (id)
02108       {
02109         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
02110         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
02111         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
02112         case T4::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T4&>(msg)); break;
02113         default:
02114         {
02115            if (has_successor())
02116            {
02117              get_successor().receive(source, msg);
02118            }
02119            else
02120            {
02121              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
02122            }
02123            break;
02124         }
02125       }
02126     }
02127 
02128     using imessage_router::accepts;
02129 
02130     //**********************************************
02131     bool accepts(etl::message_id_t id) const
02132     {
02133       switch (id)
02134       {
02135         case T1::ID: case T2::ID: case T3::ID: case T4::ID: 
02136           return true; break;
02137         default:
02138           return false; break;
02139       }
02140     }
02141   };
02142 
02143   //***************************************************************************
02144   // Specialisation for 3 message types.
02145   //***************************************************************************
02146   template <typename TDerived, 
02147             typename T1, typename T2, typename T3>
02148   class message_router<TDerived, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void>
02149    : public imessage_router
02150   {
02151   public:
02152 
02153     //**********************************************
02154     class message_packet
02155     {
02156     public:
02157 
02158       //********************************************
02159       explicit message_packet(const etl::imessage& msg)
02160       {
02161         const size_t id = msg.message_id;
02162 
02163         void* p = data;
02164 
02165         switch (id)
02166         {
02167           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
02168           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
02169           case T3::ID: ::new (p) T3(static_cast<const T3&>(msg)); break;
02170           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
02171         }
02172       }
02173 
02174       //********************************************
02175       template <typename T>
02176       explicit message_packet(const T& msg)
02177       {
02178         STATIC_ASSERT((etl::is_one_of<T, T1, T2, T3>::value), "Unsupported type for this message packet");
02179 
02180         void* p = data;
02181         ::new (p) T(static_cast<const T&>(msg));
02182       }
02183 
02184       //********************************************
02185       ~message_packet()
02186       {
02187         static_cast<etl::imessage*>(data)->~imessage();
02188       }
02189 
02190       //********************************************
02191       etl::imessage& get()
02192       {
02193         return *static_cast<etl::imessage*>(data);
02194       }
02195 
02196       //********************************************
02197       const etl::imessage& get() const
02198       {
02199         return *static_cast<const etl::imessage*>(data);
02200       }
02201 
02202       enum
02203       {
02204         SIZE      = etl::largest<T1, T2, T3>::size,
02205         ALIGNMENT = etl::largest<T1, T2, T3>::alignment
02206       };
02207 
02208     private:
02209 
02210       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
02211     };
02212 
02213     //**********************************************
02214     message_router(etl::message_router_id_t id_)
02215       : imessage_router(id_)
02216     {
02217       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02218     }
02219 
02220     //**********************************************
02221     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
02222       : imessage_router(id_, successor_)
02223     {
02224       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02225     }
02226 
02227     //**********************************************
02228     void receive(const etl::imessage& msg)
02229     {
02230       receive(etl::null_message_router::instance(), msg);
02231     }
02232 
02233     //**********************************************
02234     void receive(etl::imessage_router& source, const etl::imessage& msg)
02235     {
02236       const size_t id = msg.message_id;
02237 
02238       switch (id)
02239       {
02240         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
02241         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
02242         case T3::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T3&>(msg)); break;
02243         default:
02244         {
02245            if (has_successor())
02246            {
02247              get_successor().receive(source, msg);
02248            }
02249            else
02250            {
02251              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
02252            }
02253            break;
02254         }
02255       }
02256     }
02257 
02258     using imessage_router::accepts;
02259 
02260     //**********************************************
02261     bool accepts(etl::message_id_t id) const
02262     {
02263       switch (id)
02264       {
02265         case T1::ID: case T2::ID: case T3::ID: 
02266           return true; break;
02267         default:
02268           return false; break;
02269       }
02270     }
02271   };
02272 
02273   //***************************************************************************
02274   // Specialisation for 2 message types.
02275   //***************************************************************************
02276   template <typename TDerived, 
02277             typename T1, typename T2>
02278   class message_router<TDerived, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
02279    : public imessage_router
02280   {
02281   public:
02282 
02283     //**********************************************
02284     class message_packet
02285     {
02286     public:
02287 
02288       //********************************************
02289       explicit message_packet(const etl::imessage& msg)
02290       {
02291         const size_t id = msg.message_id;
02292 
02293         void* p = data;
02294 
02295         switch (id)
02296         {
02297           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
02298           case T2::ID: ::new (p) T2(static_cast<const T2&>(msg)); break;
02299           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
02300         }
02301       }
02302 
02303       //********************************************
02304       template <typename T>
02305       explicit message_packet(const T& msg)
02306       {
02307         STATIC_ASSERT((etl::is_one_of<T, T1, T2>::value), "Unsupported type for this message packet");
02308 
02309         void* p = data;
02310         ::new (p) T(static_cast<const T&>(msg));
02311       }
02312 
02313       //********************************************
02314       ~message_packet()
02315       {
02316         static_cast<etl::imessage*>(data)->~imessage();
02317       }
02318 
02319       //********************************************
02320       etl::imessage& get()
02321       {
02322         return *static_cast<etl::imessage*>(data);
02323       }
02324 
02325       //********************************************
02326       const etl::imessage& get() const
02327       {
02328         return *static_cast<const etl::imessage*>(data);
02329       }
02330 
02331       enum
02332       {
02333         SIZE      = etl::largest<T1, T2>::size,
02334         ALIGNMENT = etl::largest<T1, T2>::alignment
02335       };
02336 
02337     private:
02338 
02339       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
02340     };
02341 
02342     //**********************************************
02343     message_router(etl::message_router_id_t id_)
02344       : imessage_router(id_)
02345     {
02346       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02347     }
02348 
02349     //**********************************************
02350     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
02351       : imessage_router(id_, successor_)
02352     {
02353       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02354     }
02355 
02356     //**********************************************
02357     void receive(const etl::imessage& msg)
02358     {
02359       receive(etl::null_message_router::instance(), msg);
02360     }
02361 
02362     //**********************************************
02363     void receive(etl::imessage_router& source, const etl::imessage& msg)
02364     {
02365       const size_t id = msg.message_id;
02366 
02367       switch (id)
02368       {
02369         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
02370         case T2::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T2&>(msg)); break;
02371         default:
02372         {
02373            if (has_successor())
02374            {
02375              get_successor().receive(source, msg);
02376            }
02377            else
02378            {
02379              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
02380            }
02381            break;
02382         }
02383       }
02384     }
02385 
02386     using imessage_router::accepts;
02387 
02388     //**********************************************
02389     bool accepts(etl::message_id_t id) const
02390     {
02391       switch (id)
02392       {
02393         case T1::ID: case T2::ID: 
02394           return true; break;
02395         default:
02396           return false; break;
02397       }
02398     }
02399   };
02400 
02401   //***************************************************************************
02402   // Specialisation for 1 message type.
02403   //***************************************************************************
02404   template <typename TDerived, 
02405             typename T1>
02406   class message_router<TDerived, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void>
02407    : public imessage_router
02408   {
02409   public:
02410 
02411     //**********************************************
02412     class message_packet
02413     {
02414     public:
02415 
02416       //********************************************
02417       explicit message_packet(const etl::imessage& msg)
02418       {
02419         const size_t id = msg.message_id;
02420 
02421         void* p = data;
02422 
02423         switch (id)
02424         {
02425           case T1::ID: ::new (p) T1(static_cast<const T1&>(msg)); break;
02426           default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;
02427         }
02428       }
02429 
02430       //********************************************
02431       template <typename T>
02432       explicit message_packet(const T& msg)
02433       {
02434         STATIC_ASSERT((etl::is_one_of<T, T1>::value), "Unsupported type for this message packet");
02435 
02436         void* p = data;
02437         ::new (p) T(static_cast<const T&>(msg));
02438       }
02439 
02440       //********************************************
02441       ~message_packet()
02442       {
02443         static_cast<etl::imessage*>(data)->~imessage();
02444       }
02445 
02446       //********************************************
02447       etl::imessage& get()
02448       {
02449         return *static_cast<etl::imessage*>(data);
02450       }
02451 
02452       //********************************************
02453       const etl::imessage& get() const
02454       {
02455         return *static_cast<const etl::imessage*>(data);
02456       }
02457 
02458       enum
02459       {
02460         SIZE      = etl::largest<T1>::size,
02461         ALIGNMENT = etl::largest<T1>::alignment
02462       };
02463 
02464     private:
02465 
02466       typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;
02467     };
02468 
02469     //**********************************************
02470     message_router(etl::message_router_id_t id_)
02471       : imessage_router(id_)
02472     {
02473       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02474     }
02475 
02476     //**********************************************
02477     message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
02478       : imessage_router(id_, successor_)
02479     {
02480       ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
02481     }
02482 
02483     //**********************************************
02484     void receive(const etl::imessage& msg)
02485     {
02486       receive(etl::null_message_router::instance(), msg);
02487     }
02488 
02489     //**********************************************
02490     void receive(etl::imessage_router& source, const etl::imessage& msg)
02491     {
02492       const size_t id = msg.message_id;
02493 
02494       switch (id)
02495       {
02496         case T1::ID: static_cast<TDerived*>(this)->on_receive(source, static_cast<const T1&>(msg)); break;
02497         default:
02498         {
02499            if (has_successor())
02500            {
02501              get_successor().receive(source, msg);
02502            }
02503            else
02504            {
02505              static_cast<TDerived*>(this)->on_receive_unknown(source, msg);
02506            }
02507            break;
02508         }
02509       }
02510     }
02511 
02512     using imessage_router::accepts;
02513 
02514     //**********************************************
02515     bool accepts(etl::message_id_t id) const
02516     {
02517       switch (id)
02518       {
02519         case T1::ID: 
02520           return true; break;
02521         default:
02522           return false; break;
02523       }
02524     }
02525   };
02526 }
02527 
02528 #undef ETL_FILE
02529 
02530 #endif
02531