Packets: New Annotation implementation
g0dil [Wed, 11 Aug 2010 14:08:19 +0000 (14:08 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1675 270642c3-0616-0410-b53a-bc976706d245

senf/Packets/Packet.test.cc
senf/Packets/PacketImpl.cc
senf/Packets/PacketImpl.cci
senf/Packets/PacketImpl.ct [new file with mode: 0644]
senf/Packets/PacketImpl.cti
senf/Packets/PacketImpl.hh
senf/Packets/PacketImpl.ih [new file with mode: 0644]
senf/Packets/PacketImpl.test.cc
senf/Packets/PacketInterpreter.cc
senf/config.hh

index a8cba98..5b318d1 100644 (file)
@@ -90,8 +90,8 @@ namespace {
         using mixin::init;
         static void dump(packet p, std::ostream & os) {
             os << "BarPacket:\n"
-               << "  type: " << p->type() << "\n"
-               << "  length: " << p->length() << "\n";
+               << senf::fieldName("type") << p->type() << "\n"
+               << senf::fieldName("length") << p->length() << "\n";
         }
         static void finalize(packet p) {
             if (p.next(senf::nothrow))
@@ -200,11 +200,10 @@ SENF_AUTO_UNIT_TEST(packet)
     packet.dump(s);
     BOOST_CHECK_EQUAL( s.str(),
                        "Annotations:\n"
-                       "  (anonymous namespace)::ComplexAnnotation: no value\n"
-                       "  (anonymous namespace)::IntAnnotation: 0\n"
+                       "  (anonymous namespace)::IntAnnotation : 0\n"
                        "BarPacket:\n"
-                       "  type: 0\n"
-                       "  length: 0\n" );
+                       "  type                    : 0\n"
+                       "  length                  : 0\n" );
 
     packet.finalizeAll();
     BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
@@ -315,6 +314,8 @@ SENF_AUTO_UNIT_TEST(packetAssign)
 
 SENF_AUTO_UNIT_TEST(packetAnnotation)
 {
+    typedef senf::detail::AnnotationRegistry Reg;
+
     senf::Packet packet (FooPacket::create());
     BarPacket::createAfter(packet);
 
@@ -329,10 +330,23 @@ SENF_AUTO_UNIT_TEST(packetAnnotation)
     BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
     BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
 
-    BOOST_CHECK( senf::detail::AnnotationIndexer<IntAnnotation>::Small );
-    BOOST_CHECK( ! senf::detail::AnnotationIndexer<LargeAnnotation>::Small );
-    BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexAnnotation>::Small );
-    BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexEmptyAnnotation>::Small );
+    BOOST_CHECK( Reg::lookup<IntAnnotation>() >= 0 );
+    BOOST_CHECK( Reg::lookup<LargeAnnotation>() < 0 );
+    BOOST_CHECK( Reg::lookup<ComplexAnnotation>() < 0 );
+    BOOST_CHECK( Reg::lookup<ComplexEmptyAnnotation>() < 0 );
+
+    std::stringstream ss;
+
+    senf::dumpPacketAnnotationRegistry(ss);
+    BOOST_CHECK_EQUAL(
+        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" );
 }
 
 #ifdef COMPILE_CHECK
index 4639a05..4bb7eee 100644 (file)
 /** \file
     \brief PacketImpl non-inline non-template implementation */
 
-//#include "PacketImpl.ih"
+#include "PacketImpl.ih"
 
 // Custom includes
 #include <iterator>
+#include <boost/format.hpp>
+#include <senf/Utils/String.hh>
 #include "Packets.hh"
 
 //#include "PacketImpl.mpp"
 ///////////////////////////////cc.p////////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationIndexerBase
-
-unsigned senf::detail::AnnotationIndexerBase::maxAnnotations (0);
-
-prefix_ void senf::detail::AnnotationIndexerBase::dump(PacketImpl * p, std::ostream & os)
-{
-    for(std::vector<AnnotationIndexerBase*>::const_iterator
-            i (registry().begin()), i_end (registry().end());
-        i != i_end; ++i)
-        (*i)->v_dump(p,os);
-}
-
-///////////////////////////////////////////////////////////////////////////
 // senf::detail::PacketImpl
 
 prefix_ senf::detail::PacketImpl::~PacketImpl()
@@ -54,12 +43,6 @@ prefix_ senf::detail::PacketImpl::~PacketImpl()
     // We increment refcount_ to ensure, release() won't call delete again
     ++refcount_;
     eraseInterpreters(interpreters_.begin(), interpreters_.end());
-    Annotations::const_iterator  i (annotations_.begin());
-    Annotations::const_iterator const i_end (annotations_.end());
-    std::vector<bool>::iterator small (AnnotationIndexerBase::small().begin());
-    for (; i != i_end; ++i, ++small)
-        if (! *small && i->p)
-            delete i->p;
 }
 
 // interpreter chain
@@ -146,7 +129,60 @@ prefix_ void senf::detail::PacketImpl::updateIterators(PacketData * self, differ
         // else pos is after the packet and we don't need to change anything ...
 }
 
-///////////////////////////////cc.e////////////////////////////////////////
+// Annotations
+
+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));
+        if (antn)
+            AnnotationRegistry::instance().dump(key, os, antn);
+    }
+}
+
+prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_t 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();
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::AnnotationRegistry
+
+prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
+{
+#ifdef SENF_DEBUG
+    boost::format fmt ("%4.4s  %-56.56s  %-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));
+        if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
+        os << fmt
+            % (key >= 0 ? senf::str(key) : "")
+            % nm
+            % (isComplex(key) ? "yes" : "no")
+            % size(key);
+    }
+#endif
+}
+
+prefix_ void senf::dumpPacketAnnotationRegistry(std::ostream & os)
+{
+    senf::detail::AnnotationRegistry::instance().dumpRegistrations(os);
+}
+
+/////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "PacketImpl.mpp"
 
