Packets: Packet Registry unregister() support
g0dil [Tue, 4 May 2010 22:12:40 +0000 (22:12 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1619 270642c3-0616-0410-b53a-bc976706d245

.project.el
senf/Packets/PacketRegistry.ct
senf/Packets/PacketRegistry.cti
senf/Packets/PacketRegistry.hh
senf/Packets/PacketRegistry.ih
senf/Packets/PacketRegistry.test.cc

index b691d2a..307ad27 100644 (file)
@@ -71,8 +71,8 @@ checks for C/C++ preproc directives. Additionally, anything after ^L
 is ignored (Those are the file local variables and local words)."
   (let ((f (get-text-property (point) 'face)))
     (and (memq f flyspell-prog-text-faces)
-         (not (save-excursion 
-                (beginning-of-line) 
+         (not (save-excursion
+                (beginning-of-line)
                 (looking-at "\\(//\\)?#")))
          (not (let ((l (max (point-min) (- (point-max) 4096))))
                 (and (< l (point))
@@ -101,7 +101,10 @@ is ignored (Those are the file local variables and local words)."
 
 (add-hook 'ccide-new-file-hooks 'senf-new-file-hook nil t)
 
+(setq indent-tabs-mode nil) ;; needed since whitespace-mode caches this value ...
+(whitespace-mode 1)
+
 \f
-// Local Variables:
-// indent-tabs-mode: nil
-// End:
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
index b4babcc..0048815 100644 (file)
@@ -53,6 +53,13 @@ prefix_ std::string senf::detail::PkReg_EntryImpl<PacketType>::name()
     return prettyName(typeid(PacketType));
 }
 
+template <class PacketType>
+prefix_ senf::TypeIdValue senf::detail::PkReg_EntryImpl<PacketType>::typeIdValue()
+    const
+{
+    return typeid(PacketType);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::PacketRegistry<Tag>
 
@@ -89,6 +96,30 @@ prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key
 }
 
 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);
+}
+
+template <class KeyType>
+prefix_ void senf::detail::PacketRegistryImpl<KeyType>::unregisterPacket(key_t key)
+{
+    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);
+}
+
+template <class KeyType>
 prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::key_t
 senf::detail::PacketRegistryImpl<KeyType>::key(senf::TypeIdValue const & type)
 {
index 2a519b5..a99c59b 100644 (file)
@@ -41,6 +41,17 @@ RegistrationProxy(typename Tag::key_t key)
     PacketRegistry<Tag>::template registerPacket<PacketType>(key);
 }
 
+template <class Tag>
+template <class PacketType>
+prefix_ senf::PacketRegistry<Tag>::RegistrationProxy<PacketType>::~RegistrationProxy()
+{
+    try {
+        PacketRegistry<Tag>::template unregisterPacket<PacketType>();
+    }
+    catch (PacketTypeNotRegisteredException & ex)
+    {}
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::PacketRegistry<Tag>
 
@@ -53,6 +64,19 @@ prefix_ void senf::PacketRegistry<Tag>::registerPacket(typename Tag::key_t key)
 
 template <class Tag>
 template <class PacketType>
+prefix_ void senf::PacketRegistry<Tag>::unregisterPacket()
+{
+    registry().unregisterPacket<PacketType>();
+}
+
+template <class Tag>
+prefix_ void senf::PacketRegistry<Tag>::unregisterPacket(typename Tag::key_t key)
+{
+    registry().unregisterPacket(key);
+}
+
+template <class Tag>
+template <class PacketType>
 prefix_ typename Tag::key_t senf::PacketRegistry<Tag>::key()
 {
     return registry().key(senf::typeIdValue<PacketType>());
index fe21ab5..e766914 100644 (file)
@@ -109,6 +109,7 @@ namespace senf {
         struct RegistrationProxy
         {
             RegistrationProxy(typename Tag::key_t key);
+            ~RegistrationProxy();
         };
 
         /** \brief Register new packet type
@@ -126,6 +127,10 @@ namespace senf {
         template <class PacketType>
         static void registerPacket(typename Tag::key_t key);
 
+        template <class PacketType>
+        static void unregisterPacket();
+        static void unregisterPacket(typename Tag::key_t key);
+
         /** \brief Find key of a packet type
 
             Return the key of \a PacketType as registered in the \a Tag registry
@@ -245,4 +250,3 @@ namespace senf {
 // compile-command: "scons -u test"
 // comment-column: 40
 // End:
-
index 169d275..a1d66ba 100644 (file)
@@ -48,6 +48,7 @@ namespace senf {
         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 {
@@ -62,6 +63,7 @@ namespace detail {
     {
         virtual Packet::factory_t factory() const;
         virtual std::string name() const;
+        virtual TypeIdValue typeIdValue() const ;
     };
 
     /** \brief Internal: Registry implementation base-class and registry of registries
@@ -123,6 +125,10 @@ namespace detail {
         template <class PacketType>
         void registerPacket(key_t key);
 
+        template <class PacketType>
+        void unregisterPacket();
+        void unregisterPacket(key_t key);
+
         key_t key(senf::TypeIdValue const & type);
         boost::optional<key_t> key(senf::TypeIdValue const & type, bool);
 
index 9c596e9..ddb1088 100644 (file)
@@ -56,48 +56,93 @@ namespace {
     struct OtherPacketType : public PacketTypeBase {};
     typedef senf::ConcretePacket<OtherPacketType> OtherPacket;
 
+    bool contains(std::string a, std::string b)
+    { return a.find(b) != std::string::npos; }
+
+    bool contains_not(std::string a, std::string b)
+    { return a.find(b) == std::string::npos; }
+
 }
 
 SENF_PACKET_REGISTRY_REGISTER(StringTag, "foo", FooPacket);
-SENF_PACKET_REGISTRY_REGISTER(StringTag, "bar", BarPacket);
 
 SENF_AUTO_UNIT_TEST(packetRegistry_test)
 {
-    PacketRegistry<BaseTag>::registerPacket<FooPacket>(1u);
-    PacketRegistry<BaseTag>::registerPacket<BarPacket>(2u);
-
-    BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<FooPacket>(), 1u );
-    BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<BarPacket>(), 2u );
-    BOOST_CHECK_THROW( PacketRegistry<BaseTag>::key<OtherPacket>(),
-                       PacketTypeNotRegisteredException );
-
-    BOOST_CHECK_EQUAL( PacketRegistry<StringTag>::key<FooPacket>(), "foo" );
-    BOOST_CHECK( ! PacketRegistry<StringTag>::lookup("blub", senf::nothrow) );
-    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]) );
-
-    std::string elts2[] = { "bar", "foo" };
-    BOOST_CHECK_EQUAL_COLLECTIONS( PacketRegistry<StringTag>::begin(), PacketRegistry<StringTag>::end(),
-                                   elts2+0, elts2+sizeof(elts2)/sizeof(elts2[0]) );
-
-    std::stringstream s;
-    senf::dumpPacketRegistries(s);
-    BOOST_CHECK_EQUAL( s.str(),
-                       "(anonymous namespace)::BaseTag:\n"
-                       "  0x00000001 (         1) (....) (anonymous namespace)::FooPacketType\n"
-                       "  0x00000002 (         2) (....) (anonymous namespace)::BarPacketType\n"
-                       "\n"
-                       "(anonymous namespace)::RegTag:\n"
-                       "  0x00000001 (         1) (....) (anonymous namespace)::FooPacketType\n"
-                       "  0x00000002 (         2) (....) (anonymous namespace)::BarPacketType\n"
-                       "\n"
-                       "(anonymous namespace)::StringTag:\n"
-                       "  bar              (anonymous namespace)::BarPacketType\n"
-                       "  foo              (anonymous namespace)::FooPacketType\n"
-                       "\n" );
+    {
+        PacketRegistry<StringTag>::registerPacket<BarPacket>("bar");
+        PacketRegistry<BaseTag>::registerPacket<FooPacket>(1u);
+        senf::PacketRegistry<BaseTag>::RegistrationProxy<BarPacket> registerBarInBase (2u);
+
+        BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<FooPacket>(), 1u );
+        BOOST_CHECK_EQUAL( PacketRegistry<BaseTag>::key<BarPacket>(), 2u );
+        BOOST_CHECK_THROW( PacketRegistry<BaseTag>::key<OtherPacket>(),
+                           PacketTypeNotRegisteredException );
+
+        BOOST_CHECK_EQUAL( PacketRegistry<StringTag>::key<FooPacket>(), "foo" );
+        BOOST_CHECK( ! PacketRegistry<StringTag>::lookup("blub", senf::nothrow) );
+        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]) );
+
+        std::string elts2[] = { "bar", "foo" };
+        BOOST_CHECK_EQUAL_COLLECTIONS( PacketRegistry<StringTag>::begin(),
+                                       PacketRegistry<StringTag>::end(),
+                                       elts2+0, elts2+sizeof(elts2)/sizeof(elts2[0]) );
+
+        std::stringstream s;
+        senf::dumpPacketRegistries(s);
+        BOOST_CHECK_PREDICATE(
+            contains,
+            (s.str())
+            ("(anonymous namespace)::BaseTag:\n"
+             "  0x00000001 (         1) (....) (anonymous namespace)::FooPacketType\n"
+             "  0x00000002 (         2) (....) (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"
+             "\n" ));
+    }
+
+    {
+        std::stringstream s;
+        senf::dumpPacketRegistries(s);
+        BOOST_CHECK_PREDICATE(
+            contains,
+            (s.str())
+            ("(anonymous namespace)::BaseTag:\n"
+             "  0x00000001 (         1) (....) (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"
+             "\n" ));
+
+        SENF_CHECK_NO_THROW( PacketRegistry<BaseTag>::unregisterPacket(1u) );
+        SENF_CHECK_NO_THROW( PacketRegistry<StringTag>::unregisterPacket<BarPacket>() );
+
+        s.str("");
+        senf::dumpPacketRegistries(s);
+        BOOST_CHECK_PREDICATE(
+            contains_not,
+            (s.str())
+            ("(anonymous namespace)::BaseTag:\n"));
+        BOOST_CHECK_PREDICATE(
+            contains,
+            (s.str())
+            ("(anonymous namespace)::StringTag:\n"
+             "  foo              (anonymous namespace)::FooPacketType\n"
+             "\n" ));
+    }
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////