Packets: Implement PacketRegistry priority support
g0dil [Wed, 5 May 2010 15:23:04 +0000 (15:23 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1621 270642c3-0616-0410-b53a-bc976706d245

senf/Packets/80221Bundle/MIHPacket.cc
senf/Packets/DefaultBundle/LlcSnapPacket.cc
senf/Packets/MPEGDVBBundle/SNDUPacket.cc
senf/Packets/PacketRegistry.cc
senf/Packets/PacketRegistry.ct
senf/Packets/PacketRegistry.cti
senf/Packets/PacketRegistry.hh
senf/Packets/PacketRegistry.ih
senf/Packets/PacketRegistry.test.cc
senf/Packets/PacketType.cti

index e3f4389..3f549c5 100644 (file)
@@ -72,7 +72,8 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::MIHPacketType::nextPacketTy
 {
     if (p.data().size() < initSize())
         return no_factory();
-    PkReg_Entry const * e (PacketRegistry<MIHMessageRegistry>::lookup( p->messageId(), nothrow ));
+    PacketRegistry<MIHMessageRegistry>::Entry const * e (
+        PacketRegistry<MIHMessageRegistry>::lookup( p->messageId(), nothrow ));
     return e ? e->factory() : MIHGenericPayloadPacket::factory();
 }
 
index 8b09238..78762db 100644 (file)
@@ -50,8 +50,8 @@ prefix_ void senf::LlcSnapPacketType::dump(packet p, std::ostream & os)
 prefix_ senf::PacketInterpreterBase::factory_t senf::LlcSnapPacketType::nextPacketType(packet p)
 {
     if (p->type_length() >= 1536) {
-        PkReg_Entry const * e;
-        e = PacketRegistry<senf::EtherTypes>::lookup( p->type_length(), nothrow );
+        PacketRegistry<senf::EtherTypes>::Entry const * e (
+            PacketRegistry<senf::EtherTypes>::lookup( p->type_length(), nothrow ));
         return e ? e->factory() : no_factory();
     }
     if (p->type_length() <= 1500)
index 2aa6253..6f4e8ea 100644 (file)
@@ -57,12 +57,18 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::SNDUPacketType::nextPacketT
 {
     if (p.data().size() < 8)
         return no_factory();
-    PkReg_Entry const * e;
-    if (p->type() < 1536)
-        e = PacketRegistry<senf::ULEExtHeaderTypes>::lookup( p->type(), nothrow );
-    else
-        e = PacketRegistry<senf::EtherTypes>::lookup( p->type(), nothrow );
-    return e ? e->factory() : no_factory();
+    senf::PacketInterpreterBase::factory_t f (no_factory());
+    if (p->type() < 1536) {
+        PacketRegistry<senf::ULEExtHeaderTypes>::Entry const * e (
+            PacketRegistry<senf::ULEExtHeaderTypes>::lookup( p->type(), nothrow ));
+        if (e) f = e->factory();
+    }
+    else {
+        PacketRegistry<senf::EtherTypes>::Entry const * e (
+            PacketRegistry<senf::ULEExtHeaderTypes>::lookup( p->type(), nothrow ));
+        if (e) f = e->factory();
+    }
+    return f;
 }
 
 prefix_ senf::PacketInterpreterBase::optional_range
index a4fa3dc..da8a5bb 100644 (file)
@@ -31,9 +31,6 @@
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-prefix_  senf::PkReg_Entry::~PkReg_Entry()
-{}
-
 prefix_ senf::detail::PacketRegistryImplBase::~PacketRegistryImplBase()
 {}
 
index 0048815..40afa89 100644 (file)
 ///////////////////////////////ct.p////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::detail::PkReg_EntryImpl<PacketType>
+// senf::detail::PacketRegistryImpl<KeyType>::Entry
 
+template <class KeyType>
+prefix_ senf::detail::PacketRegistryImpl<KeyType>::Entry::Entry(KeyType const & key_,
+                                                                int priority_)
+    : key (key_), priority (priority_)
+{}
+
+template <class KeyType>
+prefix_ senf::detail::PacketRegistryImpl<KeyType>::Entry::~Entry()
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>
+
+template <class KeyType>
+template <class PacketType>
+prefix_ senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::
+EntryImpl(KeyType const & key, int priority)
+    : Entry (key, priority)
+{}
+
+template <class KeyType>
 template <class PacketType>
-prefix_ senf::PacketInterpreterBase::factory_t senf::detail::PkReg_EntryImpl<PacketType>::factory()
+prefix_ senf::Packet::factory_t
+senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::factory()
     const
 {
     return PacketType::factory();
 }
 
+template <class KeyType>
 template <class PacketType>
-prefix_ std::string senf::detail::PkReg_EntryImpl<PacketType>::name()
+prefix_ std::string senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::name()
     const
 {
     return prettyName(typeid(PacketType));
 }
 
+template <class KeyType>
 template <class PacketType>
-prefix_ senf::TypeIdValue senf::detail::PkReg_EntryImpl<PacketType>::typeIdValue()
+prefix_ std::type_info const &
+senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::type()
     const
 {
     return typeid(PacketType);
@@ -76,87 +101,71 @@ senf::PacketRegistry<Tag>::registry()
 
 template <class KeyType>
 template <class PacketType>
-prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key)
-{
-#ifndef SENF_DEBUG
-    registry_.insert(std::make_pair(key, Entry_ptr(new detail::PkReg_EntryImpl<PacketType>())));
-    reverseRegistry_.insert(std::make_pair(senf::typeIdValue<PacketType>(), key));
-#else
-    bool isUnique (
-        registry_.insert(
-            std::make_pair(key, Entry_ptr(new detail::PkReg_EntryImpl<PacketType>()))).second);
-    // If this assertion fails, a Packet was registered with an already known key
-    SENF_ASSERT( isUnique );
-    bool isNew (
-        reverseRegistry_.insert(
-            std::make_pair(senf::typeIdValue<PacketType>(), key)).second);
-    // If this assertion fails, the same Packet was registered with two different keys
-    SENF_ASSERT( isNew );
-#endif
+prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key, int priority)
+{
+    SENF_ASSERT(registry_.insert(
+                    typename Entry::ptr(new EntryImpl<PacketType>(key,priority))).second);
 }
 
 template <class KeyType>
 template <class PacketType>
 prefix_ void senf::detail::PacketRegistryImpl<KeyType>::unregisterPacket()
 {
-    typename PacketMap::iterator i (registry_.find(key(typeIdValue<PacketType>())));
-    typename ReversePacketMap::iterator j (reverseRegistry_.find(typeIdValue<PacketType>()));
-    if (i != registry_.end())
-        registry_.erase(i);
-    if (j != reverseRegistry_.end())
-        reverseRegistry_.erase(j);
+    registry_.template get<ByType>().erase(typeid(PacketType));
 }
 
 template <class KeyType>
-prefix_ void senf::detail::PacketRegistryImpl<KeyType>::unregisterPacket(key_t key)
+prefix_ void senf::detail::PacketRegistryImpl<KeyType>::unregisterPacket(key_t key, int priority)
 {
-    typename PacketMap::iterator i (registry_.find(key));
-    if (i == registry_.end())
-        throw PacketTypeNotRegisteredException();
-    typename ReversePacketMap::iterator j (reverseRegistry_.find(i->second->typeIdValue()));
-    registry_.erase(i);
-    if (j != reverseRegistry_.end())
-        reverseRegistry_.erase(j);
+    // Why doesn't this work:
+    // registry_.erase(boost::make_tuple(key,priority));
+    typename Registry::iterator i (registry_.find(boost::make_tuple(key,priority)));
+    if (i != registry_.end())
+        registry_.erase(i);
 }
 
 template <class KeyType>
 prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::key_t
 senf::detail::PacketRegistryImpl<KeyType>::key(senf::TypeIdValue const & type)
 {
-    typename ReversePacketMap::iterator i (reverseRegistry_.find(type));
-    if (i==reverseRegistry_.end())
+    boost::optional<KeyType> k (key(type,true));
+    if (! k)
         throw PacketTypeNotRegisteredException();
-    return i->second;
+    return *k;
 }
 
 template <class KeyType>
 prefix_ boost::optional<typename senf::detail::PacketRegistryImpl<KeyType>::key_t>
 senf::detail::PacketRegistryImpl<KeyType>::key(senf::TypeIdValue const & type, bool)
 {
-    typename ReversePacketMap::iterator i (reverseRegistry_.find(type));
-    if (i==reverseRegistry_.end())
+    typedef typename Registry::template index<ByType>::type TypeIndex;
+    TypeIndex const & typeIndex (registry_.template get<ByType>());
+    typename TypeIndex::const_iterator i (typeIndex.find(type.id()));
+    if (i == typeIndex.end())
         return boost::optional<key_t>();
-    return i->second;
+    return (*i)->key;
 }
 
 template <class KeyType>
 prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::Entry const &
 senf::detail::PacketRegistryImpl<KeyType>::lookup(key_t key)
 {
-    typename PacketMap::iterator i (registry_.find(key));
-    if (i==registry_.end())
+    Entry const * e (lookup(key, true));
+    if (!e)
         throw PacketTypeNotRegisteredException();
-    return *(i->second);
+    return *e;
 }
 
 template <class KeyType>
 prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::Entry const *
 senf::detail::PacketRegistryImpl<KeyType>::lookup(key_t key, bool)
 {
-    typename PacketMap::iterator i (registry_.find(key));
-    if (i==registry_.end())
+    typedef typename Registry::template index<ByKey>::type KeyIndex;
+    KeyIndex const & keyIndex (registry_.template get<ByKey>());
+    typename KeyIndex::const_iterator i (keyIndex.lower_bound(key));
+    if (i == keyIndex.end() || (*i)->key != key)
         return 0;
-    return i->second.get();
+    return i->get();
 }
 
 template <class KeyType>
@@ -170,12 +179,13 @@ template <class KeyType>
 prefix_ void senf::detail::PacketRegistryImpl<KeyType>::v_dump(std::ostream & os)
     const
 {
-    typename PacketMap::const_iterator i (registry_.begin());
-    typename PacketMap::const_iterator const i_end (registry_.end());
-    for (; i != i_end; ++i) {
-        std::string n (i->second->name());
-        senf::detail::DumpKey<KeyType>::dump(i->first, os);
-        os << ' ' << n.substr(21,n.size()-22) << "\n";
+    typedef typename Registry::template index<ByKey>::type KeyIndex;
+    KeyIndex const & keyIndex (registry_.template get<ByKey>());
+    for (typename KeyIndex::iterator i (keyIndex.begin()), i_end (keyIndex.end());
+         i != i_end; ++i) {
+        std::string n ((*i)->name());
+        senf::detail::DumpKey<KeyType>::dump((*i)->key, os);
+        os << ' ' << std::setw(6) << (*i)->priority << ' ' << n.substr(21,n.size()-22) << '\n';
     }
 }
 
@@ -183,7 +193,6 @@ template <class KeyType>
 prefix_ void senf::detail::PacketRegistryImpl<KeyType>::v_clear()
 {
     registry_.clear();
-    reverseRegistry_.clear();
 }
 
 ///////////////////////////////////////////////////////////////////////////
index a99c59b..dd19e9a 100644 (file)
@@ -103,14 +103,15 @@ senf::PacketRegistry<Tag>::key(Packet const & packet, NoThrow_t)
 }
 
 template <class Tag>
-prefix_ senf::PkReg_Entry const & senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key)
+prefix_ typename senf::PacketRegistry<Tag>::Entry const &
+senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key)
 {
     return registry().lookup(key);
 }
 
 template <class Tag>
-prefix_ senf::PkReg_Entry const * senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key,
-                                                                    NoThrow_t)
+prefix_ typename senf::PacketRegistry<Tag>::Entry const *
+senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key, NoThrow_t)
 {
     return registry().lookup(key,true);
 }