index 56e501b..8c863d1 100644 (file)
 ///////////////////////////////cci.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationIndexerBase
+// senf::detail::AnnotationRegistry
 
-prefix_ senf::detail::AnnotationIndexerBase::~AnnotationIndexerBase()
-{}
+prefix_ void senf::detail::AnnotationRegistry::dump(key_t key, std::ostream & os,
+                                                    void * annotation)
+    const
+{
+    Registry::const_iterator i (registry_.find(key));
+    if (i != registry_.end()) {
+        os << fieldName(i->second->v_name());
+        i->second->v_dump(os, annotation);
+        os << "\n";
+    }
+}
 
-prefix_ std::vector<bool> & senf::detail::AnnotationIndexerBase::small()
+prefix_ std::string senf::detail::AnnotationRegistry::name(key_t key)
+    const
 {
-    static std::vector<bool> smalls;
-    return smalls;
+    Registry::const_iterator i (registry_.find(key));
+    return i == registry_.end() ? "" : i->second->v_name();
 }
 
-prefix_ std::vector<senf::detail::AnnotationIndexerBase*> &
-senf::detail::AnnotationIndexerBase::registry()
+prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_t key)
+    const
 {
-    static std::vector<AnnotationIndexerBase*> reg;
-    return reg;
+    Registry::const_iterator i (registry_.find(key));
+    return i != registry_.end() && i->second->v_isComplex();
 }
 
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationP
+prefix_ unsigned senf::detail::AnnotationRegistry::size(key_t key)
+    const
+{
+    Registry::const_iterator i (registry_.find(key));
+    return i == registry_.end() ? 0 : i->second->v_size();
+}
 
-prefix_ senf::detail::AnnotationP::~AnnotationP()
+prefix_ senf::detail::AnnotationRegistry::AnnotationRegistry()
+    : simpleAnnotationCount_ (0), complexAnnotationCount_ (0)
 {}
 
