implement new tag identification scheme
This commit is contained in:
@@ -72,6 +72,8 @@ struct MyTag {
|
||||
uint16_t m_streamId;
|
||||
};
|
||||
|
||||
static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
|
||||
|
||||
|
||||
static void
|
||||
receive (Packet p)
|
||||
|
||||
@@ -23,45 +23,45 @@
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
TagsPrettyPrinterRegistry::PrettyPrinters TagsPrettyPrinterRegistry::gPrettyPrinters;
|
||||
bool TagRegistry::m_sorted;
|
||||
TagRegistry::TagsData TagRegistry::m_registry;
|
||||
|
||||
|
||||
void
|
||||
TagsPrettyPrinterRegistry::record (uint32_t uid, void (*cb) (uint8_t [Tags::SIZE], std::ostream &))
|
||||
TagRegistry::record (std::string uuid, PrettyPrinter prettyPrinter)
|
||||
{
|
||||
for (PrettyPrintersI i = gPrettyPrinters.begin ();
|
||||
i != gPrettyPrinters.end (); i++) {
|
||||
if (i->first == uid) {
|
||||
i->second = cb;
|
||||
return;
|
||||
}
|
||||
}
|
||||
gPrettyPrinters.push_back (std::make_pair (uid, cb));
|
||||
assert (!m_sorted);
|
||||
m_registry.push_back (make_pair (uuid, prettyPrinter));
|
||||
}
|
||||
uint32_t
|
||||
TagRegistry::lookupUid (std::string uuid)
|
||||
{
|
||||
if (!m_sorted) {
|
||||
std::sort (m_registry.begin (), m_registry.end ());
|
||||
m_sorted = true;
|
||||
}
|
||||
assert (m_sorted);
|
||||
uint32_t uid = 0;
|
||||
for (TagsDataCI i = m_registry.begin (); i != m_registry.end (); i++) {
|
||||
if (i->first == uuid) {
|
||||
return uid;
|
||||
}
|
||||
uid++;
|
||||
}
|
||||
// someone asked for a uid for an unregistered uuid.
|
||||
bool tried_to_use_unregistered_tag = false;
|
||||
assert (tried_to_use_unregistered_tag);
|
||||
// quiet compiler
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
TagsPrettyPrinterRegistry::prettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
|
||||
TagRegistry::prettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
|
||||
{
|
||||
for (PrettyPrintersI i = gPrettyPrinters.begin ();
|
||||
i != gPrettyPrinters.end (); i++) {
|
||||
if (i->first == uid) {
|
||||
if (i->second == 0) {
|
||||
os << "tag uid="<<uid<<" null pretty printer."<<std::endl;
|
||||
} else {
|
||||
(*(i->second)) (buf, os);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
os << "tag uid="<<uid<<" no pretty printer registered."<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t
|
||||
Tags::UidFactory::create (void)
|
||||
{
|
||||
static uint32_t uid = 0;
|
||||
uid++;
|
||||
return uid;
|
||||
assert (m_registry.size () > uid);
|
||||
PrettyPrinter prettyPrinter = m_registry[uid].second;
|
||||
if (prettyPrinter != 0) {
|
||||
prettyPrinter (buf, os);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ void
|
||||
Tags::prettyPrint (std::ostream &os)
|
||||
{
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) {
|
||||
TagsPrettyPrinterRegistry::prettyPrint (cur->m_id, cur->m_data, os);
|
||||
TagRegistry::prettyPrint (cur->m_id, cur->m_data, os);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,9 +205,9 @@ myTagCPrettyPrinterCb (struct myTagC *c, std::ostream &os)
|
||||
}
|
||||
|
||||
|
||||
static TagPrettyPrinter<struct myTagA> gMyTagAPrettyPrinter (&myTagAPrettyPrinterCb);
|
||||
static TagPrettyPrinter<struct myTagB> gMyTagBPrettyPrinter (&myTagBPrettyPrinterCb);
|
||||
static TagPrettyPrinter<struct myTagC> gMyTagCPrettyPrinter (&myTagCPrettyPrinterCb);
|
||||
static TagRegistration<struct myTagA> gMyTagARegistration ("A", &myTagAPrettyPrinterCb);
|
||||
static TagRegistration<struct myTagB> gMyTagBRegistration ("B", &myTagBPrettyPrinterCb);
|
||||
static TagRegistration<struct myTagC> gMyTagCRegistration ("C", &myTagCPrettyPrinterCb);
|
||||
|
||||
|
||||
TagsTest::TagsTest ()
|
||||
|
||||
@@ -60,10 +60,6 @@ private:
|
||||
uint32_t m_count;
|
||||
uint8_t m_data[Tags::SIZE];
|
||||
};
|
||||
class UidFactory {
|
||||
public:
|
||||
static uint32_t create (void);
|
||||
};
|
||||
|
||||
bool remove (uint32_t id);
|
||||
struct Tags::TagData *allocData (void);
|
||||
@@ -82,23 +78,20 @@ private:
|
||||
* callback function to print in a nice user-friendly
|
||||
* way the content of the target type. To register
|
||||
* such a type, all you need to do is instantiate
|
||||
* an instance of this type any number of times (at
|
||||
* least once). Typical users will create static global
|
||||
* variable of this type and construct it with
|
||||
* the proper function pointer.
|
||||
* an instance of this type as a static variable.
|
||||
*/
|
||||
template <typename T>
|
||||
class TagPrettyPrinter {
|
||||
class TagRegistration {
|
||||
public:
|
||||
/**
|
||||
* \param uuid a uuid generated with uuidgen
|
||||
* \param fn a function which can pretty-print an instance
|
||||
* of type T in the output stream.
|
||||
*/
|
||||
TagPrettyPrinter<T> (void(*fn) (T *, std::ostream &));
|
||||
TagRegistration<T> (std::string uuid, void(*fn) (T *, std::ostream &));
|
||||
private:
|
||||
TagPrettyPrinter<T> ();
|
||||
static void prettyPrintCb (uint8_t *buf, std::ostream &os);
|
||||
static void(*gPrettyPrinter) (T *, std::ostream &);
|
||||
static void prettyPrinterCb (uint8_t *buf, std::ostream &os);
|
||||
static void(*m_prettyPrinter) (T *, std::ostream &);
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
@@ -109,84 +102,87 @@ private:
|
||||
An implementation of the templates defined above
|
||||
*************************************************************/
|
||||
#include <cassert>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class holds a type <--> pretty_printer_cb mapping
|
||||
*/
|
||||
class TagsPrettyPrinterRegistry {
|
||||
class TagRegistry {
|
||||
public:
|
||||
static void record (uint32_t uid, void (*cb) (uint8_t buf[Tags::SIZE], std::ostream &os));
|
||||
static void prettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
|
||||
typedef void (*PrettyPrinter) (uint8_t [Tags::SIZE], std::ostream &);
|
||||
static void record (std::string uuid, PrettyPrinter prettyPrinter);
|
||||
static uint32_t lookupUid (std::string uuid);
|
||||
static void prettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
|
||||
private:
|
||||
typedef std::vector<std::pair<uint32_t, void (*) (uint8_t [Tags::SIZE], std::ostream &)> > PrettyPrinters;
|
||||
typedef std::vector<std::pair<uint32_t, void (*) (uint8_t [Tags::SIZE], std::ostream &)> >::iterator PrettyPrintersI;
|
||||
static PrettyPrinters gPrettyPrinters;
|
||||
typedef std::vector<std::pair<std::string,PrettyPrinter> > TagsData;
|
||||
typedef std::vector<std::pair<std::string,PrettyPrinter> >::const_iterator TagsDataCI;
|
||||
static bool m_sorted;
|
||||
static TagsData m_registry;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The TypeUid class is used to create a mapping Type --> uid
|
||||
* Of course, this class is not perfect: the value of the uid
|
||||
* associated to a given type could change accross multiple
|
||||
* runs of the same program on the same platform or accross
|
||||
* multiple platforms. There exist no generic portable
|
||||
* workaround/solution to this problem also known as
|
||||
* "type id management". The only other reliable solution
|
||||
* is to ask programmers to assign themselves a uid to each
|
||||
* type but this is painful from a management perspective.
|
||||
*
|
||||
* So, for now, this class is good enough provided you do
|
||||
* not try to serialize to permanent storage the type uids
|
||||
* generated by this class. Just don't try to do it. It might
|
||||
* seem to work but it will fail spectacularily in certain
|
||||
* use-cases and you will cry from debugging this. Hear me ?
|
||||
* Note that we use a static getUuid function which contains a
|
||||
* static std::string variable rather than a simpler static
|
||||
* member std::string variable to ensure the proper order
|
||||
* of initialization when these methods are invoked
|
||||
* from the constructor of another static variable.
|
||||
*/
|
||||
template <typename T>
|
||||
class TypeUid {
|
||||
public:
|
||||
static const uint32_t getUid (void);
|
||||
static void record (std::string uuid);
|
||||
static const uint32_t getUid (void);
|
||||
private:
|
||||
T realType;
|
||||
static std::string *getUuid (void);
|
||||
T m_realType;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void TypeUid<T>::record (std::string uuid)
|
||||
{
|
||||
*(getUuid ()) = uuid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const uint32_t TypeUid<T>::getUid (void)
|
||||
{
|
||||
static const uint32_t uid = Tags::UidFactory::create ();
|
||||
static const uint32_t uid = TagRegistry::lookupUid (*(getUuid ()));
|
||||
return uid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string *TypeUid<T>::getUuid (void)
|
||||
{
|
||||
static std::string uuid;
|
||||
return &uuid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of the TagPrettyPrinter registration class.
|
||||
* It records a callback with the TagPrettyPrinterRegistry.
|
||||
* Implementation of the TagRegistration registration class.
|
||||
* It records a callback with the TagRegistry
|
||||
* This callback performs type conversion before forwarding
|
||||
* the call to the user-provided function.
|
||||
*/
|
||||
template <typename T>
|
||||
TagPrettyPrinter<T>::TagPrettyPrinter (void(*prettyPrinter) (T *, std::ostream &))
|
||||
TagRegistration<T>::TagRegistration (std::string uuid, void (*prettyPrinter) (T *, std::ostream &))
|
||||
{
|
||||
assert (sizeof (T) <= Tags::SIZE);
|
||||
gPrettyPrinter = prettyPrinter;
|
||||
TagsPrettyPrinterRegistry::record (TypeUid<T>::getUid (),
|
||||
&TagPrettyPrinter<T>::prettyPrintCb);
|
||||
m_prettyPrinter = prettyPrinter;
|
||||
TagRegistry::record (uuid, &TagRegistration<T>::prettyPrinterCb);
|
||||
TypeUid<T>::record (uuid);
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
TagPrettyPrinter<T>::prettyPrintCb (uint8_t *buf, std::ostream &os)
|
||||
TagRegistration<T>::prettyPrinterCb (uint8_t *buf, std::ostream &os)
|
||||
{
|
||||
assert (sizeof (T) <= Tags::SIZE);
|
||||
T *tag = reinterpret_cast<T *> (buf);
|
||||
(*gPrettyPrinter) (tag, os);
|
||||
(*m_prettyPrinter) (tag, os);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void (*TagPrettyPrinter<T>::gPrettyPrinter) (T *, std::ostream &) = 0;
|
||||
void (*TagRegistration<T>::m_prettyPrinter) (T *, std::ostream &) = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user