@@ -141,8 +142,7 @@ prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::iterator
 senf::detail::PacketRegistryImpl<KeyType>::begin()
     const
 {
-    return boost::make_transform_iterator(
-        registry_.begin(), ::__gnu_cxx::select1st<typename PacketMap::value_type>());
+    return registry_.begin();
 }
 
 template <class KeyType>
@@ -150,8 +150,7 @@ prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::iterator
 senf::detail::PacketRegistryImpl<KeyType>::end()
     const
 {
-    return boost::make_transform_iterator(
-        registry_.end(), ::__gnu_cxx::select1st<typename PacketMap::value_type>());
+    return registry_.end();
 }
 
 ///////////////////////////////PacketRegistry..e///////////////////////////////////////
index e766914..beb3384 100644 (file)
@@ -91,6 +91,7 @@ namespace senf {
     {
     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
 
@@ -180,13 +181,13 @@ 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
          */
index a1d66ba..e2b0e48 100644 (file)
 // Custom includes
 #include <ext/functional>
 #include <limits>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/composite_key.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/mem_fun.hpp>
 #include <boost/intrusive_ptr.hpp>
 #include <boost/iterator/transform_iterator.hpp>
 #include <senf/Utils/TypeIdValue.hh>
 ///////////////////////////////ih.p////////////////////////////////////////
 
 namespace senf {
-
-    /** \brief Registry entry
-
-        Value returned by a registry lookup
-     */
-    struct PkReg_Entry
-        : public intrusive_refcount
-    {
-        virtual ~PkReg_Entry();
-        virtual Packet::factory_t factory() const = 0;
-                                        ///< Get factory of the registered packet type
-        virtual std::string name() const = 0;
-        virtual TypeIdValue typeIdValue() const = 0;
-    };
-
 namespace detail {
 
-    /** \brief Internal: Registry entry implementation for a specific packet type
-
-        \internal
-     */
-    template <class PacketType>
-    struct PkReg_EntryImpl
-        : public PkReg_Entry
+    struct TypeInfoCompare
     {
-        virtual Packet::factory_t factory() const;
-        virtual std::string name() const;
-        virtual TypeIdValue typeIdValue() const ;
+        bool operator()(std::type_info const & a, std::type_info const & b) const
+            { return a.before(b); }
     };
 
     /** \brief Internal: Registry implementation base-class and registry of registries
@@ -99,19 +82,61 @@ namespace detail {
     {
     public:
         typedef KeyType key_t;
-        typedef PkReg_Entry Entry;
+
+        struct Entry : public intrusive_refcount
+        {
+            typedef boost::intrusive_ptr<Entry> ptr;
+
+            Entry(KeyType const & key_, int priority_);
+            virtual ~Entry();
+
+            virtual Packet::factory_t factory() const = 0;
+
+            virtual std::string name() const = 0;
+            virtual std::type_info const & type() const = 0;
+
+            KeyType key;
+            int priority;
+        };
 
     private:
-        typedef boost::intrusive_ptr<Entry> Entry_ptr;
-        typedef std::map<key_t, Entry_ptr> PacketMap;
-        typedef std::map<senf::TypeIdValue, key_t> ReversePacketMap;
+        struct ByKey {};
+        struct ByType {};
+
+        struct RegistryIndices
+            : public boost::multi_index::indexed_by<
+                boost::multi_index::ordered_unique<
+                    boost::multi_index::tag<ByKey>,
+                    boost::multi_index::composite_key<
+                        Entry,
+                        boost::multi_index::member<Entry,KeyType,&Entry::key>,
+                        boost::multi_index::member<Entry,int,&Entry::priority> >,
+                    boost::multi_index::composite_key_compare<
+                        std::less<KeyType>,
+                        std::greater<int> > >,
+                boost::multi_index::ordered_unique<
+                    boost::multi_index::tag<ByType>,
+                    boost::multi_index::mem_fun<Entry const,std::type_info const &,&Entry::type>,
+                    TypeInfoCompare> >
+        {};
+
+        typedef boost::multi_index_container<typename Entry::ptr, RegistryIndices> Registry;
+
+        template <class PacketType>
+        struct EntryImpl : public Entry
+        {
+            EntryImpl(KeyType const & key, int priority);
+
+            virtual Packet::factory_t factory() const;
+            virtual std::string name() const;
+            virtual std::type_info const & type() const;
+        };
 
     public:
         ///////////////////////////////////////////////////////////////////////////
         // Types
 
-        typedef boost::transform_iterator< ::__gnu_cxx::select1st<typename PacketMap::value_type>,
-                                           typename PacketMap::const_iterator > iterator;
+        typedef typename Registry::template index<ByKey>::type::const_iterator iterator;
 
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
@@ -123,11 +148,11 @@ namespace detail {
         ///////////////////////////////////////////////////////////////////////////
 
         template <class PacketType>
-        void registerPacket(key_t key);
+        void registerPacket(key_t key, int priority=0);
 
         template <class PacketType>
         void unregisterPacket();
-        void unregisterPacket(key_t key);
+        void unregisterPacket(key_t key, int priority=0);
 
         key_t key(senf::TypeIdValue const & type);
         boost::optional<key_t> key(senf::TypeIdValue const & type, bool);
@@ -145,8 +170,7 @@ namespace detail {
         virtual void v_dump(std::ostream & os) const;
         virtual void v_clear();
 
-        PacketMap registry_;
-        ReversePacketMap reverseRegistry_;
+        Registry registry_;
     };
 
     template <class KeyType, bool is_integral=std::numeric_limits<KeyType>::is_integer>
index ddb1088..321e19a 100644 (file)
@@ -83,14 +83,28 @@ SENF_AUTO_UNIT_TEST(packetRegistry_test)
         BOOST_CHECK( PacketRegistry<BaseTag>::lookup(1u, senf::nothrow) );
 
         unsigned elts1[] = { 1u, 2u };
-        BOOST_CHECK_EQUAL_COLLECTIONS( PacketRegistry<BaseTag>::begin(),
-                                       PacketRegistry<BaseTag>::end(),
-                                       elts1+0, elts1+sizeof(elts1)/sizeof(elts1[0]) );
+        BOOST_CHECK_EQUAL_COLLECTIONS(
+            boost::make_transform_iterator(
+                PacketRegistry<BaseTag>::begin(),
+                boost::multi_index::member<senf::PacketRegistry<BaseTag>::Entry, unsigned,
+                                           &senf::PacketRegistry<BaseTag>::Entry::key>()),
+            boost::make_transform_iterator(
+                PacketRegistry<BaseTag>::end(),
+                boost::multi_index::member<senf::PacketRegistry<BaseTag>::Entry, unsigned,
+                                           &senf::PacketRegistry<BaseTag>::Entry::key>()),
+            elts1+0, elts1+sizeof(elts1)/sizeof(elts1[0]) );
 
         std::string elts2[] = { "bar", "foo" };
-        BOOST_CHECK_EQUAL_COLLECTIONS( PacketRegistry<StringTag>::begin(),
-                                       PacketRegistry<StringTag>::end(),
-                                       elts2+0, elts2+sizeof(elts2)/sizeof(elts2[0]) );
+        BOOST_CHECK_EQUAL_COLLECTIONS(
+            boost::make_transform_iterator(
+                PacketRegistry<StringTag>::begin(),
+                boost::multi_index::member<senf::PacketRegistry<StringTag>::Entry, std::string,
+                                           &senf::PacketRegistry<StringTag>::Entry::key>()),
+            boost::make_transform_iterator(
+                PacketRegistry<StringTag>::end(),
+                boost::multi_index::member<senf::PacketRegistry<StringTag>::Entry, std::string,
+                                           &senf::PacketRegistry<StringTag>::Entry::key>()),
+            elts2+0, elts2+sizeof(elts2)/sizeof(elts2[0]) );
 
         std::stringstream s;
         senf::dumpPacketRegistries(s);
@@ -98,15 +112,15 @@ SENF_AUTO_UNIT_TEST(packetRegistry_test)
             contains,
             (s.str())
             ("(anonymous namespace)::BaseTag:\n"
-             "  0x00000001 (         1) (....) (anonymous namespace)::FooPacketType\n"
-             "  0x00000002 (         2) (....) (anonymous namespace)::BarPacketType\n"
+             "  0x00000001 (         1) (....)      0 (anonymous namespace)::FooPacketType\n"
+             "  0x00000002 (         2) (....)      0 (anonymous namespace)::BarPacketType\n"
              "\n"));
         BOOST_CHECK_PREDICATE(
             contains,
             (s.str())
             ("(anonymous namespace)::StringTag:\n"
-             "  bar              (anonymous namespace)::BarPacketType\n"
-             "  foo              (anonymous namespace)::FooPacketType\n"
+             "  bar                   0 (anonymous namespace)::BarPacketType\n"
+             "  foo                   0 (anonymous namespace)::FooPacketType\n"
              "\n" ));
     }
 
@@ -117,14 +131,14 @@ SENF_AUTO_UNIT_TEST(packetRegistry_test)
             contains,
             (s.str())
             ("(anonymous namespace)::BaseTag:\n"
-             "  0x00000001 (         1) (....) (anonymous namespace)::FooPacketType\n"
+             "  0x00000001 (         1) (....)      0 (anonymous namespace)::FooPacketType\n"
              "\n"));
         BOOST_CHECK_PREDICATE(
             contains,
             (s.str())
             ("(anonymous namespace)::StringTag:\n"
-             "  bar              (anonymous namespace)::BarPacketType\n"
-             "  foo              (anonymous namespace)::FooPacketType\n"
+             "  bar                   0 (anonymous namespace)::BarPacketType\n"
+             "  foo                   0 (anonymous namespace)::FooPacketType\n"
              "\n" ));
 
         SENF_CHECK_NO_THROW( PacketRegistry<BaseTag>::unregisterPacket(1u) );
@@ -140,7 +154,7 @@ SENF_AUTO_UNIT_TEST(packetRegistry_test)
             contains,
             (s.str())
             ("(anonymous namespace)::StringTag:\n"
-             "  foo              (anonymous namespace)::FooPacketType\n"
+             "  foo                   0 (anonymous namespace)::FooPacketType\n"
              "\n" ));
     }
 }
index 1b7e693..fe4bdce 100644 (file)
@@ -83,7 +83,8 @@ senf::PacketTypeMixin<Self,Registry>::key(Packet const & p)
 template <class Self, class Registry>
 prefix_ senf::PacketTypeBase::factory_t senf::PacketTypeMixin<Self,Registry>::lookup(key_t key)
 {
-    PkReg_Entry const * entry (PacketRegistry<Registry>::lookup( key, senf::nothrow ));
+    typename PacketRegistry<Registry>::Entry const * entry (
+        PacketRegistry<Registry>::lookup( key, senf::nothrow ));
     return entry ? entry->factory() : PacketTypeBase::no_factory();
 }