registry.hpp
Go to the documentation of this file.
00001 
00006 /*****************************************************************************
00007 ** Ifdefs
00008 *****************************************************************************/
00009 
00010 #ifndef mm_messages_REGISTRY_HPP_
00011 #define mm_messages_REGISTRY_HPP_
00012 
00013 /*****************************************************************************
00014 ** Includes
00015 *****************************************************************************/
00016 
00017 #include <iostream>
00018 #include <map>
00019 #include <set>
00020 #include <sstream>
00021 #include <string>
00022 #include "exceptions.hpp"
00023 #include "verbosity.hpp"
00024 
00025 /*****************************************************************************
00026 ** Namespaces
00027 *****************************************************************************/
00028 
00029 namespace mm_messages {
00030 
00031 /*****************************************************************************
00032 ** Interfaces
00033 *****************************************************************************/
00034 
00035 class MessageRegistry {
00036 public:
00041   template<int ID, typename T>
00042   static bool add(const std::string &description="") {
00043     if (ids().insert( std::pair<int, std::string>(ID, description)).second) {
00044       add_by_type<T>(ID);
00045       #ifdef MM_DEBUG_REGISTRY
00046         std::cout << "Registering message packet.............[" << ID << " : '" << description << "']" << std::endl;
00047       #endif
00048       return true;
00049     } else {
00050       #ifdef MM_DEBUG_REGISTRY
00051         std::cout << "Registering message packet failed......[" << ID << " : '" << description << "']" << std::endl;
00052       #endif
00053       return false;
00054     }
00055   }
00056   static bool isRegistered(const int& id) {
00057     return (ids().find(id) != ids().end());
00058   }
00059 
00060   template <typename T>
00061   static bool isRegisteredWithType(const int& id) {
00062     return (ids_by_type<T>().find(id) != ids_by_type<T>().end());
00063   }
00064 
00065 private:
00066   template <typename T>
00067   static void add_by_type(const int& id) {
00068     ids_by_type<T>().insert(id);
00069   }
00070 
00071   /****************************************
00072    ** Hidden Globals
00073    ****************************************/
00074   template <typename T>
00075   static std::set<int>& ids_by_type() {
00076     static std::set<int> ids;
00077     return ids;
00078   }
00079   static std::map<int, std::string>& ids() {
00080     static std::map<int, std::string> complete_id_set;
00081     return complete_id_set;
00082   }
00083 };
00084 
00085 /*****************************************************************************
00086  ** Registry Enablers
00087  *****************************************************************************/
00088 
00096 template<int ID, typename T>
00097 struct RegistryEntry {
00098   RegistryEntry(const std::string& description="") {
00099     bool result = MessageRegistry::add<ID, T>(description);
00100     if ( !result ) {
00101       std::stringstream ss;
00102       ss << "registry already holds id '" << ID << "' (our packet desc: '" << description << "')" << std::endl;
00103       throw MessageRegistrationFailed(ss.str());
00104     }
00105   }
00106 };
00107 
00108 } // mm_messages
00109 
00110 /*****************************************************************************
00111  ** Registry Macros
00112  *****************************************************************************/
00113 
00114 // Macro for loading id-type pairs into the registry. If multiple macros
00115 // are called for the same id, with different types, you will get
00116 // 1) a compile time error if they are in the same translation unit OR
00117 // 2) a runtime error (exception) if they are in different, but linked translation units
00118 
00119 // This requires some heavy macro expansions to work with __COUNTER__ so that
00120 // __COUNTER__ gets expanded *before* concatenation happens (this is what goes
00121 // wrong in a naive one line implementation). See this url for details:
00122 //
00123 //    http://blog.aaronballman.com/2011/12/stupid-compiler-tricks/
00124 //
00125 #define MM_REGISTER_IMP_2(uuid) unused_packet_info_##uuid
00126 #define MM_REGISTER_IMP_1(id, T, Description, uuid) \
00127     namespace mm_messages_registry_entries { \
00128       const mm_messages::RegistryEntry<id, T> MM_REGISTER_IMP_2(uuid)(Description); \
00129     }
00130 #define MM_REGISTER_PACKET_INFO(id, T, Description) MM_REGISTER_IMP_1(id, T, Description, __COUNTER__)
00131 
00132 #endif /* mm_messages_REGISTRY_HPP_ */


mm_messages
Author(s): Daniel Stonier
autogenerated on Thu Jun 6 2019 21:13:16