// Custom includes
#include <sstream>
#include <boost/static_assert.hpp>
+#include <boost/cstdint.hpp>
#include "Packets.hh"
#include <senf/Utils/auto_unit_test.hh>
}
struct IntAnnotation {
- unsigned value;
+ boost::uint32_t value;
};
std::ostream & operator<<(std::ostream & os, IntAnnotation const & v)
{
ComplexAnnotation() : s(), i() {}
std::string s;
- int i;
+ boost::int32_t i;
};
std::ostream & operator<<(std::ostream & os, ComplexAnnotation const & v)
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
}
// Custom includes
#include <iterator>
+#include <map>
+#include <string>
#include <boost/format.hpp>
#include <senf/Utils/String.hh>
#include "Packets.hh"
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
}
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);
}
///////////////////////////////////////////////////////////////////////////
// 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
{
}
}
-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)
{}
// 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);
}
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();
}
// 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
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);
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();
// 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>
: 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;
{ 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>;
};
: 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_; }
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);
}