implement new tag identification scheme

This commit is contained in:
Mathieu Lacage
2006-09-15 13:05:03 +02:00
parent 3e88c0eb3a
commit bd97522a7c
3 changed files with 87 additions and 89 deletions

View File

@@ -72,6 +72,8 @@ struct MyTag {
uint16_t m_streamId;
};
static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
static void
receive (Packet p)

View File

@@ -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 ()

View File

@@ -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;