From bd97522a7c4ff9f028a6e64432f7fcaad5d41a68 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Fri, 15 Sep 2006 13:05:03 +0200 Subject: [PATCH] implement new tag identification scheme --- samples/main-packet.cc | 2 + src/common/tags.cc | 74 +++++++++++++++--------------- src/common/tags.h | 100 ++++++++++++++++++++--------------------- 3 files changed, 87 insertions(+), 89 deletions(-) diff --git a/samples/main-packet.cc b/samples/main-packet.cc index 6cabdb233..e4b6ef2f1 100644 --- a/samples/main-packet.cc +++ b/samples/main-packet.cc @@ -72,6 +72,8 @@ struct MyTag { uint16_t m_streamId; }; +static TagRegistration g_MyTagRegistration ("ns3::MyTag", 0); + static void receive (Packet p) diff --git a/src/common/tags.cc b/src/common/tags.cc index 2342fa509..b9e6927fc 100644 --- a/src/common/tags.cc +++ b/src/common/tags.cc @@ -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="<second)) (buf, os); - } - return; - } - } - os << "tag uid="< 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 gMyTagAPrettyPrinter (&myTagAPrettyPrinterCb); -static TagPrettyPrinter gMyTagBPrettyPrinter (&myTagBPrettyPrinterCb); -static TagPrettyPrinter gMyTagCPrettyPrinter (&myTagCPrettyPrinterCb); +static TagRegistration gMyTagARegistration ("A", &myTagAPrettyPrinterCb); +static TagRegistration gMyTagBRegistration ("B", &myTagBPrettyPrinterCb); +static TagRegistration gMyTagCRegistration ("C", &myTagCPrettyPrinterCb); TagsTest::TagsTest () diff --git a/src/common/tags.h b/src/common/tags.h index ae5a38fdd..aabca1a6c 100644 --- a/src/common/tags.h +++ b/src/common/tags.h @@ -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 -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 (void(*fn) (T *, std::ostream &)); + TagRegistration (std::string uuid, void(*fn) (T *, std::ostream &)); private: - TagPrettyPrinter (); - 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 -#include +#include 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 > PrettyPrinters; - typedef std::vector >::iterator PrettyPrintersI; - static PrettyPrinters gPrettyPrinters; + typedef std::vector > TagsData; + typedef std::vector >::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 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 +void TypeUid::record (std::string uuid) +{ + *(getUuid ()) = uuid; +} + template const uint32_t TypeUid::getUid (void) { - static const uint32_t uid = Tags::UidFactory::create (); + static const uint32_t uid = TagRegistry::lookupUid (*(getUuid ())); return uid; } +template +std::string *TypeUid::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 -TagPrettyPrinter::TagPrettyPrinter (void(*prettyPrinter) (T *, std::ostream &)) +TagRegistration::TagRegistration (std::string uuid, void (*prettyPrinter) (T *, std::ostream &)) { assert (sizeof (T) <= Tags::SIZE); - gPrettyPrinter = prettyPrinter; - TagsPrettyPrinterRegistry::record (TypeUid::getUid (), - &TagPrettyPrinter::prettyPrintCb); + m_prettyPrinter = prettyPrinter; + TagRegistry::record (uuid, &TagRegistration::prettyPrinterCb); + TypeUid::record (uuid); } template void -TagPrettyPrinter::prettyPrintCb (uint8_t *buf, std::ostream &os) +TagRegistration::prettyPrinterCb (uint8_t *buf, std::ostream &os) { assert (sizeof (T) <= Tags::SIZE); T *tag = reinterpret_cast (buf); - (*gPrettyPrinter) (tag, os); + (*m_prettyPrinter) (tag, os); } template -void (*TagPrettyPrinter::gPrettyPrinter) (T *, std::ostream &) = 0; +void (*TagRegistration::m_prettyPrinter) (T *, std::ostream &) = 0;