From: g0dil Date: Wed, 11 Aug 2010 14:08:19 +0000 (+0000) Subject: Packets: New Annotation implementation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=943a6b0973f66bc699c6e7b404da256145e93acf;p=senf.git Packets: New Annotation implementation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1675 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/Packets/Packet.test.cc b/senf/Packets/Packet.test.cc index a8cba98..5b318d1 100644 --- a/senf/Packets/Packet.test.cc +++ b/senf/Packets/Packet.test.cc @@ -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()->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().s, "dead beef" ); BOOST_CHECK_EQUAL( p2.annotation().i, 0x12345678 ); - BOOST_CHECK( senf::detail::AnnotationIndexer::Small ); - BOOST_CHECK( ! senf::detail::AnnotationIndexer::Small ); - BOOST_CHECK( ! senf::detail::AnnotationIndexer::Small ); - BOOST_CHECK( ! senf::detail::AnnotationIndexer::Small ); + BOOST_CHECK( Reg::lookup() >= 0 ); + BOOST_CHECK( Reg::lookup() < 0 ); + BOOST_CHECK( Reg::lookup() < 0 ); + BOOST_CHECK( Reg::lookup() < 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 diff --git a/senf/Packets/PacketImpl.cc b/senf/Packets/PacketImpl.cc index 4639a05..4bb7eee 100644 --- a/senf/Packets/PacketImpl.cc +++ b/senf/Packets/PacketImpl.cc @@ -23,10 +23,12 @@ /** \file \brief PacketImpl non-inline non-template implementation */ -//#include "PacketImpl.ih" +#include "PacketImpl.ih" // Custom includes #include +#include +#include #include "Packets.hh" //#include "PacketImpl.mpp" @@ -34,19 +36,6 @@ ///////////////////////////////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::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::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" diff --git a/senf/Packets/PacketImpl.cci b/senf/Packets/PacketImpl.cci index 56e501b..8c863d1 100644 --- a/senf/Packets/PacketImpl.cci +++ b/senf/Packets/PacketImpl.cci @@ -31,30 +31,47 @@ ///////////////////////////////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 & senf::detail::AnnotationIndexerBase::small() +prefix_ std::string senf::detail::AnnotationRegistry::name(key_t key) + const { - static std::vector smalls; - return smalls; + Registry::const_iterator i (registry_.find(key)); + return i == registry_.end() ? "" : i->second->v_name(); } -prefix_ std::vector & -senf::detail::AnnotationIndexerBase::registry() +prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_t key) + const { - static std::vector 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 index 0000000..7dc7cb9 --- /dev/null +++ b/senf/Packets/PacketImpl.ct @@ -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 +// +// 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 +senf::detail::AnnotationRegistry::RegistrationProxy + senf::detail::AnnotationRegistry::Entry::proxy_; + +template +senf::detail::AnnotationRegistry::key_t + senf::detail::AnnotationRegistry::Entry::key_; + +template +prefix_ void * senf::detail::PacketImpl::complexAnnotation() +{ + AnnotationRegistry::key_t key (AnnotationRegistry::lookup()); + void * rv (complexAnnotation(key)); +#ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS + if (! rv) { + complexAnnotations_.replace(-key-1, new AnnotationRegistry::Entry()); + rv = complexAnnotations_[-key-1].get(); + } +#endif + return rv; +} + +///////////////////////////////ct.e//////////////////////////////////////// +#undef prefix_ + + +// 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: diff --git a/senf/Packets/PacketImpl.cti b/senf/Packets/PacketImpl.cti index e3ec1ea..308e7b3 100644 --- a/senf/Packets/PacketImpl.cti +++ b/senf/Packets/PacketImpl.cti @@ -23,7 +23,7 @@ /** \file \brief PacketImpl inline template implementation */ -//#include "PacketImpl.ih" +#include "PacketImpl.ih" // Custom includes @@ -31,66 +31,49 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::detail::AnnotationIndexer +// senf::detail::AnnotationRegistry template -prefix_ senf::detail::AnnotationIndexer::AnnotationIndexer() - : index_ (maxAnnotations++) +prefix_ key_t senf::detail::AnnotationRegistry::registerAnnotation() { - small().push_back(Small); - registry().push_back(this); -} - -/////////////////////////////////////////////////////////////////////////// -// senf::detail::AnnotationIndexer - - -template -prefix_ void senf::detail::AnnotationIndexer::v_dump(PacketImpl * p, - std::ostream & os) -{ - - os << " " << senf::prettyName(typeid(Annotation)) << ": "; - p->dumpAnnotation(os); - os << "\n"; + key_t key (simpleAnnotationCount_ >= SENF_PACKET_ANNOTATION_SLOTS + || IsComplexAnnotation::value + ? - ++complexAnnotationCount_ + : simpleAnnotationCount_ ++); + registry_.insert(key, new Registration()); + std::cerr << ">> allocated key " << key + << " for " << prettyName(typeid(Annotation)) + << "(complex: " << IsComplexAnnotation::value + << ", convertible: " << boost::is_convertible::value + << ", size: " << sizeof(Annotation) + << ", max: " << SENF_PACKET_ANNOTATION_SLOTSIZE << ")" << std::endl; + return key; } template -prefix_ unsigned senf::detail::AnnotationIndexer::index() -{ - return AnnotationIndexer::instance().index_; -} - -/////////////////////////////////////////////////////////////////////////// -// senf::detail::GetAnnotation - -template -prefix_ Annotation & senf::detail::GetAnnotation::get(AnnotationEntry & e) -{ - if (!e.p) - e.p = new TAnnotationP(); - return static_cast< TAnnotationP* >(e.p)->annotation; -} - -template -prefix_ void senf::detail::GetAnnotation::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::key() + && AnnotationRegistry::Entry::key() < instance().keyEnd(), + "internal error: annotation key not registered" ); + SENF_ASSERT( AnnotationRegistry::Entry::key() < 0 + || ! IsComplexAnnotation::value, + "internal error: complex annotation registered with invalid key" ); + SENF_ASSERT( AnnotationRegistry::Entry::key() < SENF_PACKET_ANNOTATION_SLOTS, + "internal error: annotation key out of valid range" ); + return AnnotationRegistry::Entry::key(); } -template -prefix_ Annotation & senf::detail::GetAnnotation::get(AnnotationEntry & e) +prefix_ key_t senf::detail::AnnotationRegistry::keyBegin() + const { - return * static_cast(static_cast(& e.i)); + return -complexAnnotationCount_; } -template -prefix_ void senf::detail::GetAnnotation::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 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 prefix_ Annotation & senf::detail::PacketImpl::annotation() { - return GetAnnotation::get( - annotations_[AnnotationIndexer::index()]); -} - -template -prefix_ void senf::detail::PacketImpl::dumpAnnotation(std::ostream & os) -{ - GetAnnotation::dump( - annotations_[AnnotationIndexer::index()], os); + AnnotationRegistry::key_t key (AnnotationRegistry::lookup()); + void * antn (key >= 0 ? & simpleAnnotations_[key] : complexAnnotation()); + SENF_ASSERT( antn, "internal error: null annotation pointer" ); + return * static_cast(antn); } ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/senf/Packets/PacketImpl.hh b/senf/Packets/PacketImpl.hh index 8c64647..3aa2964 100644 --- a/senf/Packets/PacketImpl.hh +++ b/senf/Packets/PacketImpl.hh @@ -30,14 +30,13 @@ #include #include #include -#include -#include -#include #include +#include #include #include //#include "PacketImpl.mpp" +#include "PacketImpl.ih" ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { @@ -62,71 +61,6 @@ namespace senf { namespace detail { - struct AnnotationP - { - virtual ~AnnotationP(); - }; - - template - 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 & small(); - static std::vector & registry(); - static void dump(PacketImpl * p, std::ostream & os); - }; - - template - struct AnnotationIndexer - : public senf::singleton< AnnotationIndexer >, - 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::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::value - && boost::has_trivial_destructor::value) - || Complex )); - -# endif -# endif - }; - - template ::Small> - struct GetAnnotation - { - static Annotation & get(AnnotationEntry & e); - static void dump(AnnotationEntry & e, std::ostream & os); - }; - - template - struct GetAnnotation - { - 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 Annotation & annotation(); + void dumpAnnotations(std::ostream & os); - template - 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 + void * complexAnnotation(); + refcount_t refcount_; raw_container data_; interpreter_list interpreters_; - typedef std::vector 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 > + 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 index 0000000..06cb708 --- /dev/null +++ b/senf/Packets/PacketImpl.ih @@ -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 +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////////////////ih.p//////////////////////////////////////// + +namespace senf { + + struct ComplexAnnotation; + void dumpPacketAnnotationRegistry(std::ostream & os); + +namespace detail { + + template + struct IsComplexAnnotation + : public boost::mpl::or_< boost::is_convertible, + boost::mpl::greater< + boost::mpl::sizeof_, + boost::mpl::int_ > > + {}; + + class AnnotationRegistry + : public senf::singleton + { + public: + typedef int key_t; + + using senf::singleton::instance; + + template class RegistrationProxy; + + class EntryBase; + template class Entry; + + template + 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 + 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 + struct Registration + : public RegistrationBase + { + void v_dump(std::ostream & os, void * annotation) const + { os << * static_cast(annotation); } + std::string v_name() const + { return prettyName(typeid(Annotation)); } + bool v_isComplex() const + { return boost::is_convertible::value; } + unsigned v_size() const + { return sizeof(Annotation); } + }; + + key_t simpleAnnotationCount_; + key_t complexAnnotationCount_; + + typedef boost::ptr_map Registry; + Registry registry_; + + friend class senf::singleton; + }; + + template + class AnnotationRegistry::RegistrationProxy + { + public: + RegistrationProxy() + { + AnnotationRegistry::Entry::key_ = + AnnotationRegistry::instance().registerAnnotation(); + } + }; + + class AnnotationRegistry::EntryBase + { + public: + virtual ~EntryBase() {} + + virtual void * get() = 0; + }; + + template + class AnnotationRegistry::Entry + : public AnnotationRegistry::EntryBase + { + static RegistrationProxy 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; + }; + +}} + +///////////////////////////////ih.e//////////////////////////////////////// +#endif + + +// 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: diff --git a/senf/Packets/PacketImpl.test.cc b/senf/Packets/PacketImpl.test.cc index 6305d93..bfaaa36 100644 --- a/senf/Packets/PacketImpl.test.cc +++ b/senf/Packets/PacketImpl.test.cc @@ -30,6 +30,7 @@ #include "Packets.hh" #include "main.test.hh" +#include #include #include diff --git a/senf/Packets/PacketInterpreter.cc b/senf/Packets/PacketInterpreter.cc index 285ed9a..6fd279a 100644 --- a/senf/Packets/PacketInterpreter.cc +++ b/senf/Packets/PacketInterpreter.cc @@ -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); } diff --git a/senf/config.hh b/senf/config.hh index b076e20..4dd5f02 100644 --- a/senf/config.hh +++ b/senf/config.hh @@ -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