+///////////////////////////////////////////////////////////////////////////
+
 // Memory management:
 //
 // * The PacketImpl destructor will *explicitly* clean-up the interpreters_ list by removing
@@ -82,12 +99,16 @@ prefix_ senf::detail::AnnotationP::~AnnotationP()
 // senf::detail::PacketImpl
 
 prefix_ senf::detail::PacketImpl::PacketImpl()
-    : refcount_(0), annotations_(AnnotationIndexerBase::maxAnnotations)
-{}
+    : refcount_(0)
+{
+    ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
+}
 
 prefix_ senf::detail::PacketImpl::PacketImpl(size_type size, byte initValue)
-    : refcount_(0), data_(size,initValue), annotations_(AnnotationIndexerBase::maxAnnotations)
-{}
+    : refcount_(0), data_(size,initValue)
+{
+    ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
+}
 
 // reference/memory management
 
@@ -196,11 +217,6 @@ prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::capacity()
     return data_.capacity();
 }
 
-prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
-{
-    AnnotationIndexerBase::dump(this, os);
-}
-
 // This function has a problem being inlined. Somehow, often when calling this, the size of the
 // resulting inlined code would be huge?
 
@@ -216,6 +232,12 @@ prefix_ void senf::detail::PacketImpl::release(refcount_t n)
         refcount_ -= n;
 }
 
+// Annotations
+
+prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_t key)
+{
+    return key >= 0 ? & simpleAnnotations_[key] : complexAnnotation(key);
+}
 
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::PacketImpl::Guard
diff --git a/senf/Packets/PacketImpl.ct b/senf/Packets/PacketImpl.ct
new file mode 100644 (file)
index 0000000..7dc7cb9
--- /dev/null
@@ -0,0 +1,67 @@
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief PacketImpl non-inline template implementation  */
+
+#include "PacketImpl.ih"
+
+// Custom includes
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+template <class Annotation>
+senf::detail::AnnotationRegistry::RegistrationProxy<Annotation>
+    senf::detail::AnnotationRegistry::Entry<Annotation>::proxy_;
+
+template <class Annotation>
+senf::detail::AnnotationRegistry::key_t
+    senf::detail::AnnotationRegistry::Entry<Annotation>::key_;
+
+template <class Annotation>
+prefix_ void * senf::detail::PacketImpl::complexAnnotation()
+{
+    AnnotationRegistry::key_t key (AnnotationRegistry::lookup<Annotation>());
+    void * rv (complexAnnotation(key));
+#ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
+    if (! rv) {
+        complexAnnotations_.replace(-key-1, new AnnotationRegistry::Entry<Annotation>());
+        rv = complexAnnotations_[-key-1].get();
+    }
+#endif
+    return rv;
+}
+
+///////////////////////////////ct.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index e3ec1ea..308e7b3 100644 (file)
@@ -23,7 +23,7 @@
 /** \file
     \brief PacketImpl inline template implementation */
 
-//#include "PacketImpl.ih"
+#include "PacketImpl.ih"
 
 // Custom includes
 
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationIndexer<Annotation>
+// senf::detail::AnnotationRegistry
 
 template <class Annotation>
