Stefan Scholz / ETL
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers message_router_generator.h Source File

message_router_generator.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 /*[[[cog
00030 import cog
00031 cog.outl("#if 0")
00032 ]]]*/
00033 /*[[[end]]]*/
00034 #error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
00035 /*[[[cog
00036 import cog
00037 cog.outl("#endif")
00038 ]]]*/
00039 /*[[[end]]]*/
00040 
00041 /*[[[cog
00042 import cog
00043 cog.outl("//***************************************************************************")
00044 cog.outl("// This file has been auto generated. Do not edit this file.")
00045 cog.outl("//***************************************************************************")
00046 ]]]*/
00047 /*[[[end]]]*/
00048 
00049 //***************************************************************************
00050 // To generate to header file, run this at the command line.
00051 // Note: You will need Python and COG installed.
00052 //
00053 // python -m cogapp -d -e -omessage_router.h -DHandlers=<n> message_router_generator.h 
00054 // Where <n> is the number of messages to support.
00055 //
00056 // e.g.
00057 // To generate handlers for up to 16 messages...
00058 // python -m cogapp -d -e -omessage_router.h -DHandlers=16 message_router_generator.h 
00059 //
00060 // See generate.bat
00061 //***************************************************************************
00062 
00063 #ifndef __ETL_MESSAGE_ROUTER__
00064 #define __ETL_MESSAGE_ROUTER__
00065 
00066 #include <stdint.h>
00067 
00068 #include "platform.h "
00069 #include "message.h"
00070 #include "message_types.h"
00071 #include "alignment.h "
00072 #include "error_handler.h "
00073 #include "exception.h "
00074 #include "largest.h "
00075 #include "nullptr.h "
00076 
00077 #undef ETL_FILE
00078 #define ETL_FILE "35"
00079 
00080 namespace etl
00081 {
00082   //***************************************************************************
00083   /// Base exception class for message router
00084   //***************************************************************************
00085   class message_router_exception : public etl::exception
00086   {
00087   public:
00088 
00089     message_router_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
00090       : etl::exception(reason_, file_name_, line_number_)
00091     {
00092     }
00093   };
00094 
00095   //***************************************************************************
00096   /// Router id is out of the legal range.
00097   //***************************************************************************
00098   class message_router_illegal_id : public etl::message_router_exception
00099   {
00100   public:
00101 
00102     message_router_illegal_id(string_type file_name_, numeric_type line_number_)
00103       : message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_FILE"A"), file_name_, line_number_)
00104     {
00105     }
00106   };
00107 
00108   //***************************************************************************
00109   class imessage_router
00110   {
00111   public:
00112 
00113     virtual ~imessage_router() {}
00114     virtual void receive(const etl::imessage& message) = 0;
00115     virtual void receive(imessage_router& source, const etl::imessage& message) = 0;
00116     virtual bool accepts(etl::message_id_t id) const = 0;
00117 
00118     //********************************************
00119     bool accepts(const etl::imessage& msg) const
00120     {
00121       return accepts(msg.message_id);
00122     }
00123 
00124     //********************************************
00125     etl::message_router_id_t get_message_router_id() const
00126     {
00127       return message_router_id;
00128     }
00129 
00130     //********************************************
00131     bool is_null_router() const
00132     {
00133       return (message_router_id == NULL_MESSAGE_ROUTER);
00134     }
00135 
00136     //********************************************
00137     bool is_bus() const
00138     {
00139       return (message_router_id == MESSAGE_BUS);
00140     }
00141 
00142     //********************************************
00143     void set_successor(imessage_router& successor_)
00144     {
00145       successor = &successor_;
00146     }
00147 
00148     //********************************************
00149     imessage_router& get_successor() const
00150     {
00151       return *successor;
00152     }
00153 
00154     //********************************************
00155     bool has_successor() const
00156     {
00157       return (successor != std::nullptr);
00158     }
00159 
00160     enum
00161     {
00162       NULL_MESSAGE_ROUTER = 255,
00163       MESSAGE_BUS         = 254,
00164       ALL_MESSAGE_ROUTERS = 253,
00165       MAX_MESSAGE_ROUTER  = 249
00166     };
00167 
00168   protected:
00169 
00170     imessage_router(etl::message_router_id_t id_)
00171       : successor(std::nullptr),
00172         message_router_id(id_)
00173     {
00174     }
00175 
00176     imessage_router(etl::message_router_id_t id_, 
00177                     imessage_router&         successor_)
00178       : successor(&successor_),
00179         message_router_id(id_)        
00180     {
00181     }
00182 
00183   private:
00184 
00185     // Disabled.
00186     imessage_router(const imessage_router&);
00187     imessage_router& operator =(const imessage_router&);
00188 
00189     etl::imessage_router* successor;
00190 
00191     etl::message_router_id_t  message_router_id;
00192   };
00193 
00194   //***************************************************************************
00195   /// This router can be used either as a sink for messages
00196   /// or as a producer-only of messages such an interrupt routine.
00197   //***************************************************************************
00198   class null_message_router : public imessage_router
00199   {
00200   public:
00201 
00202     null_message_router()
00203       : imessage_router(imessage_router::NULL_MESSAGE_ROUTER)
00204     {
00205     }
00206 
00207     //********************************************
00208     void receive(const etl::imessage&)
00209     {
00210     }
00211 
00212     //********************************************
00213     void receive(etl::imessage_router&, const etl::imessage&)
00214     {
00215     }
00216 
00217     //********************************************
00218     bool accepts(etl::message_id_t) const
00219     {
00220       return false;
00221     }
00222 
00223     //********************************************
00224     static null_message_router& instance()
00225     {
00226       static null_message_router nmr;
00227       return nmr;
00228     }
00229   };
00230 
00231   //***************************************************************************
00232   /// Send a message to a router.
00233   /// Sets the 'sender' to etl::null_message_router type.
00234   //***************************************************************************
00235   inline static void send_message(etl::imessage_router& destination, 
00236                                   const etl::imessage&  message)
00237   {
00238     destination.receive(message);
00239   }
00240 
00241   //***************************************************************************
00242   /// Send a message to a router.
00243   //***************************************************************************
00244   inline static void send_message(etl::imessage_router& source, 
00245                                   etl::imessage_router& destination, 
00246                                   const etl::imessage&  message)
00247   {
00248     destination.receive(source, message);
00249   }
00250   
00251   /*[[[cog
00252       import cog
00253       ################################################
00254       # The first definition for all of the messages.
00255       ################################################
00256       cog.outl("//***************************************************************************")
00257       cog.outl("// The definition for all %s message types." % Handlers)
00258       cog.outl("//***************************************************************************")
00259       cog.outl("template <typename TDerived,")
00260       cog.out("          ")
00261       cog.out("typename T1, ")
00262       for n in range(2, int(Handlers)):
00263           cog.out("typename T%s = void, " % n)
00264           if n % 4 == 0:
00265               cog.outl("")
00266               cog.out("          ")
00267       cog.outl("typename T%s = void>" % int(Handlers))
00268       cog.out("class message_router")
00269       cog.outl("  : public imessage_router")
00270       cog.outl("{")
00271       cog.outl("public:")
00272       cog.outl("")
00273       cog.outl("  //**********************************************")
00274       cog.outl("  class message_packet")
00275       cog.outl("  {")
00276       cog.outl("  public:")
00277       cog.outl("")
00278       cog.outl("    //********************************************")
00279       cog.outl("    explicit message_packet(const etl::imessage& msg)")
00280       cog.outl("    {")
00281       cog.outl("      const size_t id = msg.message_id;")
00282       cog.outl("")
00283       cog.outl("      void* p = data;")
00284       cog.outl("")
00285       cog.outl("      switch (id)")
00286       cog.outl("      {")
00287       for n in range(1, int(Handlers) + 1):
00288           cog.outl("        case T%s::ID: ::new (p) T%s(static_cast<const T%s&>(msg)); break;" % (n, n, n))
00289       cog.outl("        default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;")
00290       cog.outl("      }")
00291       cog.outl("    }")
00292       cog.outl("")      
00293       cog.outl("    //********************************************")
00294       cog.outl("    template <typename T>")
00295       cog.outl("    explicit message_packet(const T& msg)")
00296       cog.outl("    {")
00297       cog.out("      STATIC_ASSERT((etl::is_one_of<T, ")
00298       for n in range(1, int(Handlers)):
00299           cog.out("T%s, " % n)
00300           if n % 16 == 0:
00301               cog.outl("")
00302               cog.out("                                       ")
00303       cog.outl("""T%s>::value), "Unsupported type for this message packet");""" % int(Handlers))
00304       cog.outl("")
00305       cog.outl("      void* p = data;")
00306       cog.outl("      ::new (p) T(static_cast<const T&>(msg));")
00307       cog.outl("    }")
00308       cog.outl("")
00309       cog.outl("    //********************************************")
00310       cog.outl("    ~message_packet()")
00311       cog.outl("    {")
00312       cog.outl("      static_cast<etl::imessage*>(data)->~imessage();")
00313       cog.outl("    }")
00314       cog.outl("")
00315       cog.outl("    //********************************************")
00316       cog.outl("    etl::imessage& get()")
00317       cog.outl("    {")
00318       cog.outl("      return *static_cast<etl::imessage*>(data);")
00319       cog.outl("    }")
00320       cog.outl("")
00321       cog.outl("    //********************************************")
00322       cog.outl("    const etl::imessage& get() const")
00323       cog.outl("    {")
00324       cog.outl("      return *static_cast<const etl::imessage*>(data);")
00325       cog.outl("    }")
00326       cog.outl("")
00327       cog.outl("    enum")
00328       cog.outl("    {")
00329       cog.out("      SIZE      = etl::largest<")
00330       for n in range(1, int(Handlers)):
00331           cog.out("T%s, " % n)
00332       cog.outl("T%s>::size," % int(Handlers))
00333       cog.out("      ALIGNMENT = etl::largest<")
00334       for n in range(1, int(Handlers)):
00335           cog.out("T%s, " % n)
00336       cog.outl("T%s>::alignment" % int(Handlers))
00337       cog.outl("    };")
00338       cog.outl("")
00339       cog.outl("  private:")
00340       cog.outl("")
00341       cog.outl("    typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;")
00342       cog.outl("  };")
00343       cog.outl("")
00344       cog.outl("  //**********************************************")
00345       cog.outl("  message_router(etl::message_router_id_t id_)")
00346       cog.outl("    : imessage_router(id_)")
00347       cog.outl("  {")
00348       cog.outl("    ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
00349       cog.outl("  }")
00350       cog.outl("")
00351       cog.outl("  //**********************************************")
00352       cog.outl("  message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)")
00353       cog.outl("    : imessage_router(id_, successor_)")
00354       cog.outl("  {")
00355       cog.outl("    ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
00356       cog.outl("  }")
00357       cog.outl("")
00358       cog.outl("  //**********************************************")
00359       cog.outl("  void receive(const etl::imessage& msg)")
00360       cog.outl("  {")
00361       cog.outl("    receive(etl::null_message_router::instance(), msg);")
00362       cog.outl("  }")
00363       cog.outl("")
00364       cog.outl("  //**********************************************")
00365       cog.outl("  void receive(etl::imessage_router& source, const etl::imessage& msg)")
00366       cog.outl("  {")
00367       cog.outl("    const etl::message_id_t id = msg.message_id;")
00368       cog.outl("")
00369       cog.outl("    switch (id)")
00370       cog.outl("    {")
00371       for n in range(1, int(Handlers) + 1):
00372           cog.out("      case T%d::ID:" % n)
00373           cog.out(" static_cast<TDerived*>(this)->on_receive(source, static_cast<const T%d&>(msg));" % n)
00374           cog.outl(" break;")
00375       cog.outl("      default:")
00376       cog.outl("      {")
00377       cog.outl("         if (has_successor())")
00378       cog.outl("         {")
00379       cog.outl("           get_successor().receive(source, msg);")
00380       cog.outl("         }")
00381       cog.outl("         else")
00382       cog.outl("         {")
00383       cog.outl("           static_cast<TDerived*>(this)->on_receive_unknown(source, msg);")
00384       cog.outl("         }")
00385       cog.outl("         break;")
00386       cog.outl("      }")
00387       cog.outl("    }")
00388       cog.outl("  }")
00389       cog.outl("")
00390       cog.outl("  using imessage_router::accepts;")
00391       cog.outl("")
00392       cog.outl("  //**********************************************")
00393       cog.outl("  bool accepts(etl::message_id_t id) const")
00394       cog.outl("  {")
00395       cog.outl("    switch (id)")
00396       cog.outl("    {")
00397       cog.out("      ")
00398       for n in range(1, int(Handlers) + 1):
00399           cog.out("case T%d::ID: " % n)
00400           if n % 8 == 0:
00401               cog.outl("")
00402               cog.out("      ")
00403       cog.outl("  return true; break;")
00404       cog.outl("      default:")
00405       cog.outl("        return false; break;")
00406       cog.outl("    }")
00407       cog.outl("  }")
00408       cog.outl("};")
00409 
00410       ####################################
00411       # All of the other specialisations.
00412       ####################################
00413       for n in range(int(Handlers) - 1, 0, -1):
00414           cog.outl("")
00415           cog.outl("//***************************************************************************")
00416           if n == 1:
00417               cog.outl("// Specialisation for %d message type." % n)
00418           else:
00419               cog.outl("// Specialisation for %d message types." % n)
00420           cog.outl("//***************************************************************************")
00421           cog.outl("template <typename TDerived, ")
00422           cog.out("          ")
00423           for t in range(1, n):
00424               cog.out("typename T%d, " % t)
00425               if t % 4 == 0:
00426                   cog.outl("")
00427                   cog.out("          ")
00428           cog.outl("typename T%d>" % n)
00429           cog.out("class message_router<TDerived, ")
00430           for t in range(1, n + 1):
00431               cog.out("T%d, " % t)
00432               if t % 16 == 0:
00433                   cog.outl("")
00434                   cog.out("               ")
00435           for t in range(n + 1, int(Handlers)):
00436               cog.out("void, ")
00437               if t % 16 == 0:
00438                   cog.outl("")
00439                   cog.out("               ")
00440           cog.outl("void>")
00441           cog.outl(" : public imessage_router")
00442           cog.outl("{")
00443           cog.outl("public:")
00444           cog.outl("")
00445           cog.outl("  //**********************************************")
00446           cog.outl("  class message_packet")
00447           cog.outl("  {")
00448           cog.outl("  public:")
00449           cog.outl("")
00450           cog.outl("    //********************************************")
00451           cog.outl("    explicit message_packet(const etl::imessage& msg)")
00452           cog.outl("    {")
00453           cog.outl("      const size_t id = msg.message_id;")
00454           cog.outl("")
00455           cog.outl("      void* p = data;")
00456           cog.outl("")
00457           cog.outl("      switch (id)")
00458           cog.outl("      {")
00459           for t in range(1, n + 1):
00460               cog.outl("        case T%s::ID: ::new (p) T%s(static_cast<const T%s&>(msg)); break;" % (t, t, t))
00461           cog.outl("        default: ETL_ASSERT(false, ETL_ERROR(unhandled_message_exception)); break;")
00462           cog.outl("      }")
00463           cog.outl("    }")
00464           cog.outl("")
00465           cog.outl("    //********************************************")
00466           cog.outl("    template <typename T>")
00467           cog.outl("    explicit message_packet(const T& msg)")
00468           cog.outl("    {")
00469           cog.out("      STATIC_ASSERT((etl::is_one_of<T, ")
00470           for t in range(1, n):
00471               cog.out("T%s, " % t)
00472               if t % 16 == 0:
00473                   cog.outl("")
00474                   cog.out("                                       ")
00475           cog.outl("""T%s>::value), "Unsupported type for this message packet");""" % n)
00476           cog.outl("")
00477           cog.outl("      void* p = data;")
00478           cog.outl("      ::new (p) T(static_cast<const T&>(msg));")
00479           cog.outl("    }")
00480           cog.outl("")
00481           cog.outl("    //********************************************")
00482           cog.outl("    ~message_packet()")
00483           cog.outl("    {")
00484           cog.outl("      static_cast<etl::imessage*>(data)->~imessage();")
00485           cog.outl("    }")
00486           cog.outl("")
00487           cog.outl("    //********************************************")
00488           cog.outl("    etl::imessage& get()")
00489           cog.outl("    {")
00490           cog.outl("      return *static_cast<etl::imessage*>(data);")
00491           cog.outl("    }")
00492           cog.outl("")
00493           cog.outl("    //********************************************")
00494           cog.outl("    const etl::imessage& get() const")
00495           cog.outl("    {")
00496           cog.outl("      return *static_cast<const etl::imessage*>(data);")
00497           cog.outl("    }")
00498           cog.outl("")
00499           cog.outl("    enum")
00500           cog.outl("    {")
00501           cog.out("      SIZE      = etl::largest<")
00502           for t in range(1, n):
00503               cog.out("T%s, " % t)
00504           cog.outl("T%s>::size," % n)
00505           cog.out("      ALIGNMENT = etl::largest<")
00506           for t in range(1, n):
00507               cog.out("T%s, " % t)
00508           cog.outl("T%s>::alignment" % n)
00509           cog.outl("    };")
00510           cog.outl("")
00511           cog.outl("  private:")
00512           cog.outl("")
00513           cog.outl("    typename etl::aligned_storage<SIZE, ALIGNMENT>::type data;")
00514           cog.outl("  };")
00515           cog.outl("")
00516           cog.outl("  //**********************************************")
00517           cog.outl("  message_router(etl::message_router_id_t id_)")
00518           cog.outl("    : imessage_router(id_)")
00519           cog.outl("  {")
00520           cog.outl("    ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
00521           cog.outl("  }")
00522           cog.outl("")
00523           cog.outl("  //**********************************************")
00524           cog.outl("  message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)")
00525           cog.outl("    : imessage_router(id_, successor_)")
00526           cog.outl("  {")
00527           cog.outl("    ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));")
00528           cog.outl("  }")
00529           cog.outl("")
00530           cog.outl("  //**********************************************")
00531           cog.outl("  void receive(const etl::imessage& msg)")
00532           cog.outl("  {")
00533           cog.outl("    receive(etl::null_message_router::instance(), msg);")
00534           cog.outl("  }")
00535           cog.outl("")
00536           cog.outl("  //**********************************************")
00537           cog.outl("  void receive(etl::imessage_router& source, const etl::imessage& msg)")
00538           cog.outl("  {")
00539           cog.outl("    const size_t id = msg.message_id;")
00540           cog.outl("")
00541           cog.outl("    switch (id)")
00542           cog.outl("    {")
00543           for t in range(1, n + 1):
00544               cog.out("      case T%d::ID:" % t)
00545               cog.out(" static_cast<TDerived*>(this)->on_receive(source, static_cast<const T%d&>(msg));" % t)
00546               cog.outl(" break;")
00547           cog.outl("      default:")
00548           cog.outl("      {")
00549           cog.outl("         if (has_successor())")
00550           cog.outl("         {")
00551           cog.outl("           get_successor().receive(source, msg);")
00552           cog.outl("         }")
00553           cog.outl("         else")
00554           cog.outl("         {")
00555           cog.outl("           static_cast<TDerived*>(this)->on_receive_unknown(source, msg);")
00556           cog.outl("         }")
00557           cog.outl("         break;")
00558           cog.outl("      }")
00559           cog.outl("    }")
00560           cog.outl("  }")
00561           cog.outl("")
00562           cog.outl("  using imessage_router::accepts;")
00563           cog.outl("")
00564           cog.outl("  //**********************************************")
00565           cog.outl("  bool accepts(etl::message_id_t id) const")
00566           cog.outl("  {")
00567           cog.outl("    switch (id)")
00568           cog.outl("    {")
00569           cog.out("      ")
00570           for t in range(1, n + 1):
00571               cog.out("case T%d::ID: " % t)
00572               if t % 8 == 0:
00573                   cog.outl("")
00574                   cog.out("      ")
00575           cog.outl("")
00576           cog.outl("        return true; break;")
00577           cog.outl("      default:")
00578           cog.outl("        return false; break;")
00579           cog.outl("    }")
00580           cog.outl("  }")
00581           cog.outl("};")
00582   ]]]*/
00583   /*[[[end]]]*/
00584 }
00585 
00586 #undef ETL_FILE
00587 
00588 #endif
00589