Packets: Keep annotation registry sorted by type name
g0dil [Wed, 11 Aug 2010 18:30:43 +0000 (18:30 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1677 270642c3-0616-0410-b53a-bc976706d245

senf/Packets/Packet.test.cc
senf/Packets/PacketImpl.cc
senf/Packets/PacketImpl.cci
senf/Packets/PacketImpl.ct
senf/Packets/PacketImpl.cti
senf/Packets/PacketImpl.hh
senf/Packets/PacketImpl.ih
senf/Packets/PacketInterpreter.cc

index e735207..2dafae1 100644 (file)
@@ -29,6 +29,7 @@
 // Custom includes
 #include <sstream>
 #include <boost/static_assert.hpp>
+#include <boost/cstdint.hpp>
 #include "Packets.hh"
 
 #include <senf/Utils/auto_unit_test.hh>
@@ -111,7 +112,7 @@ namespace {
     }
 
     struct IntAnnotation {
-        unsigned value;
+        boost::uint32_t value;
     };
 
     std::ostream & operator<<(std::ostream & os, IntAnnotation const & v)
@@ -128,7 +129,7 @@ namespace {
     {
         ComplexAnnotation() : s(), i() {}
         std::string s;
-        int i;
+        boost::int32_t i;
     };
 
     std::ostream & operator<<(std::ostream & os, ComplexAnnotation const & v)
@@ -343,11 +344,11 @@ SENF_AUTO_UNIT_TEST(packetAnnotation)
         ss.str(),
         "SENF_PACKET_ANNOTATION_SLOTS = 8\n"
         "SENF_PACKET_ANNOTATION_SLOTSIZE = 16\n"
-        "SLOT  TYPE                                                      COMPLEX   SIZE\n"
-        "      (anonymous namespace)::ComplexEmptyAnnotation             yes          1\n"
-        "      (anonymous namespace)::ComplexAnnotation                  yes          8\n"
-        "      (anonymous namespace)::LargeAnnotation                    no          32\n"
-        "   0  (anonymous namespace)::IntAnnotation                      no           4\n" );
+        "TYPE                                                      FAST  COMPLEX   SIZE\n"
+        "(anonymous namespace)::ComplexAnnotation                  no    yes          8\n"
+        "(anonymous namespace)::ComplexEmptyAnnotation             no    yes          1\n"
+        "(anonymous namespace)::IntAnnotation                      yes   no           4\n"
+        "(anonymous namespace)::LargeAnnotation                    no    no          32\n" );
 #endif
 }
 
index 4bb7eee..9444ab7 100644 (file)
@@ -27,6 +27,8 @@
 
 // Custom includes
 #include <iterator>
+#include <map>
+#include <string>
 #include <boost/format.hpp>
 #include <senf/Utils/String.hh>
 #include "Packets.hh"
@@ -133,25 +135,23 @@ prefix_ void senf::detail::PacketImpl::updateIterators(PacketData * self, differ
 
 prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
 {
-    for (AnnotationRegistry::key_t key (AnnotationRegistry::instance().keyBegin());
-         key != AnnotationRegistry::instance().keyEnd(); ++key) {
-        void * antn (annotation(key));
+    for (AnnotationRegistry::iterator i (AnnotationRegistry::instance().begin());
+         i != AnnotationRegistry::instance().end(); ++i) {
+        void * antn (annotation(*i));
         if (antn)
-            AnnotationRegistry::instance().dump(key, os, antn);
+            AnnotationRegistry::instance().dump(*i, os, antn);
     }
 }
 
-prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_t key)
+prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_type key)
 {
-    SENF_ASSERT( key<0, "complexAnnotation called with invalid key");
+    SENF_ASSERT( key < 0, "complexAnnotation called with invalid key");
 #ifdef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
     return 0;
 #else
-    while (complexAnnotations_.size() < ComplexAnnotations::size_type(-key))
-        complexAnnotations_.push_back(0);
-    if (complexAnnotations_.is_null(-key-1))
-        return 0;
-    return complexAnnotations_[-key-1].get();
+    return (ComplexAnnotations::size_type(-key-1) >= complexAnnotations_.size()
+            || complexAnnotations_.is_null(-key-1))
+        ? 0 : complexAnnotations_[-key-1].get();
 #endif
 }
 