-prefix_ senf::detail::AnnotationIndexer<Annotation>::AnnotationIndexer()
-    : index_ (maxAnnotations++)
+prefix_ key_t senf::detail::AnnotationRegistry::registerAnnotation()
 {
-    small().push_back(Small);
-    registry().push_back(this);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationIndexer<Annotation>
-
-
-template <class Annotation>
-prefix_ void senf::detail::AnnotationIndexer<Annotation>::v_dump(PacketImpl * p,
-                                                                 std::ostream & os)
-{
-
-    os << "  " << senf::prettyName(typeid(Annotation)) << ": ";
-    p->dumpAnnotation<Annotation>(os);
-    os << "\n";
+    key_t 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;
+    return key;
 }
 
 template <class Annotation>
-prefix_ unsigned senf::detail::AnnotationIndexer<Annotation>::index()
-{
-    return AnnotationIndexer::instance().index_;
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::GetAnnotation<Annotation,Small>
-
-template <class Annotation, bool Small>
-prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(AnnotationEntry & e)
-{
-    if (!e.p)
-        e.p = new TAnnotationP<Annotation>();
-    return static_cast< TAnnotationP<Annotation>* >(e.p)->annotation;
-}
-
-template <class Annotation, bool Small>
-prefix_ void senf::detail::GetAnnotation<Annotation,Small>::dump(AnnotationEntry & e,
-                                                                 std::ostream & os)
+prefix_ key_t senf::detail::AnnotationRegistry::lookup()
 {
-    if (!e.p) os << "no value";
-    else      os << get(e);
+    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" );
+    return AnnotationRegistry::Entry<Annotation>::key();
 }
 
-template <class Annotation>
-prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationEntry & e)
+prefix_ key_t senf::detail::AnnotationRegistry::keyBegin()
+    const
 {
-    return * static_cast<Annotation*>(static_cast<void*>(& e.i));
+    return -complexAnnotationCount_;
 }
 
-template <class Annotation>
-prefix_ void senf::detail::GetAnnotation<Annotation, true>::dump(AnnotationEntry & e,
-                                                                 std::ostream & os)
+prefix_ key_t senf::detail::AnnotationRegistry::keyEnd()
+    const
 {
-    os << get(e);
+    return simpleAnnotationCount_;
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -109,23 +92,20 @@ prefix_ void senf::detail::PacketImpl::insert(PacketData * self, iterator pos, F
 
 template <class InputIterator>
 prefix_ senf::detail::PacketImpl::PacketImpl(InputIterator first, InputIterator last)
-    : refcount_(0), data_(first,last), annotations_(AnnotationIndexerBase::maxAnnotations)
-{}
+    : refcount_(0), data_(first,last)
+{
+    ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
+}
 
 // Annotations
 
 template <class Annotation>
 prefix_ Annotation & senf::detail::PacketImpl::annotation()
 {
-    return GetAnnotation<Annotation>::get(
-        annotations_[AnnotationIndexer<Annotation>::index()]);
-}
-
-template <class Annotation>
-prefix_ void senf::detail::PacketImpl::dumpAnnotation(std::ostream & os)
-{
-    GetAnnotation<Annotation>::dump(
-        annotations_[AnnotationIndexer<Annotation>::index()], os);
+    AnnotationRegistry::key_t 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);
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 8c64647..3aa2964 100644 (file)
 #include <memory>
 #include <vector>
 #include <boost/utility.hpp>
-#include <boost/type_traits/is_base_of.hpp>
-#include <boost/type_traits/has_trivial_constructor.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
 #include <boost/static_assert.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <senf/Utils/pool_alloc_mixin.hh>
 #include <senf/Utils/singleton.hh>
 
 //#include "PacketImpl.mpp"
+#include "PacketImpl.ih"
 ///////////////////////////////hh.p////////////////////////////////////////
 
 namespace senf {
@@ -62,71 +61,6 @@ namespace senf {
 
 namespace detail {
 
-    struct AnnotationP
-    {
-        virtual ~AnnotationP();
-    };
-
-    template <class Annotation>
-    struct TAnnotationP
-        : public AnnotationP
-    {
-        Annotation annotation;
-    };
-
-    union AnnotationEntry {
-        AnnotationP * p;
-        unsigned long long i;
-    };
-
-    struct AnnotationIndexerBase
-    {
-        virtual ~AnnotationIndexerBase();
-        virtual void v_dump(PacketImpl * p, std::ostream & os) = 0;
-
-        static unsigned maxAnnotations;
-        static std::vector<bool> & small();
-        static std::vector<AnnotationIndexerBase*> & registry();
-        static void dump(PacketImpl * p, std::ostream & os);
-    };
-
-    template <class Annotation>
-    struct AnnotationIndexer
-        : public senf::singleton< AnnotationIndexer<Annotation> >,
-          public AnnotationIndexerBase
-    {
-        AnnotationIndexer();
-        virtual void v_dump(PacketImpl * p, std::ostream & os);
-        unsigned index_;
-        static unsigned index();
-        static bool const Complex = boost::is_base_of<ComplexAnnotation, Annotation>::value;
-        static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) && ! Complex);
-
-#       if 0 // The test is difficult since it does not work with user-defined trivial constructors
-#       ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
-
-        BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value
-                               && boost::has_trivial_destructor<Annotation>::value)
-                              || Complex ));
-
-#       endif
-#       endif
-    };
-
-    template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
-    struct GetAnnotation
-    {
-        static Annotation & get(AnnotationEntry & e);
-        static void dump(AnnotationEntry & e, std::ostream & os);
-    };
-
-    template <class Annotation>
-    struct GetAnnotation<Annotation, true>
-    {
-        static Annotation & get(AnnotationEntry & e);
-        static void dump(AnnotationEntry & e, std::ostream & os);
-    };
-
     /** \brief Internal: Packet data storage
 
         \internal
@@ -199,9 +133,8 @@ namespace detail {
         // Annotations
         template <class Annotation>
         Annotation & annotation();
+
         void dumpAnnotations(std::ostream & os);
-        template <class Annotation>
-        void dumpAnnotation(std::ostream & os);
 
         /** \brief Internal: Keep PacketImpl instance alive
 
@@ -218,15 +151,30 @@ namespace detail {
         };
 
     private:
+        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 !
+        template <class Annotation>
+        void * complexAnnotation();
+
         refcount_t refcount_;
         raw_container data_;
         interpreter_list interpreters_;
 
-        typedef std::vector<AnnotationEntry> Annotations;
-        Annotations annotations_;
+        union SimpleAnnotationSlot
+        {
+            unsigned char _ [SENF_PACKET_ANNOTATION_SLOTSIZE];
+        };
 
-        void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
-        void updateIterators(PacketData * self, difference_type pos, difference_type n);
+        typedef boost::ptr_vector< boost::nullable<AnnotationRegistry::EntryBase> >
+            ComplexAnnotations;
+#       ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
+            ComplexAnnotations complexAnnotations_;
+#       endif
+
+        SimpleAnnotationSlot simpleAnnotations_[SENF_PACKET_ANNOTATION_SLOTS];
     };
 
 }}
@@ -236,7 +184,7 @@ namespace detail {
 #if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
 #define HH_SENF_Packets_PacketImpl_i_
 #include "PacketImpl.cci"
-//#include "PacketImpl.ct"
+#include "PacketImpl.ct"
 #include "PacketImpl.cti"
 #endif
 
@@ -250,4 +198,3 @@ namespace detail {
 // compile-command: "scons -u test"
 // comment-column: 40
 // End:
-
diff --git a/senf/Packets/PacketImpl.ih b/senf/Packets/PacketImpl.ih
new file mode 100644 (file)
index 0000000..06cb708
--- /dev/null
@@ -0,0 +1,177 @@
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief PacketImpl internal header */
+
+#ifndef IH_SENF_senf_Packets_PacketImpl_
+#define IH_SENF_senf_Packets_PacketImpl_ 1
+
+// Custom includes
+#include <iostream>
+#include <string>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/mpl/sizeof.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/greater.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
+#include <senf/Utils/TypeInfo.hh>
+#include <senf/Utils/singleton.hh>
+#include <senf/config.hh>
+#include <senf/Utils/IgnoreValue.hh>
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+
+    struct ComplexAnnotation;
+    void dumpPacketAnnotationRegistry(std::ostream & os);
+
+namespace detail {
+
+    template <class Annotation>
+    struct IsComplexAnnotation
+        : public boost::mpl::or_< boost::is_convertible<Annotation*, ComplexAnnotation*>,
+                                  boost::mpl::greater<
+                                      boost::mpl::sizeof_<Annotation>,
+                                      boost::mpl::int_<SENF_PACKET_ANNOTATION_SLOTSIZE> > >
+    {};
+
+    class AnnotationRegistry
+        : 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);
+
+    private:
+        AnnotationRegistry();
+
+        struct RegistrationBase
+        {
+            virtual ~RegistrationBase () {};
+            key_t 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;
+            virtual unsigned v_size() const = 0;
+        };
+
+        template <class Annotation>
+        struct Registration
+            : public RegistrationBase
+        {
+            void v_dump(std::ostream & os, void * annotation) const
+                { os << * static_cast<Annotation*>(annotation); }
+            std::string v_name() const
+                { return prettyName(typeid(Annotation)); }
+            bool v_isComplex() const
+                { return boost::is_convertible<Annotation*, ComplexAnnotation*>::value; }
+            unsigned v_size() const
+                { return sizeof(Annotation); }
+        };
+
+        key_t simpleAnnotationCount_;
+        key_t complexAnnotationCount_;
+
+        typedef boost::ptr_map<key_t, RegistrationBase> Registry;
+        Registry registry_;
+
+        friend class senf::singleton<AnnotationRegistry>;
+    };
+
+    template <class Annotation>
+    class AnnotationRegistry::RegistrationProxy
+    {
+    public:
+        RegistrationProxy()
+            {
+                AnnotationRegistry::Entry<Annotation>::key_ =
+                    AnnotationRegistry::instance().registerAnnotation<Annotation>();
+            }
+    };
+
+    class AnnotationRegistry::EntryBase
+    {
+    public:
+        virtual ~EntryBase() {}
+
+        virtual void * get() = 0;
+    };
+
+    template <class Annotation>
+    class AnnotationRegistry::Entry
+        : public AnnotationRegistry::EntryBase
+    {
+        static RegistrationProxy<Annotation> proxy_;
+        static AnnotationRegistry::key_t key_;
+    public:
+        // We use this member to force instantiation of proxy_ ...
+        static AnnotationRegistry::key_t key()
+            { senf::IGNORE(&proxy_); return key_; }
+
+        virtual void * get() { return & annotation_; }
+
+    private:
+        Annotation annotation_;
+
+        friend class AnnotationRegistry::RegistrationProxy<Annotation>;
+    };
+
+}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
index 6305d93..bfaaa36 100644 (file)
@@ -30,6 +30,7 @@
 #include "Packets.hh"
 #include "main.test.hh"
 
+#include <sstream>
 #include <senf/Utils/auto_unit_test.hh>
 #include <boost/test/test_tools.hpp>
 
index 285ed9a..6fd279a 100644 (file)
@@ -75,7 +75,8 @@ prefix_ senf::PacketInterpreterBase::ptr senf::PacketInterpreterBase::append(ptr
 prefix_ void senf::PacketInterpreterBase::dump(std::ostream & os)
 {
     try {
-        if (detail::AnnotationIndexerBase::maxAnnotations > 0) {
+        if (detail::AnnotationRegistry::instance().keyBegin()
+            != detail::AnnotationRegistry::instance().keyEnd()) {
             os << "Annotations:\n";
             impl().dumpAnnotations(os);
         }
index b076e20..4dd5f02 100644 (file)
@@ -92,9 +92,12 @@ namespace config {
 #     define SENF_PACKET_ANNOTATION_SLOTS 8
 # endif
 #
+# ifndef SENF_PACKET_ANNOTATION_SLOTSIZE
+#     define SENF_PACKET_ANNOTATION_SLOTSIZE 16
+# endif
+#
 //# define SENF_PACKET_NO_COMPLEX_ANNOTATIONS
 
-
 ///////////////////////////////hh.e////////////////////////////////////////
 #endif