Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / Packets / PacketRegistry.hh
index e766914..491c738 100644 (file)
 #include <boost/optional.hpp>
 #include <boost/preprocessor/cat.hpp>
 #include <senf/Utils/Exception.hh>
+#include <senf/Utils/singleton.hh>
 #include "Packet.hh"
 
 #include "PacketRegistry.ih"
 //#include "PacketRegistry.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace senf {
 
@@ -68,48 +69,53 @@ namespace senf {
         senf::PacketRegistry<SomeTag>::registerPacket<SomePacket>(key_of_somePacket);
 
         // static registration. 'registerSomePacket' is an arbitrary symbol name
-        senf::PacketRegistry<SomeTag>::RegistrationProxy<SomePacket>
-            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.
+        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).
 
-        To simplify static registration the SENF_PACKET_REGISTRY_REGISTER macro can be used:
-        \code
-        SENF_PACKET_REGISTRY_REGISTER(SomeTag, SomePacket, key_of_somePacket);
-        \endcode
+        \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 Tag>
     class PacketRegistry
+        : private senf::singleton< PacketRegistry<Tag> >
     {
     public:
         typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
+        typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::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<Tag>::RegistrationProxy<PacketType>
-                    registerPacketType (key);
+                senf::PacketRegistry<Tag>::ScopedRegistrationProxy<PacketType>
+                    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 <class PacketType>
-        struct RegistrationProxy
+        struct ScopedRegistrationProxy
         {
-            RegistrationProxy(typename Tag::key_t key);
-            ~RegistrationProxy();
+            ScopedRegistrationProxy(typename Tag::key_t key, int priority=0);
+            ~ScopedRegistrationProxy();
         };
 
         /** \brief Register new packet type
@@ -117,19 +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 <class PacketType>
-        static void registerPacket(typename Tag::key_t key);
+        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 <class PacketType>
         static void unregisterPacket();
-        static void unregisterPacket(typename Tag::key_t key);
+
+        /** \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
 
@@ -148,7 +172,7 @@ namespace senf {
 
             \tparam PacketType packet of which the key is requested
             \returns key of the packet wrapped in a <a
-                href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
+                href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional</a> or
                 an unbound optional, if the key is not found.
          */
         template <class PacketType>
@@ -170,7 +194,7 @@ namespace senf {
 
             \param packet The packet of which the key is requested
             \returns key of the packet wrapped in a <a
-                href="http://www.boost.org/libs/optional/doc/optional.html">boost::optional</a> or
+                href="http://www.boost.org/doc/libs/release/libs/optional/index.html">boost::optional</a> or
                 an unbound optional, if the key is not found.
          */
         static typename boost::optional<typename Tag::key_t> key(Packet const & packet, NoThrow_t);
@@ -180,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<PacketRegistry>::instance;
+        using singleton<PacketRegistry>::alive;
+
+        PacketRegistry();
+
         typedef detail::PacketRegistryImpl<typename Tag::key_t> Registry;
         static Registry & registry();
+        Registry registry_;
+
+        friend class senf::singleton< PacketRegistry >;
     };
 
     /** \brief Statically add an entry to a packet registry
@@ -209,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
@@ -231,7 +277,7 @@ namespace senf {
 
 }
 
-///////////////////////////////hh.e////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 #endif
 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketRegistry_i_)
 #define HH_SENF_Packets_PacketRegistry_i_