@@ -161,16 +161,18 @@ prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::k
 prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
 {
 #ifdef SENF_DEBUG
-    boost::format fmt ("%4.4s  %-56.56s  %-7.7s  %5d\n");
+    boost::format fmt ("%-56.56s  %-4.4s  %-7.7s  %5d\n");
     os << "SENF_PACKET_ANNOTATION_SLOTS = " << SENF_PACKET_ANNOTATION_SLOTS << "\n"
        << "SENF_PACKET_ANNOTATION_SLOTSIZE = " << SENF_PACKET_ANNOTATION_SLOTSIZE << "\n";
-    os << fmt % "SLOT" % "TYPE" % "COMPLEX" % "SIZE";
-    for (key_t key (keyBegin()); key != keyEnd(); ++key) {
-        std::string nm (name(key));
+    os << fmt % "TYPE" % "FAST" % "COMPLEX" % "SIZE";
+
+    for (Index::const_iterator i (index_.begin()), i_end (index_.end()); i != i_end; ++i) {
+        key_type key (i->second);
+        std::string nm (i->first);
         if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
         os << fmt
-            % (key >= 0 ? senf::str(key) : "")
             % nm
+            % (key >= 0 ? "yes" : "no")
             % (isComplex(key) ? "yes" : "no")
             % size(key);
     }
index 8c863d1..63c330c 100644 (file)
@@ -33,7 +33,7 @@
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::AnnotationRegistry
 
-prefix_ void senf::detail::AnnotationRegistry::dump(key_t key, std::ostream & os,
+prefix_ void senf::detail::AnnotationRegistry::dump(key_type key, std::ostream & os,
                                                     void * annotation)
     const
 {
@@ -45,27 +45,41 @@ prefix_ void senf::detail::AnnotationRegistry::dump(key_t key, std::ostream & os
     }
 }
 
-prefix_ std::string senf::detail::AnnotationRegistry::name(key_t key)
+prefix_ std::string senf::detail::AnnotationRegistry::name(key_type key)
     const
 {
     Registry::const_iterator i (registry_.find(key));
     return i == registry_.end() ? "" : i->second->v_name();
 }
 
-prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_t key)
+prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_type key)
     const
 {
     Registry::const_iterator i (registry_.find(key));
     return i != registry_.end() && i->second->v_isComplex();
 }
 
-prefix_ unsigned senf::detail::AnnotationRegistry::size(key_t key)
+prefix_ unsigned senf::detail::AnnotationRegistry::size(key_type key)
     const
 {
     Registry::const_iterator i (registry_.find(key));
     return i == registry_.end() ? 0 : i->second->v_size();
 }
 
+prefix_ senf::detail::AnnotationRegistry::iterator senf::detail::AnnotationRegistry::begin()
+    const
+{
+    return boost::make_transform_iterator(index_.begin(),
+                                          __gnu_cxx::select2nd<Index::value_type>());
+}
+
+prefix_ senf::detail::AnnotationRegistry::iterator senf::detail::AnnotationRegistry::end()
+    const
+{
+    return boost::make_transform_iterator(index_.end(),
+                                          __gnu_cxx::select2nd<Index::value_type>());
+}
+
 prefix_ senf::detail::AnnotationRegistry::AnnotationRegistry()
     : simpleAnnotationCount_ (0), complexAnnotationCount_ (0)
 {}
@@ -234,7 +248,7 @@ prefix_ void senf::detail::PacketImpl::release(refcount_t n)
 
 // Annotations
 
-prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_t key)
+prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_type key)
 {
     return key >= 0 ? & simpleAnnotations_[key] : complexAnnotation(key);
 }
index 7dc7cb9..93a757c 100644 (file)
@@ -35,16 +35,18 @@ senf::detail::AnnotationRegistry::RegistrationProxy<Annotation>
     senf::detail::AnnotationRegistry::Entry<Annotation>::proxy_;
 
 template <class Annotation>
