{
if (p.data().size() < initSize())
return no_factory();
- PkReg_Entry const * e (PacketRegistry<MIHMessageRegistry>::lookup( p->messageId(), nothrow ));
+ PacketRegistry<MIHMessageRegistry>::Entry const * e (
+ PacketRegistry<MIHMessageRegistry>::lookup( p->messageId(), nothrow ));
return e ? e->factory() : MIHGenericPayloadPacket::factory();
}
prefix_ senf::PacketInterpreterBase::factory_t senf::LlcSnapPacketType::nextPacketType(packet p)
{
if (p->type_length() >= 1536) {
- PkReg_Entry const * e;
- e = PacketRegistry<senf::EtherTypes>::lookup( p->type_length(), nothrow );
+ PacketRegistry<senf::EtherTypes>::Entry const * e (
+ PacketRegistry<senf::EtherTypes>::lookup( p->type_length(), nothrow ));
return e ? e->factory() : no_factory();
}
if (p->type_length() <= 1500)
{
if (p.data().size() < 8)
return no_factory();
- PkReg_Entry const * e;
- if (p->type() < 1536)
- e = PacketRegistry<senf::ULEExtHeaderTypes>::lookup( p->type(), nothrow );
- else
- e = PacketRegistry<senf::EtherTypes>::lookup( p->type(), nothrow );
- return e ? e->factory() : no_factory();
+ senf::PacketInterpreterBase::factory_t f (no_factory());
+ if (p->type() < 1536) {
+ PacketRegistry<senf::ULEExtHeaderTypes>::Entry const * e (
+ PacketRegistry<senf::ULEExtHeaderTypes>::lookup( p->type(), nothrow ));
+ if (e) f = e->factory();
+ }
+ else {
+ PacketRegistry<senf::EtherTypes>::Entry const * e (
+ PacketRegistry<senf::ULEExtHeaderTypes>::lookup( p->type(), nothrow ));
+ if (e) f = e->factory();
+ }
+ return f;
}
prefix_ senf::PacketInterpreterBase::optional_range
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ senf::PkReg_Entry::~PkReg_Entry()
-{}
-
prefix_ senf::detail::PacketRegistryImplBase::~PacketRegistryImplBase()
{}
///////////////////////////////ct.p////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::detail::PkReg_EntryImpl<PacketType>
+// senf::detail::PacketRegistryImpl<KeyType>::Entry
+template <class KeyType>
+prefix_ senf::detail::PacketRegistryImpl<KeyType>::Entry::Entry(KeyType const & key_,
+ int priority_)
+ : key (key_), priority (priority_)
+{}
+
+template <class KeyType>
+prefix_ senf::detail::PacketRegistryImpl<KeyType>::Entry::~Entry()
+{}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>
+
+template <class KeyType>
+template <class PacketType>
+prefix_ senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::
+EntryImpl(KeyType const & key, int priority)
+ : Entry (key, priority)
+{}
+
+template <class KeyType>
template <class PacketType>
-prefix_ senf::PacketInterpreterBase::factory_t senf::detail::PkReg_EntryImpl<PacketType>::factory()
+prefix_ senf::Packet::factory_t
+senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::factory()
const
{
return PacketType::factory();
}
+template <class KeyType>
template <class PacketType>
-prefix_ std::string senf::detail::PkReg_EntryImpl<PacketType>::name()
+prefix_ std::string senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::name()
const
{
return prettyName(typeid(PacketType));
}
+template <class KeyType>
template <class PacketType>
-prefix_ senf::TypeIdValue senf::detail::PkReg_EntryImpl<PacketType>::typeIdValue()
+prefix_ std::type_info const &
+senf::detail::PacketRegistryImpl<KeyType>::EntryImpl<PacketType>::type()
const
{
return typeid(PacketType);
template <class KeyType>
template <class PacketType>
-prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key)
-{
-#ifndef SENF_DEBUG
- registry_.insert(std::make_pair(key, Entry_ptr(new detail::PkReg_EntryImpl<PacketType>())));
- reverseRegistry_.insert(std::make_pair(senf::typeIdValue<PacketType>(), key));
-#else
- bool isUnique (
- registry_.insert(
- std::make_pair(key, Entry_ptr(new detail::PkReg_EntryImpl<PacketType>()))).second);
- // If this assertion fails, a Packet was registered with an already known key
- SENF_ASSERT( isUnique );
- bool isNew (
- reverseRegistry_.insert(
- std::make_pair(senf::typeIdValue<PacketType>(), key)).second);
- // If this assertion fails, the same Packet was registered with two different keys
- SENF_ASSERT( isNew );
-#endif
+prefix_ void senf::detail::PacketRegistryImpl<KeyType>::registerPacket(key_t key, int priority)
+{
+ SENF_ASSERT(registry_.insert(
+ typename Entry::ptr(new EntryImpl<PacketType>(key,priority))).second);
}
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);
+ registry_.template get<ByType>().erase(typeid(PacketType));
}
template <class KeyType>
-prefix_ void senf::detail::PacketRegistryImpl<KeyType>::unregisterPacket(key_t key)
+prefix_ void senf::detail::PacketRegistryImpl<KeyType>::unregisterPacket(key_t key, int priority)
{
- 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);
+ // Why doesn't this work:
+ // registry_.erase(boost::make_tuple(key,priority));
+ typename Registry::iterator i (registry_.find(boost::make_tuple(key,priority)));
+ if (i != registry_.end())
+ registry_.erase(i);
}
template <class KeyType>
prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::key_t
senf::detail::PacketRegistryImpl<KeyType>::key(senf::TypeIdValue const & type)
{
- typename ReversePacketMap::iterator i (reverseRegistry_.find(type));
- if (i==reverseRegistry_.end())
+ boost::optional<KeyType> k (key(type,true));
+ if (! k)
throw PacketTypeNotRegisteredException();
- return i->second;
+ return *k;
}
template <class KeyType>
prefix_ boost::optional<typename senf::detail::PacketRegistryImpl<KeyType>::key_t>
senf::detail::PacketRegistryImpl<KeyType>::key(senf::TypeIdValue const & type, bool)
{
- typename ReversePacketMap::iterator i (reverseRegistry_.find(type));
- if (i==reverseRegistry_.end())
+ typedef typename Registry::template index<ByType>::type TypeIndex;
+ TypeIndex const & typeIndex (registry_.template get<ByType>());
+ typename TypeIndex::const_iterator i (typeIndex.find(type.id()));
+ if (i == typeIndex.end())
return boost::optional<key_t>();
- return i->second;
+ return (*i)->key;
}
template <class KeyType>
prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::Entry const &
senf::detail::PacketRegistryImpl<KeyType>::lookup(key_t key)
{
- typename PacketMap::iterator i (registry_.find(key));
- if (i==registry_.end())
+ Entry const * e (lookup(key, true));
+ if (!e)
throw PacketTypeNotRegisteredException();
- return *(i->second);
+ return *e;
}
template <class KeyType>
prefix_ typename senf::detail::PacketRegistryImpl<KeyType>::Entry const *
senf::detail::PacketRegistryImpl<KeyType>::lookup(key_t key, bool)
{
- typename PacketMap::iterator i (registry_.find(key));
- if (i==registry_.end())
+ typedef typename Registry::template index<ByKey>::type KeyIndex;
+ KeyIndex const & keyIndex (registry_.template get<ByKey>());
+ typename KeyIndex::const_iterator i (keyIndex.lower_bound(key));
+ if (i == keyIndex.end() || (*i)->key != key)
return 0;
- return i->second.get();
+ return i->get();
}
template <class KeyType>
prefix_ void senf::detail::PacketRegistryImpl<KeyType>::v_dump(std::ostream & os)
const
{
- typename PacketMap::const_iterator i (registry_.begin());
- typename PacketMap::const_iterator const i_end (registry_.end());
- for (; i != i_end; ++i) {
- std::string n (i->second->name());
- senf::detail::DumpKey<KeyType>::dump(i->first, os);
- os << ' ' << n.substr(21,n.size()-22) << "\n";
+ typedef typename Registry::template index<ByKey>::type KeyIndex;
+ KeyIndex const & keyIndex (registry_.template get<ByKey>());
+ for (typename KeyIndex::iterator i (keyIndex.begin()), i_end (keyIndex.end());
+ i != i_end; ++i) {
+ std::string n ((*i)->name());
+ senf::detail::DumpKey<KeyType>::dump((*i)->key, os);
+ os << ' ' << std::setw(6) << (*i)->priority << ' ' << n.substr(21,n.size()-22) << '\n';
}
}
prefix_ void senf::detail::PacketRegistryImpl<KeyType>::v_clear()
{
registry_.clear();
- reverseRegistry_.clear();
}
///////////////////////////////////////////////////////////////////////////
}
template <class Tag>
-prefix_ senf::PkReg_Entry const & senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key)
+prefix_ typename senf::PacketRegistry<Tag>::Entry const &
+senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key)
{
return registry().lookup(key);
}
template <class Tag>
-prefix_ senf::PkReg_Entry const * senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key,
- NoThrow_t)
+prefix_ typename senf::PacketRegistry<Tag>::Entry const *
+senf::PacketRegistry<Tag>::lookup(typename Tag::key_t key, NoThrow_t)
{
return registry().lookup(key,true);
}
senf::detail::PacketRegistryImpl<KeyType>::begin()
const
{
- return boost::make_transform_iterator(
- registry_.begin(), ::__gnu_cxx::select1st<typename PacketMap::value_type>());
+ return registry_.begin();
}
template <class KeyType>
senf::detail::PacketRegistryImpl<KeyType>::end()
const
{
- return boost::make_transform_iterator(
- registry_.end(), ::__gnu_cxx::select1st<typename PacketMap::value_type>());
+ return registry_.end();
}
///////////////////////////////PacketRegistry..e///////////////////////////////////////
{
public:
typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::iterator iterator;
+ typedef typename detail::PacketRegistryImpl<typename Tag::key_t>::Entry Entry;
/** \brief Statically register a packet type in a PacketRegistry
\throws PacketTypeNotRegistered if the \a key is not found in the registry
\return %Packet entry for given \a key
*/
- static PkReg_Entry const & lookup(typename Tag::key_t key);
+ static Entry const & lookup(typename Tag::key_t key);
/** \brief Lookup a packet by it's key
\return Pointer to packet entry for given \a key or 0, if the key is not found in the
registry.
*/
- static PkReg_Entry const * lookup(typename Tag::key_t key, NoThrow_t);
+ static Entry const * lookup(typename Tag::key_t key, NoThrow_t);
/** \brief Beginning iterator to list of registered keys
*/
// Custom includes
#include <ext/functional>
#include <limits>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/composite_key.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/mem_fun.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <senf/Utils/TypeIdValue.hh>
///////////////////////////////ih.p////////////////////////////////////////
namespace senf {
-
- /** \brief Registry entry
-
- Value returned by a registry lookup
- */
- struct PkReg_Entry
- : public intrusive_refcount
- {
- virtual ~PkReg_Entry();
- 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 {
- /** \brief Internal: Registry entry implementation for a specific packet type
-
- \internal
- */
- template <class PacketType>
- struct PkReg_EntryImpl
- : public PkReg_Entry
+ struct TypeInfoCompare
{
- virtual Packet::factory_t factory() const;
- virtual std::string name() const;
- virtual TypeIdValue typeIdValue() const ;
+ bool operator()(std::type_info const & a, std::type_info const & b) const
+ { return a.before(b); }
};
/** \brief Internal: Registry implementation base-class and registry of registries
{
public:
typedef KeyType key_t;
- typedef PkReg_Entry Entry;
+
+ struct Entry : public intrusive_refcount
+ {
+ typedef boost::intrusive_ptr<Entry> ptr;
+
+ Entry(KeyType const & key_, int priority_);
+ virtual ~Entry();
+
+ virtual Packet::factory_t factory() const = 0;
+
+ virtual std::string name() const = 0;
+ virtual std::type_info const & type() const = 0;
+
+ KeyType key;
+ int priority;
+ };
private:
- typedef boost::intrusive_ptr<Entry> Entry_ptr;
- typedef std::map<key_t, Entry_ptr> PacketMap;
- typedef std::map<senf::TypeIdValue, key_t> ReversePacketMap;
+ struct ByKey {};
+ struct ByType {};
+
+ struct RegistryIndices
+ : public boost::multi_index::indexed_by<
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<ByKey>,
+ boost::multi_index::composite_key<
+ Entry,
+ boost::multi_index::member<Entry,KeyType,&Entry::key>,
+ boost::multi_index::member<Entry,int,&Entry::priority> >,
+ boost::multi_index::composite_key_compare<
+ std::less<KeyType>,
+ std::greater<int> > >,
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<ByType>,
+ boost::multi_index::mem_fun<Entry const,std::type_info const &,&Entry::type>,
+ TypeInfoCompare> >
+ {};
+
+ typedef boost::multi_index_container<typename Entry::ptr, RegistryIndices> Registry;
+
+ template <class PacketType>
+ struct EntryImpl : public Entry
+ {
+ EntryImpl(KeyType const & key, int priority);
+
+ virtual Packet::factory_t factory() const;
+ virtual std::string name() const;
+ virtual std::type_info const & type() const;
+ };
public:
///////////////////////////////////////////////////////////////////////////
// Types
- typedef boost::transform_iterator< ::__gnu_cxx::select1st<typename PacketMap::value_type>,
- typename PacketMap::const_iterator > iterator;
+ typedef typename Registry::template index<ByKey>::type::const_iterator iterator;
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///////////////////////////////////////////////////////////////////////////
template <class PacketType>
- void registerPacket(key_t key);
+ void registerPacket(key_t key, int priority=0);
template <class PacketType>
void unregisterPacket();
- void unregisterPacket(key_t key);
+ void unregisterPacket(key_t key, int priority=0);
key_t key(senf::TypeIdValue const & type);
boost::optional<key_t> key(senf::TypeIdValue const & type, bool);
virtual void v_dump(std::ostream & os) const;
virtual void v_clear();
- PacketMap registry_;
- ReversePacketMap reverseRegistry_;
+ Registry registry_;
};
template <class KeyType, bool is_integral=std::numeric_limits<KeyType>::is_integer>
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]) );
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ boost::make_transform_iterator(
+ PacketRegistry<BaseTag>::begin(),
+ boost::multi_index::member<senf::PacketRegistry<BaseTag>::Entry, unsigned,
+ &senf::PacketRegistry<BaseTag>::Entry::key>()),
+ boost::make_transform_iterator(
+ PacketRegistry<BaseTag>::end(),
+ boost::multi_index::member<senf::PacketRegistry<BaseTag>::Entry, unsigned,
+ &senf::PacketRegistry<BaseTag>::Entry::key>()),
+ 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]) );
+ BOOST_CHECK_EQUAL_COLLECTIONS(
+ boost::make_transform_iterator(
+ PacketRegistry<StringTag>::begin(),
+ boost::multi_index::member<senf::PacketRegistry<StringTag>::Entry, std::string,
+ &senf::PacketRegistry<StringTag>::Entry::key>()),
+ boost::make_transform_iterator(
+ PacketRegistry<StringTag>::end(),
+ boost::multi_index::member<senf::PacketRegistry<StringTag>::Entry, std::string,
+ &senf::PacketRegistry<StringTag>::Entry::key>()),
+ elts2+0, elts2+sizeof(elts2)/sizeof(elts2[0]) );
std::stringstream s;
senf::dumpPacketRegistries(s);
contains,
(s.str())
("(anonymous namespace)::BaseTag:\n"
- " 0x00000001 ( 1) (....) (anonymous namespace)::FooPacketType\n"
- " 0x00000002 ( 2) (....) (anonymous namespace)::BarPacketType\n"
+ " 0x00000001 ( 1) (....) 0 (anonymous namespace)::FooPacketType\n"
+ " 0x00000002 ( 2) (....) 0 (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"
+ " bar 0 (anonymous namespace)::BarPacketType\n"
+ " foo 0 (anonymous namespace)::FooPacketType\n"
"\n" ));
}
contains,
(s.str())
("(anonymous namespace)::BaseTag:\n"
- " 0x00000001 ( 1) (....) (anonymous namespace)::FooPacketType\n"
+ " 0x00000001 ( 1) (....) 0 (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"
+ " bar 0 (anonymous namespace)::BarPacketType\n"
+ " foo 0 (anonymous namespace)::FooPacketType\n"
"\n" ));
SENF_CHECK_NO_THROW( PacketRegistry<BaseTag>::unregisterPacket(1u) );
contains,
(s.str())
("(anonymous namespace)::StringTag:\n"
- " foo (anonymous namespace)::FooPacketType\n"
+ " foo 0 (anonymous namespace)::FooPacketType\n"
"\n" ));
}
}
template <class Self, class Registry>
prefix_ senf::PacketTypeBase::factory_t senf::PacketTypeMixin<Self,Registry>::lookup(key_t key)
{
- PkReg_Entry const * entry (PacketRegistry<Registry>::lookup( key, senf::nothrow ));
+ typename PacketRegistry<Registry>::Entry const * entry (
+ PacketRegistry<Registry>::lookup( key, senf::nothrow ));
return entry ? entry->factory() : PacketTypeBase::no_factory();
}