X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=senf%2FPackets%2FPacketRegistry.hh;h=491c73842d9ebd3f0aa1c17c56a56b4bacf512df;hb=7661548b20e6c7627f54bff87e0758396fd523ef;hp=19c70d59102e51f98f1d5f1995a6a9cf95d04141;hpb=ccff925ac3c102822a38617d00aef1bcf5217706;p=senf.git diff --git a/senf/Packets/PacketRegistry.hh b/senf/Packets/PacketRegistry.hh index 19c70d5..491c738 100644 --- a/senf/Packets/PacketRegistry.hh +++ b/senf/Packets/PacketRegistry.hh @@ -32,11 +32,12 @@ #include #include #include +#include #include "Packet.hh" #include "PacketRegistry.ih" //#include "PacketRegistry.mpp" -///////////////////////////////hh.p//////////////////////////////////////// +//-///////////////////////////////////////////////////////////////////////////////////////////////// namespace senf { @@ -68,47 +69,53 @@ namespace senf { senf::PacketRegistry::registerPacket(key_of_somePacket); // static registration. 'registerSomePacket' is an arbitrary symbol name - senf::PacketRegistry::RegistrationProxy - registerSomePacket (key_of_somePacket); + SENF_PACKET_REGISTRY_REGISTER( SomeTag, key_of_somePacket, SomePacket ); \endcode - This global variable declaration will register \a SomePacket with the \a SomeTag registry - under the key \a key_of_somePacket. The variable \a registerSomePacket is a dummy. It's only - function is to force the call of it's constructor during global construction time. This - static registration only works when the symbol is included into the final binary. To force - this inclusion, you should not put packet registrations into a library but into an object - file. - - To simplify static registration the SENF_PACKET_REGISTRY_REGISTER macro can be used: - \code - SENF_PACKET_REGISTRY_REGISTER(SomeTag, SomePacket, key_of_somePacket); - \endcode + SENF_PACKET_REGISTRY_REGISTER will declare an anonymous global variable which will ensure, + the packet is registered automatically during global initialization (as long as the object + file is linked into the final executable). + + \section packet_registry_priority Multiple registration for a single key + + Ordinarily, the PacketRegistry will reject registering the same key twice. However, the + registry supports an additional priority parameter when registering a packet. You may + register multiple Packets with the same \a key as long as the \a priority is unique. The + registration with the highest \a priority value will take precedence on key lookup. \ingroup packet_module */ template class PacketRegistry + : private senf::singleton< PacketRegistry > { public: typedef typename detail::PacketRegistryImpl::iterator iterator; + typedef typename detail::PacketRegistryImpl::Entry Entry; /** \brief Statically register a packet type in a PacketRegistry - To use this class, define a global symbol in the following way: + This class is normally used via SENF_PACKET_REGISTRY_REGISTER. To use this class + directly, define a symbol in the following way: \code namespace { - senf::PacketRegistry::RegistrationProxy - registerPacketType (key); + senf::PacketRegistry::ScopedRegistrationProxy + registerPacketType (key, optional_priority); } - \endcode Here \a Tag is the type tag of the registry to register the packet in, \a + \endcode + Here \a Tag is the type tag of the registry to register the packet in, \a PacketType is the packet to register (this is the ConcretePacket of that packet) and \a key is the key of type \c Tag::key_t under which the packet is to be registered. \a registerPacketType is an arbitrary name for the global symbol. + + The packet will be registered in the constructor and will be unregistered when the scope + of \c registerPacketType ends. */ template - struct RegistrationProxy + struct ScopedRegistrationProxy { - RegistrationProxy(typename Tag::key_t key); + ScopedRegistrationProxy(typename Tag::key_t key, int priority=0); + ~ScopedRegistrationProxy(); }; /** \brief Register new packet type @@ -116,15 +123,37 @@ namespace senf { Register \a PacketType in the packet registry \a Tag under the given \a key. \par Preconditions: - The given \a key must be unique and not be assigned to any other + The given pair \a key, \a priority must be unique and not be assigned to any other packet class in this registry. The %Packet must not already be registered in the registry. \tparam PacketType ConcretePacket instantiation of packet to register - \param key The key of the packet + \param[in] key The key of the packet + \param [in] priority Optional priority + */ + template + static void registerPacket(typename Tag::key_t key, int priority=0); + + /** \brief Unregister packet by packet type + + Removes \a PacketType from the packet registry. If the packet type is not registered, + this is a no-op. + + \tparam PacketType ConcretePacket instantiation of packet to remove from registry */ template - static void registerPacket(typename Tag::key_t key); + static void unregisterPacket(); + + /** \brief Unregister packet by key + + Removes the packet registration for \a key (and \a priority) from the registry. If no + packet is registered with the given pair \a key, \a priority, this operation is a + no-op. + + \param[in] key Key to remove from the registry + \param[in] priority Optional priority of the key to remove + */ + static void unregisterPacket(typename Tag::key_t key, int priority=0); /** \brief Find key of a packet type @@ -143,7 +172,7 @@ namespace senf { \tparam PacketType packet of which the key is requested \returns key of the packet wrapped in a boost::optional or + href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional or an unbound optional, if the key is not found. */ template @@ -165,7 +194,7 @@ namespace senf { \param packet The packet of which the key is requested \returns key of the packet wrapped in a boost::optional or + href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional or an unbound optional, if the key is not found. */ static typename boost::optional key(Packet const & packet, NoThrow_t); @@ -175,25 +204,33 @@ namespace senf { \throws PacketTypeNotRegistered if the \a key is not found in the registry \return %Packet entry for given \a key */ - static PkReg_Entry const & lookup(typename Tag::key_t key); + static Entry const & lookup(typename Tag::key_t key); /** \brief Lookup a packet by it's key \return Pointer to packet entry for given \a key or 0, if the key is not found in the registry. */ - static PkReg_Entry const * lookup(typename Tag::key_t key, NoThrow_t); + static Entry const * lookup(typename Tag::key_t key, NoThrow_t); - /** \brief Beginning iterator to list of registered keys + /** \brief Beginning iterator to list of registered entries */ static iterator begin(); - /** \brief End iterator to list of registered keys + /** \brief End iterator to list of registered entries */ static iterator end(); private: + using singleton::instance; + using singleton::alive; + + PacketRegistry(); + typedef detail::PacketRegistryImpl Registry; static Registry & registry(); + Registry registry_; + + friend class senf::singleton< PacketRegistry >; }; /** \brief Statically add an entry to a packet registry @@ -204,10 +241,24 @@ namespace senf { \ingroup packet_module \hideinitializer */ -# define SENF_PACKET_REGISTRY_REGISTER( registry, value, type ) \ - namespace { \ - senf::PacketRegistry< registry >::RegistrationProxy< type > \ - BOOST_PP_CAT(packetRegistration_, __LINE__) ( value ); \ +# define SENF_PACKET_REGISTRY_REGISTER( registry, value, type ) \ + namespace { \ + senf::PacketRegistry< registry >::ScopedRegistrationProxy< type > \ + BOOST_PP_CAT(packetRegistration_, __LINE__) ( value ); \ + } + + /** \brief Statically add an entry to a packet registry with explicit priority + + This macro will declare an anonymous global variable in such a way, that constructing this + variable will add a registration to the given packet registry. + + \ingroup packet_module + \hideinitializer + */ +# define SENF_PACKET_REGISTRY_REGISTER_PRIORITY( registry, value, priority, type ) \ + namespace { \ + senf::PacketRegistry< registry >::ScopedRegistrationProxy< type > \ + BOOST_PP_CAT(packetRegistration_, __LINE__) ( value, priority ); \ } /** \brief Dump all packet registries @@ -222,11 +273,11 @@ namespace senf { This exception is signaled whenever a throwing lookup operation fails. */ struct PacketTypeNotRegisteredException : public senf::Exception - { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered"){} }; + { PacketTypeNotRegisteredException() : senf::Exception("packet type not registered") {} }; } -///////////////////////////////hh.e//////////////////////////////////////// +//-///////////////////////////////////////////////////////////////////////////////////////////////// #endif #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_) #define HH_SENF_Packets_PacketRegistry_i_ @@ -235,7 +286,7 @@ namespace senf { #include "PacketRegistry.cti" #endif - + // Local Variables: // mode: c++ // fill-column: 100 @@ -245,4 +296,3 @@ namespace senf { // compile-command: "scons -u test" // comment-column: 40 // End: -