-senf::detail::AnnotationRegistry::key_t
+senf::detail::AnnotationRegistry::key_type
     senf::detail::AnnotationRegistry::Entry<Annotation>::key_;
 
 template <class Annotation>
 prefix_ void * senf::detail::PacketImpl::complexAnnotation()
 {
-    AnnotationRegistry::key_t key (AnnotationRegistry::lookup<Annotation>());
+    AnnotationRegistry::key_type key (AnnotationRegistry::lookup<Annotation>());
     void * rv (complexAnnotation(key));
 #ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
     if (! rv) {
+        while (complexAnnotations_.size() < ComplexAnnotations::size_type(-key))
+            complexAnnotations_.push_back(0);
         complexAnnotations_.replace(-key-1, new AnnotationRegistry::Entry<Annotation>());
         rv = complexAnnotations_[-key-1].get();
     }
index 308e7b3..0627756 100644 (file)
 // senf::detail::AnnotationRegistry
 
 template <class Annotation>
-prefix_ key_t senf::detail::AnnotationRegistry::registerAnnotation()
+prefix_ senf::detail::AnnotationRegistry::key_type
+senf::detail::AnnotationRegistry::registerAnnotation()
 {
-    key_t key (simpleAnnotationCount_ >= SENF_PACKET_ANNOTATION_SLOTS
+    key_type key (simpleAnnotationCount_ >= SENF_PACKET_ANNOTATION_SLOTS
                || IsComplexAnnotation<Annotation>::value
                ? - ++complexAnnotationCount_
                : simpleAnnotationCount_ ++);
-    registry_.insert(key, new Registration<Annotation>());
-    std::cerr << ">> allocated key " << key
-              << " for " << prettyName(typeid(Annotation))
-              << "(complex: " << IsComplexAnnotation<Annotation>::value
-              << ", convertible: " << boost::is_convertible<Annotation*, ComplexAnnotation*>::value
-              << ", size: " << sizeof(Annotation)
-              << ", max: " << SENF_PACKET_ANNOTATION_SLOTSIZE << ")" << std::endl;
+    std::pair<Registry::iterator, bool> reg (
+        registry_.insert(key, new Registration<Annotation>()));
+    SENF_ASSERT(reg.second, "internal error: duplicate annotation key");
+    index_.insert(std::make_pair(reg.first->second->v_name(), key));
     return key;
 }
 
 template <class Annotation>
-prefix_ key_t senf::detail::AnnotationRegistry::lookup()
+prefix_ senf::detail::AnnotationRegistry::key_type senf::detail::AnnotationRegistry::lookup()
 {
-    SENF_ASSERT( instance().keyBegin() <= AnnotationRegistry::Entry<Annotation>::key()
-                 && AnnotationRegistry::Entry<Annotation>::key() < instance().keyEnd(),
-                 "internal error: annotation key not registered" );
-    SENF_ASSERT( AnnotationRegistry::Entry<Annotation>::key() < 0
-                 || ! IsComplexAnnotation<Annotation>::value,
-                 "internal error: complex annotation registered with invalid key" );
-    SENF_ASSERT( AnnotationRegistry::Entry<Annotation>::key() < SENF_PACKET_ANNOTATION_SLOTS,
-                 "internal error: annotation key out of valid range" );
+    SENF_ASSERT(
+        -instance().complexAnnotationCount_ <= AnnotationRegistry::Entry<Annotation>::key()
+        && AnnotationRegistry::Entry<Annotation>::key() < instance().simpleAnnotationCount_,
+        "internal error: annotation key not registered" );
+    SENF_ASSERT(
+        AnnotationRegistry::Entry<Annotation>::key() < 0
+        || ! IsComplexAnnotation<Annotation>::value,
+        "internal error: complex annotation registered with invalid key" );
+    SENF_ASSERT(
+        AnnotationRegistry::Entry<Annotation>::key() < SENF_PACKET_ANNOTATION_SLOTS,
+        "internal error: annotation key out of valid range" );
     return AnnotationRegistry::Entry<Annotation>::key();
 }
 
-prefix_ key_t senf::detail::AnnotationRegistry::keyBegin()
-    const
-{
-    return -complexAnnotationCount_;
-}
-
-prefix_ key_t senf::detail::AnnotationRegistry::keyEnd()
-    const
-{
-    return simpleAnnotationCount_;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::PacketImpl
 
@@ -102,7 +91,7 @@ prefix_ senf::detail::PacketImpl::PacketImpl(InputIterator first, InputIterator
 template <class Annotation>
 prefix_ Annotation & senf::detail::PacketImpl::annotation()
 {
-    AnnotationRegistry::key_t key (AnnotationRegistry::lookup<Annotation>());
+    AnnotationRegistry::key_type key (AnnotationRegistry::lookup<Annotation>());
     void * antn (key >= 0 ? & simpleAnnotations_[key] : complexAnnotation<Annotation>());
     SENF_ASSERT( antn, "internal error: null annotation pointer" );
     return * static_cast<Annotation*>(antn);
index 3aa2964..fcdd71f 100644 (file)
@@ -154,8 +154,8 @@ namespace detail {
         void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
         void updateIterators(PacketData * self, difference_type pos, difference_type n);
 
-        void * annotation(AnnotationRegistry::key_t key); // may return 0 !
-        void * complexAnnotation(AnnotationRegistry::key_t key); // may return 0 !
+        void * annotation(AnnotationRegistry::key_type key); // may return 0 !
+        void * complexAnnotation(AnnotationRegistry::key_type key); // may return 0 !
         template <class Annotation>
         void * complexAnnotation();
 
index 06cb708..32ce82c 100644 (file)
 
 // Custom includes
 #include <iostream>
+#include <map>
 #include <string>
+#include <ext/functional>
+#include <boost/iterator/transform_iterator.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/mpl/sizeof.hpp>
 #include <boost/mpl/int.hpp>
@@ -61,38 +64,13 @@ namespace detail {
         : public senf::singleton<AnnotationRegistry>
     {
     public:
-        typedef int key_t;
-
-        using senf::singleton<AnnotationRegistry>::instance;
-
-        template <class Annotation> class RegistrationProxy;
-
-        class EntryBase;
-        template <class Annotation> class Entry;
-
-        template <class Annotation>
-        key_t registerAnnotation();
-
-        void dump(key_t key, std::ostream & os, void * annotation) const;
-        std::string name(key_t key) const;
-        bool isComplex(key_t key) const;
-        unsigned size(key_t key) const;
-
-        template <class Annotation>
-        static key_t lookup();
-
-        key_t keyBegin() const;
-        key_t keyEnd() const;
-
-        void dumpRegistrations(std::ostream & os);
+        typedef int key_type;
 
     private:
-        AnnotationRegistry();
-
         struct RegistrationBase
         {
             virtual ~RegistrationBase () {};
-            key_t key;
+            key_type key;
             virtual void v_dump(std::ostream & os, void * annotation) const = 0;
             virtual std::string v_name() const = 0;
             virtual bool v_isComplex() const = 0;
@@ -113,11 +91,49 @@ namespace detail {
                 { return sizeof(Annotation); }
         };
 
-        key_t simpleAnnotationCount_;
-        key_t complexAnnotationCount_;
+        typedef boost::ptr_map<key_type, RegistrationBase> Registry;
+        // Index must be a multi-map since two identically named classes
+        // both in the anonymous namespace both have the same demangled name.
+        // we could sort on the mangled name instead ...
+        typedef std::multimap<std::string, key_type> Index;
+
+    public:
+        typedef boost::transform_iterator< ::__gnu_cxx::select2nd<Index::value_type>,
+                                           Index::const_iterator > iterator;
+
+        using senf::singleton<AnnotationRegistry>::instance;
+
+        template <class Annotation> class RegistrationProxy;
+
+        class EntryBase;
+        template <class Annotation> class Entry;
+
+        template <class Annotation>
+        key_type registerAnnotation();
+
+        void dump(key_type key, std::ostream & os, void * annotation) const;
+        std::string name(key_type key) const;
+        bool isComplex(key_type key) const;
+        unsigned size(key_type key) const;
+
+        template <class Annotation>
+        static key_type lookup();
+
+        iterator begin() const;
+        iterator end() const;
+
+        void dumpRegistrations(std::ostream & os);
+
+    private:
+        AnnotationRegistry();
+
+        key_type simpleAnnotationCount_;
+        key_type complexAnnotationCount_;
 
-        typedef boost::ptr_map<key_t, RegistrationBase> Registry;
         Registry registry_;
+        // The index is needed to ensure a persistent and reproducible
+        // ordering of the annotations when dumping
+        Index index_;
 
         friend class senf::singleton<AnnotationRegistry>;
     };
@@ -146,10 +162,10 @@ namespace detail {
         : public AnnotationRegistry::EntryBase
     {
         static RegistrationProxy<Annotation> proxy_;
-        static AnnotationRegistry::key_t key_;
+        static AnnotationRegistry::key_type key_;
     public:
         // We use this member to force instantiation of proxy_ ...
-        static AnnotationRegistry::key_t key()
+        static AnnotationRegistry::key_type key()
             { senf::IGNORE(&proxy_); return key_; }
 
         virtual void * get() { return & annotation_; }
index 6fd279a..62b912c 100644 (file)
@@ -75,8 +75,8 @@ prefix_ senf::PacketInterpreterBase::ptr senf::PacketInterpreterBase::append(ptr
 prefix_ void senf::PacketInterpreterBase::dump(std::ostream & os)
 {
     try {
-        if (detail::AnnotationRegistry::instance().keyBegin()
-            != detail::AnnotationRegistry::instance().keyEnd()) {
+        if (detail::AnnotationRegistry::instance().begin()
+            != detail::AnnotationRegistry::instance().end()) {
             os << "Annotations:\n";
             impl().dumpAnnotations(os);
         }